ibm_db 2.5.26-universal-darwin-14 → 2.6.1-universal-darwin-14
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.
- checksums.yaml +4 -4
- data/CHANGES +11 -0
- data/MANIFEST +14 -14
- data/README +225 -225
- data/ext/Makefile.nt32 +181 -181
- data/ext/Makefile.nt32.191 +212 -212
- data/ext/extconf.rb +264 -261
- data/ext/extconf_MacOS.rb +269 -0
- data/ext/ibm_db.c +11879 -11793
- data/ext/ruby_ibm_db.h +241 -240
- data/ext/ruby_ibm_db_cli.c +851 -845
- data/ext/ruby_ibm_db_cli.h +500 -489
- data/init.rb +41 -41
- data/lib/IBM_DB.rb +27 -19
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3339 -3289
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
- data/test/cases/adapter_test.rb +207 -207
- data/test/cases/associations/belongs_to_associations_test.rb +711 -711
- data/test/cases/associations/cascaded_eager_loading_test.rb +181 -181
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -851
- data/test/cases/associations/join_model_test.rb +743 -743
- data/test/cases/attribute_methods_test.rb +822 -822
- data/test/cases/base_test.rb +2133 -2133
- data/test/cases/calculations_test.rb +482 -482
- data/test/cases/migration_test.rb +2408 -2408
- data/test/cases/persistence_test.rb +642 -642
- data/test/cases/query_cache_test.rb +257 -257
- data/test/cases/relations_test.rb +1182 -1182
- data/test/cases/schema_dumper_test.rb +256 -256
- data/test/cases/transaction_callbacks_test.rb +300 -300
- data/test/cases/validations/uniqueness_validation_test.rb +299 -299
- data/test/cases/xml_serialization_test.rb +408 -408
- data/test/config.yml +154 -154
- data/test/connections/native_ibm_db/connection.rb +43 -43
- data/test/ibm_db_test.rb +24 -24
- data/test/models/warehouse_thing.rb +4 -4
- data/test/schema/schema.rb +751 -751
- metadata +6 -8
- data/lib/linux/rb18x/ibm_db.bundle +0 -0
- data/lib/linux/rb19x/ibm_db.bundle +0 -0
- data/lib/linux/rb20x/ibm_db.bundle +0 -0
- data/lib/linux/rb21x/ibm_db.bundle +0 -0
@@ -1,2408 +1,2408 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'bigdecimal/util'
|
3
|
-
|
4
|
-
require 'models/person'
|
5
|
-
require 'models/topic'
|
6
|
-
require 'models/developer'
|
7
|
-
|
8
|
-
require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
|
9
|
-
require MIGRATIONS_ROOT + "/rename/1_we_need_things"
|
10
|
-
require MIGRATIONS_ROOT + "/rename/2_rename_things"
|
11
|
-
require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
|
12
|
-
|
13
|
-
if ActiveRecord::Base.connection.supports_migrations?
|
14
|
-
class BigNumber < ActiveRecord::Base; end
|
15
|
-
|
16
|
-
class Reminder < ActiveRecord::Base; end
|
17
|
-
|
18
|
-
class Thing < ActiveRecord::Base; end
|
19
|
-
|
20
|
-
class ActiveRecord::Migration
|
21
|
-
class << self
|
22
|
-
attr_accessor :message_count
|
23
|
-
end
|
24
|
-
|
25
|
-
def puts(text="")
|
26
|
-
ActiveRecord::Migration.message_count ||= 0
|
27
|
-
ActiveRecord::Migration.message_count += 1
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class MigrationTableAndIndexTest < ActiveRecord::TestCase
|
32
|
-
def test_add_schema_info_respects_prefix_and_suffix
|
33
|
-
conn = ActiveRecord::Base.connection
|
34
|
-
|
35
|
-
conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
|
36
|
-
# Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
|
37
|
-
ActiveRecord::Base.table_name_prefix = 'p_'
|
38
|
-
ActiveRecord::Base.table_name_suffix = '_s'
|
39
|
-
conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
|
40
|
-
|
41
|
-
conn.initialize_schema_migrations_table
|
42
|
-
|
43
|
-
assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
|
44
|
-
ensure
|
45
|
-
ActiveRecord::Base.table_name_prefix = ""
|
46
|
-
ActiveRecord::Base.table_name_suffix = ""
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class MigrationTest < ActiveRecord::TestCase
|
51
|
-
self.use_transactional_fixtures = false
|
52
|
-
|
53
|
-
if (current_adapter?(:IBM_DBAdapter))
|
54
|
-
#Rename is supported only for server zOS 9 , DB2 COBRA and Informix
|
55
|
-
server_type = ActiveRecord::Base.connection.servertype.class.name
|
56
|
-
@ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
|
57
|
-
server_type.class.name.include?('::IBM_IDS') ||
|
58
|
-
(server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
|
59
|
-
end
|
60
|
-
|
61
|
-
fixtures :people
|
62
|
-
|
63
|
-
def setup
|
64
|
-
ActiveRecord::Migration.verbose = true
|
65
|
-
ActiveRecord::Migration.message_count = 0
|
66
|
-
end
|
67
|
-
|
68
|
-
def teardown
|
69
|
-
ActiveRecord::Base.connection.initialize_schema_migrations_table
|
70
|
-
ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
|
71
|
-
|
72
|
-
%w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table|
|
73
|
-
Thing.connection.drop_table(table) rescue nil
|
74
|
-
end
|
75
|
-
Thing.reset_column_information
|
76
|
-
|
77
|
-
%w(reminders people_reminders prefix_reminders_suffix).each do |table|
|
78
|
-
Reminder.connection.drop_table(table) rescue nil
|
79
|
-
end
|
80
|
-
Reminder.reset_column_information
|
81
|
-
|
82
|
-
%w(last_name key bio age height wealth birthday favorite_day
|
83
|
-
moment_of_truth male administrator funny).each do |column|
|
84
|
-
Person.connection.remove_column('people', column) rescue nil
|
85
|
-
end
|
86
|
-
Person.connection.remove_column("people", "first_name") rescue nil
|
87
|
-
Person.connection.remove_column("people", "middle_name") rescue nil
|
88
|
-
Person.connection.add_column("people", "first_name", :string, :limit => 40)
|
89
|
-
Person.reset_column_information
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_add_index
|
93
|
-
# Limit size of last_name and key columns to support Firebird index limitations
|
94
|
-
Person.connection.add_column "people", "last_name", :string, :limit => 100
|
95
|
-
Person.connection.add_column "people", "key", :string, :limit => 100
|
96
|
-
Person.connection.add_column "people", "administrator", :boolean
|
97
|
-
|
98
|
-
assert_nothing_raised { Person.connection.add_index("people", "last_name") }
|
99
|
-
assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
|
100
|
-
|
101
|
-
# Orcl nds shrt indx nms. Sybs 2.
|
102
|
-
# OpenBase does not have named indexes. You must specify a single column name
|
103
|
-
unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
|
104
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
105
|
-
assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
|
106
|
-
# Oracle adapter cannot have specified index name larger than 30 characters
|
107
|
-
# Oracle adapter is shortening index name when just column list is given
|
108
|
-
unless current_adapter?(:OracleAdapter)
|
109
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
110
|
-
assert_nothing_raised { Person.connection.remove_index("people", :name => :index_people_on_last_name_and_first_name) }
|
111
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
112
|
-
assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
|
113
|
-
end
|
114
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
115
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
116
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
|
117
|
-
assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
|
118
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) }
|
119
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
|
120
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) }
|
121
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
122
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) }
|
123
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
124
|
-
end
|
125
|
-
|
126
|
-
# quoting
|
127
|
-
# Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
|
128
|
-
# OpenBase does not have named indexes. You must specify a single column name
|
129
|
-
unless current_adapter?(:OpenBaseAdapter)
|
130
|
-
unless current_adapter?(:IBM_DBAdapter)
|
131
|
-
Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique)
|
132
|
-
else
|
133
|
-
Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'first_name'}"
|
134
|
-
end
|
135
|
-
assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
|
136
|
-
assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
|
137
|
-
end
|
138
|
-
|
139
|
-
# Sybase adapter does not support indexes on :boolean columns
|
140
|
-
# OpenBase does not have named indexes. You must specify a single column
|
141
|
-
unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
|
142
|
-
assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
|
143
|
-
assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
|
144
|
-
end
|
145
|
-
|
146
|
-
# Selected adapters support index sort order
|
147
|
-
if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
148
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) }
|
149
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
|
150
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) }
|
151
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
152
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) }
|
153
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
154
|
-
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) }
|
155
|
-
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_index_symbol_names
|
160
|
-
assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name }
|
161
|
-
assert Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
|
162
|
-
assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name }
|
163
|
-
assert !Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_add_index_length_limit
|
167
|
-
good_index_name = 'x' * Person.connection.index_name_length
|
168
|
-
too_long_index_name = good_index_name + 'x'
|
169
|
-
assert_raise(ArgumentError) { Person.connection.add_index("people", "first_name", :name => too_long_index_name) }
|
170
|
-
assert !Person.connection.index_name_exists?("people", too_long_index_name, false)
|
171
|
-
assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) }
|
172
|
-
assert Person.connection.index_name_exists?("people", good_index_name, false)
|
173
|
-
Person.connection.remove_index("people", :name => good_index_name)
|
174
|
-
end
|
175
|
-
|
176
|
-
def test_add_index_attribute_length_limit
|
177
|
-
Person.connection.add_index :people, [:first_name, :primary_contact_id], :length => {:first_name => 10, :primary_contact_id => nil}, :name => "attribute_length"
|
178
|
-
assert Person.connection.index_exists?(:people, [:first_name, :primary_contact_id], :name => "attribute_length")
|
179
|
-
ensure
|
180
|
-
Person.connection.remove_index(:people, :name => "attribute_length")
|
181
|
-
end
|
182
|
-
|
183
|
-
def test_remove_nonexistent_index
|
184
|
-
# we do this by name, so OpenBase is a wash as noted above
|
185
|
-
unless current_adapter?(:OpenBaseAdapter)
|
186
|
-
assert_raise(ArgumentError) { Person.connection.remove_index("people", "no_such_index") }
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def test_rename_index
|
191
|
-
unless current_adapter?(:OpenBaseAdapter)
|
192
|
-
# keep the names short to make Oracle and similar behave
|
193
|
-
Person.connection.add_index('people', [:first_name], :name => 'old_idx')
|
194
|
-
assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') }
|
195
|
-
# if the adapter doesn't support the indexes call, pick defaults that let the test pass
|
196
|
-
assert !Person.connection.index_name_exists?('people', 'old_idx', false)
|
197
|
-
assert Person.connection.index_name_exists?('people', 'new_idx', true)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def test_double_add_index
|
202
|
-
unless current_adapter?(:OpenBaseAdapter)
|
203
|
-
Person.connection.add_index('people', [:first_name], :name => 'some_idx')
|
204
|
-
assert_raise(ArgumentError) { Person.connection.add_index('people', [:first_name], :name => 'some_idx') }
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def test_index_exists
|
209
|
-
Person.connection.create_table :testings do |t|
|
210
|
-
t.column :foo, :string, :limit => 100
|
211
|
-
t.column :bar, :string, :limit => 100
|
212
|
-
end
|
213
|
-
Person.connection.add_index :testings, :foo
|
214
|
-
|
215
|
-
assert Person.connection.index_exists?(:testings, :foo)
|
216
|
-
assert !Person.connection.index_exists?(:testings, :bar)
|
217
|
-
ensure
|
218
|
-
Person.connection.drop_table :testings rescue nil
|
219
|
-
end
|
220
|
-
|
221
|
-
def test_index_exists_on_multiple_columns
|
222
|
-
Person.connection.create_table :testings do |t|
|
223
|
-
t.column :foo, :string, :limit => 100
|
224
|
-
t.column :bar, :string, :limit => 100
|
225
|
-
end
|
226
|
-
Person.connection.add_index :testings, [:foo, :bar]
|
227
|
-
|
228
|
-
assert Person.connection.index_exists?(:testings, [:foo, :bar])
|
229
|
-
ensure
|
230
|
-
Person.connection.drop_table :testings rescue nil
|
231
|
-
end
|
232
|
-
|
233
|
-
def test_unique_index_exists
|
234
|
-
Person.connection.create_table :testings do |t|
|
235
|
-
t.column :foo, :string, :limit => 100
|
236
|
-
end
|
237
|
-
Person.connection.add_index :testings, :foo, :unique => true
|
238
|
-
|
239
|
-
assert Person.connection.index_exists?(:testings, :foo, :unique => true)
|
240
|
-
ensure
|
241
|
-
Person.connection.drop_table :testings rescue nil
|
242
|
-
end
|
243
|
-
|
244
|
-
def test_named_index_exists
|
245
|
-
Person.connection.create_table :testings do |t|
|
246
|
-
t.column :foo, :string, :limit => 100
|
247
|
-
end
|
248
|
-
Person.connection.add_index :testings, :foo, :name => "custom_index_name"
|
249
|
-
|
250
|
-
assert Person.connection.index_exists?(:testings, :foo, :name => "custom_index_name")
|
251
|
-
ensure
|
252
|
-
Person.connection.drop_table :testings rescue nil
|
253
|
-
end
|
254
|
-
|
255
|
-
def testing_table_with_only_foo_attribute
|
256
|
-
Person.connection.create_table :testings, :id => false do |t|
|
257
|
-
t.column :foo, :string
|
258
|
-
end
|
259
|
-
|
260
|
-
yield Person.connection
|
261
|
-
ensure
|
262
|
-
Person.connection.drop_table :testings rescue nil
|
263
|
-
end
|
264
|
-
protected :testing_table_with_only_foo_attribute
|
265
|
-
|
266
|
-
def test_create_table_without_id
|
267
|
-
testing_table_with_only_foo_attribute do |connection|
|
268
|
-
assert_equal connection.columns(:testings).size, 1
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
unless current_adapter?(:IBM_DBAdapter)
|
273
|
-
# For DB2: Cannot add a primary key to a table with some rows already in it as it violates the unique constraint
|
274
|
-
# Secondly GENERATED BY DEFAULT AS IDENTITY cannot be applied in a alter table command.
|
275
|
-
# as this will be wrong sql syntax for DB
|
276
|
-
def test_add_column_with_primary_key_attribute
|
277
|
-
testing_table_with_only_foo_attribute do |connection|
|
278
|
-
assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
|
279
|
-
assert_equal connection.columns(:testings).size, 2
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
def test_create_table_adds_id
|
285
|
-
Person.connection.create_table :testings do |t|
|
286
|
-
t.column :foo, :string
|
287
|
-
end
|
288
|
-
|
289
|
-
assert_equal %w(foo id),
|
290
|
-
Person.connection.columns(:testings).map { |c| c.name }.sort
|
291
|
-
ensure
|
292
|
-
Person.connection.drop_table :testings rescue nil
|
293
|
-
end
|
294
|
-
|
295
|
-
def test_create_table_with_not_null_column
|
296
|
-
assert_nothing_raised do
|
297
|
-
Person.connection.create_table :testings do |t|
|
298
|
-
t.column :foo, :string, :null => false
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
assert_raise(ActiveRecord::StatementInvalid) do
|
303
|
-
Person.connection.execute "insert into testings (foo) values (NULL)"
|
304
|
-
end
|
305
|
-
ensure
|
306
|
-
Person.connection.drop_table :testings rescue nil
|
307
|
-
end
|
308
|
-
|
309
|
-
def test_create_table_with_defaults
|
310
|
-
# MySQL doesn't allow defaults on TEXT or BLOB columns.
|
311
|
-
mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
|
312
|
-
|
313
|
-
Person.connection.create_table :testings do |t|
|
314
|
-
t.column :one, :string, :default => "hello"
|
315
|
-
t.column :two, :boolean, :default => true
|
316
|
-
t.column :three, :boolean, :default => false
|
317
|
-
t.column :four, :integer, :default => 1
|
318
|
-
t.column :five, :text, :default => "hello" unless mysql
|
319
|
-
end
|
320
|
-
|
321
|
-
columns = Person.connection.columns(:testings)
|
322
|
-
one = columns.detect { |c| c.name == "one" }
|
323
|
-
two = columns.detect { |c| c.name == "two" }
|
324
|
-
three = columns.detect { |c| c.name == "three" }
|
325
|
-
four = columns.detect { |c| c.name == "four" }
|
326
|
-
five = columns.detect { |c| c.name == "five" } unless mysql
|
327
|
-
|
328
|
-
assert_equal "hello", one.default
|
329
|
-
assert_equal true, two.default
|
330
|
-
assert_equal false, three.default
|
331
|
-
assert_equal 1, four.default
|
332
|
-
assert_equal "hello", five.default unless mysql
|
333
|
-
|
334
|
-
ensure
|
335
|
-
Person.connection.drop_table :testings rescue nil
|
336
|
-
end
|
337
|
-
|
338
|
-
def test_create_table_with_limits
|
339
|
-
assert_nothing_raised do
|
340
|
-
Person.connection.create_table :testings do |t|
|
341
|
-
t.column :foo, :string, :limit => 255
|
342
|
-
|
343
|
-
t.column :default_int, :integer
|
344
|
-
|
345
|
-
t.column :one_int, :integer, :limit => 1
|
346
|
-
t.column :four_int, :integer, :limit => 4
|
347
|
-
t.column :eight_int, :integer, :limit => 8
|
348
|
-
t.column :eleven_int, :integer, :limit => 11
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
columns = Person.connection.columns(:testings)
|
353
|
-
foo = columns.detect { |c| c.name == "foo" }
|
354
|
-
assert_equal 255, foo.limit
|
355
|
-
|
356
|
-
default = columns.detect { |c| c.name == "default_int" }
|
357
|
-
one = columns.detect { |c| c.name == "one_int" }
|
358
|
-
four = columns.detect { |c| c.name == "four_int" }
|
359
|
-
eight = columns.detect { |c| c.name == "eight_int" }
|
360
|
-
eleven = columns.detect { |c| c.name == "eleven_int" }
|
361
|
-
|
362
|
-
if current_adapter?(:PostgreSQLAdapter)
|
363
|
-
assert_equal 'integer', default.sql_type
|
364
|
-
assert_equal 'smallint', one.sql_type
|
365
|
-
assert_equal 'integer', four.sql_type
|
366
|
-
assert_equal 'bigint', eight.sql_type
|
367
|
-
assert_equal 'integer', eleven.sql_type
|
368
|
-
elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
369
|
-
assert_match 'int(11)', default.sql_type
|
370
|
-
assert_match 'tinyint', one.sql_type
|
371
|
-
assert_match 'int', four.sql_type
|
372
|
-
assert_match 'bigint', eight.sql_type
|
373
|
-
assert_match 'int(11)', eleven.sql_type
|
374
|
-
elsif current_adapter?(:OracleAdapter)
|
375
|
-
assert_equal 'NUMBER(38)', default.sql_type
|
376
|
-
assert_equal 'NUMBER(1)', one.sql_type
|
377
|
-
assert_equal 'NUMBER(4)', four.sql_type
|
378
|
-
assert_equal 'NUMBER(8)', eight.sql_type
|
379
|
-
end
|
380
|
-
ensure
|
381
|
-
Person.connection.drop_table :testings rescue nil
|
382
|
-
end
|
383
|
-
|
384
|
-
def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
|
385
|
-
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
|
386
|
-
|
387
|
-
Person.connection.create_table :testings do |t|
|
388
|
-
t.column :foo, :string
|
389
|
-
end
|
390
|
-
|
391
|
-
assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort
|
392
|
-
ensure
|
393
|
-
Person.connection.drop_table :testings rescue nil
|
394
|
-
ActiveRecord::Base.primary_key_prefix_type = nil
|
395
|
-
end
|
396
|
-
|
397
|
-
def test_create_table_with_primary_key_prefix_as_table_name
|
398
|
-
ActiveRecord::Base.primary_key_prefix_type = :table_name
|
399
|
-
|
400
|
-
Person.connection.create_table :testings do |t|
|
401
|
-
t.column :foo, :string
|
402
|
-
end
|
403
|
-
|
404
|
-
assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort
|
405
|
-
ensure
|
406
|
-
Person.connection.drop_table :testings rescue nil
|
407
|
-
ActiveRecord::Base.primary_key_prefix_type = nil
|
408
|
-
end
|
409
|
-
|
410
|
-
def test_create_table_with_force_true_does_not_drop_nonexisting_table
|
411
|
-
if Person.connection.table_exists?(:testings2)
|
412
|
-
Person.connection.drop_table :testings2
|
413
|
-
end
|
414
|
-
|
415
|
-
# using a copy as we need the drop_table method to
|
416
|
-
# continue to work for the ensure block of the test
|
417
|
-
temp_conn = Person.connection.dup
|
418
|
-
temp_conn.expects(:drop_table).never
|
419
|
-
temp_conn.create_table :testings2, :force => true do |t|
|
420
|
-
t.column :foo, :string
|
421
|
-
end
|
422
|
-
ensure
|
423
|
-
Person.connection.drop_table :testings2 rescue nil
|
424
|
-
end
|
425
|
-
|
426
|
-
def test_create_table_with_timestamps_should_create_datetime_columns
|
427
|
-
table_name = :testings
|
428
|
-
|
429
|
-
Person.connection.create_table table_name do |t|
|
430
|
-
t.timestamps
|
431
|
-
end
|
432
|
-
created_columns = Person.connection.columns(table_name)
|
433
|
-
|
434
|
-
created_at_column = created_columns.detect {|c| c.name == 'created_at' }
|
435
|
-
updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
|
436
|
-
|
437
|
-
assert !created_at_column.null
|
438
|
-
assert !updated_at_column.null
|
439
|
-
ensure
|
440
|
-
Person.connection.drop_table table_name rescue nil
|
441
|
-
end
|
442
|
-
|
443
|
-
def test_create_table_with_timestamps_should_create_datetime_columns_with_options
|
444
|
-
table_name = :testings
|
445
|
-
|
446
|
-
Person.connection.create_table table_name do |t|
|
447
|
-
t.timestamps :null => false
|
448
|
-
end
|
449
|
-
created_columns = Person.connection.columns(table_name)
|
450
|
-
|
451
|
-
created_at_column = created_columns.detect {|c| c.name == 'created_at' }
|
452
|
-
updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
|
453
|
-
|
454
|
-
assert !created_at_column.null
|
455
|
-
assert !updated_at_column.null
|
456
|
-
ensure
|
457
|
-
Person.connection.drop_table table_name rescue nil
|
458
|
-
end
|
459
|
-
|
460
|
-
def test_create_table_without_a_block
|
461
|
-
table_name = :testings
|
462
|
-
Person.connection.create_table table_name
|
463
|
-
ensure
|
464
|
-
Person.connection.drop_table table_name rescue nil
|
465
|
-
end
|
466
|
-
|
467
|
-
# Sybase, and SQLite3 will not allow you to add a NOT NULL
|
468
|
-
# column to a table without a default value.
|
469
|
-
unless current_adapter?(:SybaseAdapter, :SQLite3Adapter, :IBM_DBAdapter)
|
470
|
-
def test_add_column_not_null_without_default
|
471
|
-
Person.connection.create_table :testings do |t|
|
472
|
-
t.column :foo, :string
|
473
|
-
end
|
474
|
-
Person.connection.add_column :testings, :bar, :string, :null => false
|
475
|
-
|
476
|
-
assert_raise(ActiveRecord::StatementInvalid) do
|
477
|
-
Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
|
478
|
-
end
|
479
|
-
ensure
|
480
|
-
Person.connection.drop_table :testings rescue nil
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
def test_add_column_not_null_with_default
|
485
|
-
Person.connection.create_table :testings do |t|
|
486
|
-
t.column :foo, :string
|
487
|
-
end
|
488
|
-
|
489
|
-
con = Person.connection
|
490
|
-
Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
|
491
|
-
Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
|
492
|
-
Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
|
493
|
-
assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
|
494
|
-
|
495
|
-
assert_raise(ActiveRecord::StatementInvalid) do
|
496
|
-
unless current_adapter?(:OpenBaseAdapter)
|
497
|
-
Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)"
|
498
|
-
else
|
499
|
-
Person.connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)",
|
500
|
-
"Testing Insert","id",2)
|
501
|
-
end
|
502
|
-
end
|
503
|
-
ensure
|
504
|
-
Person.connection.drop_table :testings rescue nil
|
505
|
-
end
|
506
|
-
|
507
|
-
# We specifically do a manual INSERT here, and then test only the SELECT
|
508
|
-
# functionality. This allows us to more easily catch INSERT being broken,
|
509
|
-
# but SELECT actually working fine.
|
510
|
-
def test_native_decimal_insert_manual_vs_automatic
|
511
|
-
correct_value = '0012345678901234567890.0123456789'.to_d
|
512
|
-
|
513
|
-
Person.delete_all
|
514
|
-
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
515
|
-
Person.reset_column_information
|
516
|
-
|
517
|
-
# Do a manual insertion
|
518
|
-
if current_adapter?(:OracleAdapter)
|
519
|
-
Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)"
|
520
|
-
elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
|
521
|
-
Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)"
|
522
|
-
elsif current_adapter?(:PostgreSQLAdapter)
|
523
|
-
Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())"
|
524
|
-
elsif current_adapter?(:IBM_DBAdapter)
|
525
|
-
Person.connection.execute "insert into people (wealth, created_at, updated_at, lock_version, first_name) values (12345678901234567890.0123456789, CURRENT TIMESTAMP, CURRENT TIMESTAMP, 0, 'Jim')"
|
526
|
-
else
|
527
|
-
Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
|
528
|
-
end
|
529
|
-
|
530
|
-
# SELECT
|
531
|
-
row = Person.find(:first)
|
532
|
-
assert_kind_of BigDecimal, row.wealth
|
533
|
-
|
534
|
-
# If this assert fails, that means the SELECT is broken!
|
535
|
-
unless current_adapter?(:SQLite3Adapter)
|
536
|
-
assert_equal correct_value, row.wealth
|
537
|
-
end
|
538
|
-
|
539
|
-
# Reset to old state
|
540
|
-
Person.delete_all
|
541
|
-
|
542
|
-
# Now use the Rails insertion
|
543
|
-
unless current_adapter?(:IBM_DBAdapter)
|
544
|
-
assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
|
545
|
-
else
|
546
|
-
# First_name is a not null column, hence ensure a value is specified
|
547
|
-
assert_nothing_raised { Person.create ({:wealth => BigDecimal.new("12345678901234567890.0123456789"), :first_name => "James"}) }
|
548
|
-
end
|
549
|
-
|
550
|
-
# SELECT
|
551
|
-
row = Person.find(:first)
|
552
|
-
assert_kind_of BigDecimal, row.wealth
|
553
|
-
|
554
|
-
# If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
|
555
|
-
unless current_adapter?(:SQLite3Adapter)
|
556
|
-
assert_equal correct_value, row.wealth
|
557
|
-
end
|
558
|
-
|
559
|
-
# Reset to old state
|
560
|
-
Person.connection.del_column "people", "wealth" rescue nil
|
561
|
-
Person.reset_column_information
|
562
|
-
end
|
563
|
-
|
564
|
-
def test_add_column_with_precision_and_scale
|
565
|
-
Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
|
566
|
-
Person.reset_column_information
|
567
|
-
|
568
|
-
wealth_column = Person.columns_hash['wealth']
|
569
|
-
assert_equal 9, wealth_column.precision
|
570
|
-
assert_equal 7, wealth_column.scale
|
571
|
-
end
|
572
|
-
|
573
|
-
# Test SQLite adapter specifically for decimal types with precision and scale
|
574
|
-
# attributes, since these need to be maintained in schema but aren't actually
|
575
|
-
# used in SQLite itself
|
576
|
-
if current_adapter?(:SQLite3Adapter)
|
577
|
-
def test_change_column_with_new_precision_and_scale
|
578
|
-
Person.delete_all
|
579
|
-
Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
|
580
|
-
Person.reset_column_information
|
581
|
-
|
582
|
-
Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8
|
583
|
-
Person.reset_column_information
|
584
|
-
|
585
|
-
wealth_column = Person.columns_hash['wealth']
|
586
|
-
assert_equal 12, wealth_column.precision
|
587
|
-
assert_equal 8, wealth_column.scale
|
588
|
-
end
|
589
|
-
|
590
|
-
def test_change_column_preserve_other_column_precision_and_scale
|
591
|
-
Person.delete_all
|
592
|
-
Person.connection.add_column 'people', 'last_name', :string
|
593
|
-
Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
|
594
|
-
Person.reset_column_information
|
595
|
-
|
596
|
-
wealth_column = Person.columns_hash['wealth']
|
597
|
-
assert_equal 9, wealth_column.precision
|
598
|
-
assert_equal 7, wealth_column.scale
|
599
|
-
|
600
|
-
Person.connection.change_column 'people', 'last_name', :string, :null => false
|
601
|
-
Person.reset_column_information
|
602
|
-
|
603
|
-
wealth_column = Person.columns_hash['wealth']
|
604
|
-
assert_equal 9, wealth_column.precision
|
605
|
-
assert_equal 7, wealth_column.scale
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
|
-
def test_native_types
|
610
|
-
Person.delete_all
|
611
|
-
Person.connection.add_column "people", "last_name", :string
|
612
|
-
Person.connection.add_column "people", "bio", :text
|
613
|
-
Person.connection.add_column "people", "age", :integer
|
614
|
-
Person.connection.add_column "people", "height", :float
|
615
|
-
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
616
|
-
Person.connection.add_column "people", "birthday", :datetime
|
617
|
-
Person.connection.add_column "people", "favorite_day", :date
|
618
|
-
Person.connection.add_column "people", "moment_of_truth", :datetime
|
619
|
-
Person.connection.add_column "people", "male", :boolean
|
620
|
-
Person.reset_column_information
|
621
|
-
|
622
|
-
assert_nothing_raised do
|
623
|
-
Person.create :first_name => 'bob', :last_name => 'bobsen',
|
624
|
-
:bio => "I was born ....", :age => 18, :height => 1.78,
|
625
|
-
:wealth => BigDecimal.new("12345678901234567890.0123456789"),
|
626
|
-
:birthday => 18.years.ago, :favorite_day => 10.days.ago,
|
627
|
-
:moment_of_truth => "1782-10-10 21:40:18", :male => true
|
628
|
-
end
|
629
|
-
|
630
|
-
bob = Person.find(:first)
|
631
|
-
assert_equal 'bob', bob.first_name
|
632
|
-
assert_equal 'bobsen', bob.last_name
|
633
|
-
assert_equal "I was born ....", bob.bio
|
634
|
-
assert_equal 18, bob.age
|
635
|
-
|
636
|
-
# Test for 30 significant digits (beyond the 16 of float), 10 of them
|
637
|
-
# after the decimal place.
|
638
|
-
|
639
|
-
unless current_adapter?(:SQLite3Adapter)
|
640
|
-
assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
|
641
|
-
end
|
642
|
-
|
643
|
-
assert_equal true, bob.male?
|
644
|
-
|
645
|
-
assert_equal String, bob.first_name.class
|
646
|
-
assert_equal String, bob.last_name.class
|
647
|
-
assert_equal String, bob.bio.class
|
648
|
-
assert_equal Fixnum, bob.age.class
|
649
|
-
assert_equal Time, bob.birthday.class
|
650
|
-
|
651
|
-
if current_adapter?(:OracleAdapter, :SybaseAdapter)
|
652
|
-
# Sybase, and Oracle don't differentiate between date/time
|
653
|
-
assert_equal Time, bob.favorite_day.class
|
654
|
-
else
|
655
|
-
assert_equal Date, bob.favorite_day.class
|
656
|
-
end
|
657
|
-
|
658
|
-
# Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column
|
659
|
-
# therefore no timezone change is done afterwards when default timezone is changed
|
660
|
-
unless current_adapter?(:OracleAdapter)
|
661
|
-
# Test DateTime column and defaults, including timezone.
|
662
|
-
# FIXME: moment of truth may be Time on 64-bit platforms.
|
663
|
-
if bob.moment_of_truth.is_a?(DateTime)
|
664
|
-
|
665
|
-
with_env_tz 'US/Eastern' do
|
666
|
-
bob.reload
|
667
|
-
assert_equal DateTime.local_offset, bob.moment_of_truth.offset
|
668
|
-
assert_not_equal 0, bob.moment_of_truth.offset
|
669
|
-
assert_not_equal "Z", bob.moment_of_truth.zone
|
670
|
-
# US/Eastern is -5 hours from GMT
|
671
|
-
assert_equal Rational(-5, 24), bob.moment_of_truth.offset
|
672
|
-
assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM
|
673
|
-
assert_equal DateTime::ITALY, bob.moment_of_truth.start
|
674
|
-
end
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
assert_instance_of TrueClass, bob.male?
|
679
|
-
assert_kind_of BigDecimal, bob.wealth
|
680
|
-
end
|
681
|
-
|
682
|
-
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
683
|
-
def test_unabstracted_database_dependent_types
|
684
|
-
Person.delete_all
|
685
|
-
|
686
|
-
ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
|
687
|
-
Person.reset_column_information
|
688
|
-
assert_match(/tinyint/, Person.columns_hash['intelligence_quotient'].sql_type)
|
689
|
-
ensure
|
690
|
-
ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil
|
691
|
-
end
|
692
|
-
end
|
693
|
-
|
694
|
-
def test_add_remove_single_field_using_string_arguments
|
695
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
696
|
-
|
697
|
-
ActiveRecord::Migration.add_column 'people', 'last_name', :string
|
698
|
-
|
699
|
-
Person.reset_column_information
|
700
|
-
assert Person.column_methods_hash.include?(:last_name)
|
701
|
-
|
702
|
-
ActiveRecord::Migration.remove_column 'people', 'last_name'
|
703
|
-
|
704
|
-
Person.reset_column_information
|
705
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
706
|
-
end
|
707
|
-
|
708
|
-
def test_add_remove_single_field_using_symbol_arguments
|
709
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
710
|
-
|
711
|
-
ActiveRecord::Migration.add_column :people, :last_name, :string
|
712
|
-
|
713
|
-
Person.reset_column_information
|
714
|
-
assert Person.column_methods_hash.include?(:last_name)
|
715
|
-
|
716
|
-
ActiveRecord::Migration.remove_column :people, :last_name
|
717
|
-
|
718
|
-
Person.reset_column_information
|
719
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
720
|
-
end
|
721
|
-
|
722
|
-
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
723
|
-
def testing_table_for_positioning
|
724
|
-
Person.connection.create_table :testings, :id => false do |t|
|
725
|
-
t.column :first, :integer
|
726
|
-
t.column :second, :integer
|
727
|
-
t.column :third, :integer
|
728
|
-
end
|
729
|
-
|
730
|
-
yield Person.connection
|
731
|
-
ensure
|
732
|
-
Person.connection.drop_table :testings rescue nil
|
733
|
-
end
|
734
|
-
protected :testing_table_for_positioning
|
735
|
-
|
736
|
-
def test_column_positioning
|
737
|
-
testing_table_for_positioning do |conn|
|
738
|
-
assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name }
|
739
|
-
end
|
740
|
-
end
|
741
|
-
|
742
|
-
def test_add_column_with_positioning
|
743
|
-
testing_table_for_positioning do |conn|
|
744
|
-
conn.add_column :testings, :new_col, :integer
|
745
|
-
assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name }
|
746
|
-
end
|
747
|
-
testing_table_for_positioning do |conn|
|
748
|
-
conn.add_column :testings, :new_col, :integer, :first => true
|
749
|
-
assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name }
|
750
|
-
end
|
751
|
-
testing_table_for_positioning do |conn|
|
752
|
-
conn.add_column :testings, :new_col, :integer, :after => :first
|
753
|
-
assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name }
|
754
|
-
end
|
755
|
-
end
|
756
|
-
|
757
|
-
def test_change_column_with_positioning
|
758
|
-
testing_table_for_positioning do |conn|
|
759
|
-
conn.change_column :testings, :second, :integer, :first => true
|
760
|
-
assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name }
|
761
|
-
end
|
762
|
-
testing_table_for_positioning do |conn|
|
763
|
-
conn.change_column :testings, :second, :integer, :after => :third
|
764
|
-
assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name }
|
765
|
-
end
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
if(!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
|
770
|
-
def test_add_rename
|
771
|
-
Person.delete_all
|
772
|
-
|
773
|
-
begin
|
774
|
-
Person.connection.add_column "people", "girlfriend", :string
|
775
|
-
Person.reset_column_information
|
776
|
-
Person.create :girlfriend => 'bobette'
|
777
|
-
|
778
|
-
Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
|
779
|
-
|
780
|
-
Person.reset_column_information
|
781
|
-
bob = Person.find(:first)
|
782
|
-
|
783
|
-
assert_equal "bobette", bob.exgirlfriend
|
784
|
-
ensure
|
785
|
-
Person.connection.remove_column("people", "girlfriend") rescue nil
|
786
|
-
Person.connection.remove_column("people", "exgirlfriend") rescue nil
|
787
|
-
end
|
788
|
-
|
789
|
-
end
|
790
|
-
|
791
|
-
def test_rename_column_using_symbol_arguments
|
792
|
-
begin
|
793
|
-
names_before = Person.find(:all).map(&:first_name)
|
794
|
-
Person.connection.rename_column :people, :first_name, :nick_name
|
795
|
-
Person.reset_column_information
|
796
|
-
assert Person.column_names.include?("nick_name")
|
797
|
-
assert_equal names_before, Person.find(:all).map(&:nick_name)
|
798
|
-
ensure
|
799
|
-
Person.connection.remove_column("people","nick_name")
|
800
|
-
Person.connection.add_column("people","first_name", :string)
|
801
|
-
end
|
802
|
-
end
|
803
|
-
|
804
|
-
def test_rename_column
|
805
|
-
begin
|
806
|
-
names_before = Person.find(:all).map(&:first_name)
|
807
|
-
Person.connection.rename_column "people", "first_name", "nick_name"
|
808
|
-
Person.reset_column_information
|
809
|
-
assert Person.column_names.include?("nick_name")
|
810
|
-
assert_equal names_before, Person.find(:all).map(&:nick_name)
|
811
|
-
ensure
|
812
|
-
Person.connection.remove_column("people","nick_name")
|
813
|
-
Person.connection.add_column("people","first_name", :string)
|
814
|
-
end
|
815
|
-
end
|
816
|
-
|
817
|
-
def test_rename_column_preserves_default_value_not_null
|
818
|
-
begin
|
819
|
-
default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
|
820
|
-
assert_equal 70000, default_before
|
821
|
-
Developer.connection.rename_column "developers", "salary", "anual_salary"
|
822
|
-
Developer.reset_column_information
|
823
|
-
assert Developer.column_names.include?("anual_salary")
|
824
|
-
default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
|
825
|
-
assert_equal 70000, default_after
|
826
|
-
ensure
|
827
|
-
Developer.connection.rename_column "developers", "anual_salary", "salary"
|
828
|
-
Developer.reset_column_information
|
829
|
-
end
|
830
|
-
end
|
831
|
-
|
832
|
-
def test_rename_nonexistent_column
|
833
|
-
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
834
|
-
table.column :hat_name, :string, :default => nil
|
835
|
-
end
|
836
|
-
exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
|
837
|
-
ActiveRecord::StatementInvalid
|
838
|
-
else
|
839
|
-
ActiveRecord::ActiveRecordError
|
840
|
-
end
|
841
|
-
assert_raise(exception) do
|
842
|
-
Person.connection.rename_column "hats", "nonexistent", "should_fail"
|
843
|
-
end
|
844
|
-
ensure
|
845
|
-
ActiveRecord::Base.connection.drop_table(:hats)
|
846
|
-
end
|
847
|
-
|
848
|
-
def test_rename_column_with_sql_reserved_word
|
849
|
-
begin
|
850
|
-
assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
|
851
|
-
Person.reset_column_information
|
852
|
-
assert Person.column_names.include?("group")
|
853
|
-
ensure
|
854
|
-
Person.connection.remove_column("people", "group") rescue nil
|
855
|
-
Person.connection.add_column("people", "first_name", :string) rescue nil
|
856
|
-
end
|
857
|
-
end
|
858
|
-
end
|
859
|
-
|
860
|
-
unless current_adapter?(:IBM_DBAdapter)
|
861
|
-
def test_rename_column_with_an_index
|
862
|
-
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
863
|
-
table.column :hat_name, :string, :limit => 100
|
864
|
-
table.column :hat_size, :integer
|
865
|
-
end
|
866
|
-
Person.connection.add_index :hats, :hat_name
|
867
|
-
assert_nothing_raised do
|
868
|
-
Person.connection.rename_column "hats", "hat_name", "name"
|
869
|
-
end
|
870
|
-
ensure
|
871
|
-
ActiveRecord::Base.connection.drop_table(:hats)
|
872
|
-
end
|
873
|
-
end
|
874
|
-
|
875
|
-
def test_remove_column_with_index
|
876
|
-
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
877
|
-
table.column :hat_name, :string, :limit => 100
|
878
|
-
table.column :hat_size, :integer
|
879
|
-
end
|
880
|
-
ActiveRecord::Base.connection.add_index "hats", "hat_size"
|
881
|
-
|
882
|
-
assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
|
883
|
-
ensure
|
884
|
-
ActiveRecord::Base.connection.drop_table(:hats)
|
885
|
-
end
|
886
|
-
|
887
|
-
def test_remove_column_with_multi_column_index
|
888
|
-
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
889
|
-
table.column :hat_name, :string, :limit => 100
|
890
|
-
table.column :hat_size, :integer
|
891
|
-
table.column :hat_style, :string, :limit => 100
|
892
|
-
end
|
893
|
-
ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
|
894
|
-
|
895
|
-
assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
|
896
|
-
ensure
|
897
|
-
ActiveRecord::Base.connection.drop_table(:hats)
|
898
|
-
end
|
899
|
-
|
900
|
-
def test_remove_column_no_second_parameter_raises_exception
|
901
|
-
assert_raise(ArgumentError) { Person.connection.remove_column("funny") }
|
902
|
-
end
|
903
|
-
|
904
|
-
def test_change_type_of_not_null_column
|
905
|
-
assert_nothing_raised do
|
906
|
-
unless current_adapter?(:IBM_DBAdapter)
|
907
|
-
Topic.connection.change_column "topics", "written_on", :datetime, :null => false
|
908
|
-
else
|
909
|
-
Topic.connection.change_column_null "topics", "written_on", false
|
910
|
-
end
|
911
|
-
Topic.reset_column_information
|
912
|
-
|
913
|
-
unless current_adapter?(:IBM_DBAdapter)
|
914
|
-
Topic.connection.change_column "topics", "written_on", :datetime, :null => false
|
915
|
-
else
|
916
|
-
Topic.connection.change_column_null "topics", "written_on", false
|
917
|
-
end
|
918
|
-
Topic.reset_column_information
|
919
|
-
|
920
|
-
unless current_adapter?(:IBM_DBAdapter)
|
921
|
-
Topic.connection.change_column "topics", "written_on", :datetime, :null => true
|
922
|
-
else
|
923
|
-
Topic.connection.change_column_null "topics", "written_on", true
|
924
|
-
end
|
925
|
-
|
926
|
-
Topic.reset_column_information
|
927
|
-
end
|
928
|
-
end
|
929
|
-
|
930
|
-
if current_adapter?(:SQLite3Adapter)
|
931
|
-
def test_rename_table_for_sqlite_should_work_with_reserved_words
|
932
|
-
begin
|
933
|
-
assert_nothing_raised do
|
934
|
-
ActiveRecord::Base.connection.rename_table :references, :old_references
|
935
|
-
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
936
|
-
t.column :url, :string
|
937
|
-
end
|
938
|
-
end
|
939
|
-
|
940
|
-
assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references }
|
941
|
-
|
942
|
-
# Using explicit id in insert for compatibility across all databases
|
943
|
-
con = ActiveRecord::Base.connection
|
944
|
-
assert_nothing_raised do
|
945
|
-
con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')"
|
946
|
-
end
|
947
|
-
assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1")
|
948
|
-
|
949
|
-
ensure
|
950
|
-
ActiveRecord::Base.connection.drop_table :references
|
951
|
-
ActiveRecord::Base.connection.rename_table :old_references, :references
|
952
|
-
end
|
953
|
-
end
|
954
|
-
end
|
955
|
-
|
956
|
-
def test_rename_table
|
957
|
-
begin
|
958
|
-
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
959
|
-
t.column :url, :string
|
960
|
-
end
|
961
|
-
ActiveRecord::Base.connection.rename_table :octopuses, :octopi
|
962
|
-
|
963
|
-
# Using explicit id in insert for compatibility across all databases
|
964
|
-
con = ActiveRecord::Base.connection
|
965
|
-
con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
|
966
|
-
assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
|
967
|
-
con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
|
968
|
-
|
969
|
-
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
|
970
|
-
|
971
|
-
ensure
|
972
|
-
ActiveRecord::Base.connection.drop_table :octopuses rescue nil
|
973
|
-
ActiveRecord::Base.connection.drop_table :octopi rescue nil
|
974
|
-
end
|
975
|
-
end
|
976
|
-
|
977
|
-
def test_change_column_nullability
|
978
|
-
Person.delete_all
|
979
|
-
Person.connection.add_column "people", "funny", :boolean
|
980
|
-
Person.reset_column_information
|
981
|
-
assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
|
982
|
-
unless current_adapter?(:IBM_DBAdapter)
|
983
|
-
Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true
|
984
|
-
else
|
985
|
-
Person.connection.change_column_null "people", "funny",false
|
986
|
-
end
|
987
|
-
Person.reset_column_information
|
988
|
-
assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
|
989
|
-
unless current_adapter?(:IBM_DBAdapter)
|
990
|
-
Person.connection.change_column "people", "funny", :boolean, :null => true
|
991
|
-
else
|
992
|
-
Person.connection.change_column_null "people", "funny",true
|
993
|
-
end
|
994
|
-
Person.reset_column_information
|
995
|
-
assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
|
996
|
-
end
|
997
|
-
|
998
|
-
def test_rename_table_with_an_index
|
999
|
-
begin
|
1000
|
-
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
1001
|
-
t.column :url, :string
|
1002
|
-
end
|
1003
|
-
ActiveRecord::Base.connection.add_index :octopuses, :url
|
1004
|
-
|
1005
|
-
ActiveRecord::Base.connection.rename_table :octopuses, :octopi
|
1006
|
-
|
1007
|
-
# Using explicit id in insert for compatibility across all databases
|
1008
|
-
con = ActiveRecord::Base.connection
|
1009
|
-
con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
|
1010
|
-
assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
|
1011
|
-
con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
|
1012
|
-
|
1013
|
-
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
|
1014
|
-
assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
|
1015
|
-
ensure
|
1016
|
-
ActiveRecord::Base.connection.drop_table :octopuses rescue nil
|
1017
|
-
ActiveRecord::Base.connection.drop_table :octopi rescue nil
|
1018
|
-
end
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1022
|
-
# Cannot convert from type integer to varchar.
|
1023
|
-
# Safe to not run this test as add_column will be covered in other test cases
|
1024
|
-
def test_change_column
|
1025
|
-
Person.connection.add_column 'people', 'age', :integer
|
1026
|
-
label = "test_change_column Columns"
|
1027
|
-
old_columns = Person.connection.columns(Person.table_name, label)
|
1028
|
-
assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
|
1029
|
-
|
1030
|
-
assert_nothing_raised { Person.connection.change_column "people", "age", :string }
|
1031
|
-
|
1032
|
-
new_columns = Person.connection.columns(Person.table_name, label)
|
1033
|
-
assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
|
1034
|
-
assert new_columns.find { |c| c.name == 'age' and c.type == :string }
|
1035
|
-
|
1036
|
-
old_columns = Topic.connection.columns(Topic.table_name, label)
|
1037
|
-
assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
1038
|
-
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
|
1039
|
-
new_columns = Topic.connection.columns(Topic.table_name, label)
|
1040
|
-
assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
1041
|
-
assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
|
1042
|
-
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
|
1043
|
-
end
|
1044
|
-
end
|
1045
|
-
|
1046
|
-
def test_change_column_with_nil_default
|
1047
|
-
Person.connection.add_column "people", "contributor", :boolean, :default => true
|
1048
|
-
Person.reset_column_information
|
1049
|
-
assert Person.new.contributor?
|
1050
|
-
|
1051
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1052
|
-
assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
|
1053
|
-
else
|
1054
|
-
assert_nothing_raised { Person.connection.change_column_default "people", "contributor", nil }
|
1055
|
-
end
|
1056
|
-
Person.reset_column_information
|
1057
|
-
assert !Person.new.contributor?
|
1058
|
-
assert_nil Person.new.contributor
|
1059
|
-
ensure
|
1060
|
-
Person.connection.remove_column("people", "contributor") rescue nil
|
1061
|
-
end
|
1062
|
-
|
1063
|
-
def test_change_column_with_new_default
|
1064
|
-
Person.connection.add_column "people", "administrator", :boolean, :default => true
|
1065
|
-
Person.reset_column_information
|
1066
|
-
assert Person.new.administrator?
|
1067
|
-
|
1068
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1069
|
-
assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
|
1070
|
-
else
|
1071
|
-
assert_nothing_raised { Person.connection.change_column_default "people", "administrator", false }
|
1072
|
-
end
|
1073
|
-
Person.reset_column_information
|
1074
|
-
assert !Person.new.administrator?
|
1075
|
-
ensure
|
1076
|
-
Person.connection.remove_column("people", "administrator") rescue nil
|
1077
|
-
end
|
1078
|
-
|
1079
|
-
def test_change_column_default
|
1080
|
-
Person.connection.change_column_default "people", "first_name", "Tester"
|
1081
|
-
Person.reset_column_information
|
1082
|
-
assert_equal "Tester", Person.new.first_name
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
def test_change_column_quotes_column_names
|
1086
|
-
Person.connection.create_table :testings do |t|
|
1087
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1088
|
-
t.column :select, :string
|
1089
|
-
else
|
1090
|
-
# If no limit specified by default column of length 255 is created, which later cannot be scaled down to 10
|
1091
|
-
t.column :select, :string, :limit => 5
|
1092
|
-
end
|
1093
|
-
end
|
1094
|
-
|
1095
|
-
assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 }
|
1096
|
-
|
1097
|
-
# Oracle needs primary key value from sequence
|
1098
|
-
if current_adapter?(:OracleAdapter)
|
1099
|
-
assert_nothing_raised { Person.connection.execute "insert into testings (id, #{Person.connection.quote_column_name('select')}) values (testings_seq.nextval, '7 chars')" }
|
1100
|
-
else
|
1101
|
-
assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
|
1102
|
-
end
|
1103
|
-
ensure
|
1104
|
-
Person.connection.drop_table :testings rescue nil
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
def test_keeping_default_and_notnull_constaint_on_change
|
1108
|
-
Person.connection.create_table :testings do |t|
|
1109
|
-
t.column :title, :string
|
1110
|
-
end
|
1111
|
-
person_klass = Class.new(Person)
|
1112
|
-
person_klass.table_name = 'testings'
|
1113
|
-
|
1114
|
-
person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
|
1115
|
-
person_klass.reset_column_information
|
1116
|
-
assert_equal 99, person_klass.columns_hash["wealth"].default
|
1117
|
-
assert_equal false, person_klass.columns_hash["wealth"].null
|
1118
|
-
# Oracle needs primary key value from sequence
|
1119
|
-
if current_adapter?(:OracleAdapter)
|
1120
|
-
assert_nothing_raised {person_klass.connection.execute("insert into testings (id, title) values (testings_seq.nextval, 'tester')")}
|
1121
|
-
else
|
1122
|
-
assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
|
1123
|
-
end
|
1124
|
-
|
1125
|
-
# change column default to see that column doesn't lose its not null definition
|
1126
|
-
person_klass.connection.change_column_default "testings", "wealth", 100
|
1127
|
-
person_klass.reset_column_information
|
1128
|
-
assert_equal 100, person_klass.columns_hash["wealth"].default
|
1129
|
-
assert_equal false, person_klass.columns_hash["wealth"].null
|
1130
|
-
|
1131
|
-
# rename column to see that column doesn't lose its not null and/or default definition
|
1132
|
-
if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
|
1133
|
-
person_klass.connection.rename_column "testings", "wealth", "money"
|
1134
|
-
person_klass.reset_column_information
|
1135
|
-
assert_nil person_klass.columns_hash["wealth"]
|
1136
|
-
assert_equal 100, person_klass.columns_hash["money"].default
|
1137
|
-
assert_equal false, person_klass.columns_hash["money"].null
|
1138
|
-
end
|
1139
|
-
|
1140
|
-
# change column
|
1141
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1142
|
-
person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
|
1143
|
-
person_klass.reset_column_information
|
1144
|
-
assert_equal 1000, person_klass.columns_hash["money"].default
|
1145
|
-
assert_equal false, person_klass.columns_hash["money"].null
|
1146
|
-
else
|
1147
|
-
person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 15, :scale => 1,:null => false, :default => 1000
|
1148
|
-
person_klass.reset_column_information
|
1149
|
-
assert_equal 1000, person_klass.columns_hash["wealth"].default
|
1150
|
-
assert_equal false, person_klass.columns_hash["wealth"].null
|
1151
|
-
end
|
1152
|
-
|
1153
|
-
# change column, make it nullable and clear default
|
1154
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1155
|
-
person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
|
1156
|
-
person_klass.reset_column_information
|
1157
|
-
assert_nil person_klass.columns_hash["money"].default
|
1158
|
-
assert_equal true, person_klass.columns_hash["money"].null
|
1159
|
-
else
|
1160
|
-
person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 20, :scale => 2, :null => true, :default => nil
|
1161
|
-
person_klass.reset_column_information
|
1162
|
-
assert_nil person_klass.columns_hash["wealth"].default
|
1163
|
-
assert_equal true, person_klass.columns_hash["wealth"].null
|
1164
|
-
end
|
1165
|
-
|
1166
|
-
# change_column_null, make it not nullable and set null values to a default value
|
1167
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1168
|
-
person_klass.connection.execute('UPDATE testings SET money = NULL')
|
1169
|
-
person_klass.connection.change_column_null "testings", "money", false, 2000
|
1170
|
-
person_klass.reset_column_information
|
1171
|
-
assert_nil person_klass.columns_hash["money"].default
|
1172
|
-
assert_equal false, person_klass.columns_hash["money"].null
|
1173
|
-
assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
|
1174
|
-
else
|
1175
|
-
# Trying to set the value of the column wealth to NULL and
|
1176
|
-
# in the next statement a not null constraint is being applied which is wrong
|
1177
|
-
#person_klass.connection.execute('UPDATE testings SET money = NULL')
|
1178
|
-
person_klass.connection.change_column_null "testings", "wealth", false, 2000
|
1179
|
-
person_klass.reset_column_information
|
1180
|
-
#assert_nil person_klass.columns_hash["wealth"].default #Setting default to 2000 and expecting nil is nor correct
|
1181
|
-
assert_not_nil person_klass.columns_hash["wealth"].default
|
1182
|
-
assert_equal false, person_klass.columns_hash["wealth"].null
|
1183
|
-
#Changing default does not change the already inserted value. Hence expecting 2000 is wrong.
|
1184
|
-
assert_equal [99], Person.connection.select_values("SELECT wealth FROM testings").map { |s| s.to_i }.sort
|
1185
|
-
end
|
1186
|
-
ensure
|
1187
|
-
Person.connection.drop_table :testings rescue nil
|
1188
|
-
end
|
1189
|
-
|
1190
|
-
def test_change_column_default_to_null
|
1191
|
-
Person.connection.change_column_default "people", "first_name", nil
|
1192
|
-
Person.reset_column_information
|
1193
|
-
assert_nil Person.new.first_name
|
1194
|
-
end
|
1195
|
-
|
1196
|
-
def test_column_exists
|
1197
|
-
Person.connection.create_table :testings do |t|
|
1198
|
-
t.column :foo, :string
|
1199
|
-
end
|
1200
|
-
|
1201
|
-
assert Person.connection.column_exists?(:testings, :foo)
|
1202
|
-
assert !Person.connection.column_exists?(:testings, :bar)
|
1203
|
-
ensure
|
1204
|
-
Person.connection.drop_table :testings rescue nil
|
1205
|
-
end
|
1206
|
-
|
1207
|
-
def test_column_exists_with_type
|
1208
|
-
Person.connection.create_table :testings do |t|
|
1209
|
-
t.column :foo, :string
|
1210
|
-
t.column :bar, :decimal, :precision => 8, :scale => 2
|
1211
|
-
end
|
1212
|
-
|
1213
|
-
assert Person.connection.column_exists?(:testings, :foo, :string)
|
1214
|
-
assert !Person.connection.column_exists?(:testings, :foo, :integer)
|
1215
|
-
assert Person.connection.column_exists?(:testings, :bar, :decimal)
|
1216
|
-
assert !Person.connection.column_exists?(:testings, :bar, :integer)
|
1217
|
-
ensure
|
1218
|
-
Person.connection.drop_table :testings rescue nil
|
1219
|
-
end
|
1220
|
-
|
1221
|
-
def test_column_exists_with_definition
|
1222
|
-
Person.connection.create_table :testings do |t|
|
1223
|
-
t.column :foo, :string, :limit => 100
|
1224
|
-
t.column :bar, :decimal, :precision => 8, :scale => 2
|
1225
|
-
end
|
1226
|
-
|
1227
|
-
assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100)
|
1228
|
-
assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50)
|
1229
|
-
assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2)
|
1230
|
-
assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2)
|
1231
|
-
ensure
|
1232
|
-
Person.connection.drop_table :testings rescue nil
|
1233
|
-
end
|
1234
|
-
|
1235
|
-
def test_column_exists_on_table_with_no_options_parameter_supplied
|
1236
|
-
Person.connection.create_table :testings do |t|
|
1237
|
-
t.string :foo
|
1238
|
-
end
|
1239
|
-
Person.connection.change_table :testings do |t|
|
1240
|
-
assert t.column_exists?(:foo)
|
1241
|
-
assert !(t.column_exists?(:bar))
|
1242
|
-
end
|
1243
|
-
ensure
|
1244
|
-
Person.connection.drop_table :testings rescue nil
|
1245
|
-
end
|
1246
|
-
|
1247
|
-
def test_add_table
|
1248
|
-
assert !Reminder.table_exists?
|
1249
|
-
|
1250
|
-
WeNeedReminders.up
|
1251
|
-
|
1252
|
-
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1253
|
-
assert_equal "hello world", Reminder.find(:first).content
|
1254
|
-
|
1255
|
-
WeNeedReminders.down
|
1256
|
-
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1257
|
-
end
|
1258
|
-
|
1259
|
-
def test_add_table_with_decimals
|
1260
|
-
Person.connection.drop_table :big_numbers rescue nil
|
1261
|
-
|
1262
|
-
assert !BigNumber.table_exists?
|
1263
|
-
GiveMeBigNumbers.up
|
1264
|
-
|
1265
|
-
assert BigNumber.create(
|
1266
|
-
:bank_balance => 1586.43,
|
1267
|
-
:big_bank_balance => BigDecimal("1000234000567.95"),
|
1268
|
-
:world_population => 6000000000,
|
1269
|
-
:my_house_population => 3,
|
1270
|
-
:value_of_e => BigDecimal("2.7182818284590452353602875")
|
1271
|
-
)
|
1272
|
-
|
1273
|
-
b = BigNumber.find(:first)
|
1274
|
-
assert_not_nil b
|
1275
|
-
|
1276
|
-
assert_not_nil b.bank_balance
|
1277
|
-
assert_not_nil b.big_bank_balance
|
1278
|
-
assert_not_nil b.world_population
|
1279
|
-
assert_not_nil b.my_house_population
|
1280
|
-
assert_not_nil b.value_of_e
|
1281
|
-
|
1282
|
-
# TODO: set world_population >= 2**62 to cover 64-bit platforms and test
|
1283
|
-
# is_a?(Bignum)
|
1284
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1285
|
-
assert_kind_of Integer, b.world_population
|
1286
|
-
else
|
1287
|
-
assert_kind_of BigDecimal, b.world_population
|
1288
|
-
end
|
1289
|
-
assert_equal 6000000000, b.world_population
|
1290
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1291
|
-
assert_kind_of Fixnum, b.my_house_population
|
1292
|
-
else
|
1293
|
-
assert_kind_of BigDecimal, b.my_house_population
|
1294
|
-
end
|
1295
|
-
assert_equal 3, b.my_house_population
|
1296
|
-
assert_kind_of BigDecimal, b.bank_balance
|
1297
|
-
assert_equal BigDecimal("1586.43"), b.bank_balance
|
1298
|
-
assert_kind_of BigDecimal, b.big_bank_balance
|
1299
|
-
assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
|
1300
|
-
|
1301
|
-
# This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
|
1302
|
-
# precision/scale explicitly left out. By the SQL standard, numbers
|
1303
|
-
# assigned to this field should be truncated but that's seldom respected.
|
1304
|
-
if current_adapter?(:PostgreSQLAdapter)
|
1305
|
-
# - PostgreSQL changes the SQL spec on columns declared simply as
|
1306
|
-
# "decimal" to something more useful: instead of being given a scale
|
1307
|
-
# of 0, they take on the compile-time limit for precision and scale,
|
1308
|
-
# so the following should succeed unless you have used really wacky
|
1309
|
-
# compilation options
|
1310
|
-
# - SQLite2 has the default behavior of preserving all data sent in,
|
1311
|
-
# so this happens there too
|
1312
|
-
assert_kind_of BigDecimal, b.value_of_e
|
1313
|
-
assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
|
1314
|
-
elsif current_adapter?(:SQLite3Adapter)
|
1315
|
-
# - SQLite3 stores a float, in violation of SQL
|
1316
|
-
assert_kind_of BigDecimal, b.value_of_e
|
1317
|
-
assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
|
1318
|
-
else
|
1319
|
-
# - SQL standard is an integer
|
1320
|
-
unless current_adapter?(:IBM_DBAdapter)
|
1321
|
-
assert_kind_of Fixnum, b.value_of_e
|
1322
|
-
else
|
1323
|
-
assert_kind_of BigDecimal, b.value_of_e
|
1324
|
-
end
|
1325
|
-
assert_equal 2, b.value_of_e
|
1326
|
-
end
|
1327
|
-
|
1328
|
-
GiveMeBigNumbers.down
|
1329
|
-
assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
|
1330
|
-
end
|
1331
|
-
|
1332
|
-
def test_migrator
|
1333
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1334
|
-
assert !Reminder.table_exists?
|
1335
|
-
|
1336
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
|
1337
|
-
|
1338
|
-
assert_equal 3, ActiveRecord::Migrator.current_version
|
1339
|
-
Person.reset_column_information
|
1340
|
-
assert Person.column_methods_hash.include?(:last_name)
|
1341
|
-
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1342
|
-
assert_equal "hello world", Reminder.find(:first).content
|
1343
|
-
|
1344
|
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
|
1345
|
-
|
1346
|
-
assert_equal 0, ActiveRecord::Migrator.current_version
|
1347
|
-
Person.reset_column_information
|
1348
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1349
|
-
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1350
|
-
end
|
1351
|
-
|
1352
|
-
def test_filtering_migrations
|
1353
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1354
|
-
assert !Reminder.table_exists?
|
1355
|
-
|
1356
|
-
name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
|
1357
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
|
1358
|
-
|
1359
|
-
Person.reset_column_information
|
1360
|
-
assert Person.column_methods_hash.include?(:last_name)
|
1361
|
-
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1362
|
-
|
1363
|
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
|
1364
|
-
|
1365
|
-
Person.reset_column_information
|
1366
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1367
|
-
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1368
|
-
end
|
1369
|
-
|
1370
|
-
class MockMigration < ActiveRecord::Migration
|
1371
|
-
attr_reader :went_up, :went_down
|
1372
|
-
def initialize
|
1373
|
-
@went_up = false
|
1374
|
-
@went_down = false
|
1375
|
-
end
|
1376
|
-
|
1377
|
-
def up
|
1378
|
-
@went_up = true
|
1379
|
-
super
|
1380
|
-
end
|
1381
|
-
|
1382
|
-
def down
|
1383
|
-
@went_down = true
|
1384
|
-
super
|
1385
|
-
end
|
1386
|
-
end
|
1387
|
-
|
1388
|
-
def test_instance_based_migration_up
|
1389
|
-
migration = MockMigration.new
|
1390
|
-
assert !migration.went_up, 'have not gone up'
|
1391
|
-
assert !migration.went_down, 'have not gone down'
|
1392
|
-
|
1393
|
-
migration.migrate :up
|
1394
|
-
assert migration.went_up, 'have gone up'
|
1395
|
-
assert !migration.went_down, 'have not gone down'
|
1396
|
-
end
|
1397
|
-
|
1398
|
-
def test_instance_based_migration_down
|
1399
|
-
migration = MockMigration.new
|
1400
|
-
assert !migration.went_up, 'have not gone up'
|
1401
|
-
assert !migration.went_down, 'have not gone down'
|
1402
|
-
|
1403
|
-
migration.migrate :down
|
1404
|
-
assert !migration.went_up, 'have gone up'
|
1405
|
-
assert migration.went_down, 'have not gone down'
|
1406
|
-
end
|
1407
|
-
|
1408
|
-
def test_migrator_one_up
|
1409
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1410
|
-
assert !Reminder.table_exists?
|
1411
|
-
|
1412
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1413
|
-
|
1414
|
-
Person.reset_column_information
|
1415
|
-
assert Person.column_methods_hash.include?(:last_name)
|
1416
|
-
assert !Reminder.table_exists?
|
1417
|
-
|
1418
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
|
1419
|
-
|
1420
|
-
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1421
|
-
assert_equal "hello world", Reminder.find(:first).content
|
1422
|
-
end
|
1423
|
-
|
1424
|
-
def test_migrator_one_down
|
1425
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
|
1426
|
-
|
1427
|
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
|
1428
|
-
|
1429
|
-
Person.reset_column_information
|
1430
|
-
assert Person.column_methods_hash.include?(:last_name)
|
1431
|
-
assert !Reminder.table_exists?
|
1432
|
-
end
|
1433
|
-
|
1434
|
-
def test_migrator_one_up_one_down
|
1435
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1436
|
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
|
1437
|
-
|
1438
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1439
|
-
assert !Reminder.table_exists?
|
1440
|
-
end
|
1441
|
-
|
1442
|
-
def test_migrator_double_up
|
1443
|
-
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1444
|
-
ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
|
1445
|
-
assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) }
|
1446
|
-
assert_equal(1, ActiveRecord::Migrator.current_version)
|
1447
|
-
end
|
1448
|
-
|
1449
|
-
def test_migrator_double_down
|
1450
|
-
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1451
|
-
ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
|
1452
|
-
ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1)
|
1453
|
-
assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) }
|
1454
|
-
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1455
|
-
end
|
1456
|
-
|
1457
|
-
if ActiveRecord::Base.connection.supports_ddl_transactions?
|
1458
|
-
def test_migrator_one_up_with_exception_and_rollback
|
1459
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1460
|
-
|
1461
|
-
e = assert_raise(StandardError) do
|
1462
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
|
1463
|
-
end
|
1464
|
-
|
1465
|
-
assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
|
1466
|
-
|
1467
|
-
Person.reset_column_information
|
1468
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1469
|
-
end
|
1470
|
-
end
|
1471
|
-
|
1472
|
-
def test_finds_migrations
|
1473
|
-
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
|
1474
|
-
|
1475
|
-
[[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
|
1476
|
-
assert_equal migrations[i].version, pair.first
|
1477
|
-
assert_equal migrations[i].name, pair.last
|
1478
|
-
end
|
1479
|
-
end
|
1480
|
-
|
1481
|
-
def test_finds_migrations_in_subdirectories
|
1482
|
-
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations
|
1483
|
-
|
1484
|
-
[[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
|
1485
|
-
assert_equal migrations[i].version, pair.first
|
1486
|
-
assert_equal migrations[i].name, pair.last
|
1487
|
-
end
|
1488
|
-
end
|
1489
|
-
|
1490
|
-
def test_finds_migrations_from_two_directories
|
1491
|
-
directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps']
|
1492
|
-
migrations = ActiveRecord::Migrator.new(:up, directories).migrations
|
1493
|
-
|
1494
|
-
[[20090101010101, "PeopleHaveHobbies"],
|
1495
|
-
[20090101010202, "PeopleHaveDescriptions"],
|
1496
|
-
[20100101010101, "ValidWithTimestampsPeopleHaveLastNames"],
|
1497
|
-
[20100201010101, "ValidWithTimestampsWeNeedReminders"],
|
1498
|
-
[20100301010101, "ValidWithTimestampsInnocentJointable"]].each_with_index do |pair, i|
|
1499
|
-
assert_equal pair.first, migrations[i].version
|
1500
|
-
assert_equal pair.last, migrations[i].name
|
1501
|
-
end
|
1502
|
-
end
|
1503
|
-
|
1504
|
-
def test_dump_schema_information_outputs_lexically_ordered_versions
|
1505
|
-
migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps'
|
1506
|
-
ActiveRecord::Migrator.run(:up, migration_path, 20100301010101)
|
1507
|
-
ActiveRecord::Migrator.run(:up, migration_path, 20100201010101)
|
1508
|
-
|
1509
|
-
schema_info = ActiveRecord::Base.connection.dump_schema_information
|
1510
|
-
assert_match(/20100201010101.*20100301010101/m, schema_info)
|
1511
|
-
end
|
1512
|
-
|
1513
|
-
def test_finds_pending_migrations
|
1514
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
|
1515
|
-
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
|
1516
|
-
|
1517
|
-
assert_equal 1, migrations.size
|
1518
|
-
assert_equal migrations[0].version, 3
|
1519
|
-
assert_equal migrations[0].name, 'InterleavedInnocentJointable'
|
1520
|
-
end
|
1521
|
-
|
1522
|
-
def test_relative_migrations
|
1523
|
-
list = Dir.chdir(MIGRATIONS_ROOT) do
|
1524
|
-
ActiveRecord::Migrator.up("valid/", 1)
|
1525
|
-
end
|
1526
|
-
|
1527
|
-
migration_proxy = list.find { |item|
|
1528
|
-
item.name == 'ValidPeopleHaveLastNames'
|
1529
|
-
}
|
1530
|
-
assert migration_proxy, 'should find pending migration'
|
1531
|
-
end
|
1532
|
-
|
1533
|
-
def test_only_loads_pending_migrations
|
1534
|
-
# migrate up to 1
|
1535
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1536
|
-
|
1537
|
-
proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
|
1538
|
-
|
1539
|
-
names = proxies.map(&:name)
|
1540
|
-
assert !names.include?('ValidPeopleHaveLastNames')
|
1541
|
-
assert names.include?('WeNeedReminders')
|
1542
|
-
assert names.include?('InnocentJointable')
|
1543
|
-
end
|
1544
|
-
|
1545
|
-
def test_target_version_zero_should_run_only_once
|
1546
|
-
# migrate up to 1
|
1547
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
|
1548
|
-
|
1549
|
-
# migrate down to 0
|
1550
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
|
1551
|
-
|
1552
|
-
# migrate down to 0 again
|
1553
|
-
proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
|
1554
|
-
assert_equal [], proxies
|
1555
|
-
end
|
1556
|
-
|
1557
|
-
def test_migrator_db_has_no_schema_migrations_table
|
1558
|
-
# Oracle adapter raises error if semicolon is present as last character
|
1559
|
-
if current_adapter?(:OracleAdapter)
|
1560
|
-
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
|
1561
|
-
else
|
1562
|
-
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
|
1563
|
-
end
|
1564
|
-
assert_nothing_raised do
|
1565
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
|
1566
|
-
end
|
1567
|
-
end
|
1568
|
-
|
1569
|
-
def test_migrator_verbosity
|
1570
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1571
|
-
assert_not_equal 0, ActiveRecord::Migration.message_count
|
1572
|
-
ActiveRecord::Migration.message_count = 0
|
1573
|
-
|
1574
|
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
|
1575
|
-
assert_not_equal 0, ActiveRecord::Migration.message_count
|
1576
|
-
ActiveRecord::Migration.message_count = 0
|
1577
|
-
end
|
1578
|
-
|
1579
|
-
def test_migrator_verbosity_off
|
1580
|
-
ActiveRecord::Migration.verbose = false
|
1581
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1582
|
-
assert_equal 0, ActiveRecord::Migration.message_count
|
1583
|
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
|
1584
|
-
assert_equal 0, ActiveRecord::Migration.message_count
|
1585
|
-
end
|
1586
|
-
|
1587
|
-
def test_migrator_going_down_due_to_version_target
|
1588
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1589
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
|
1590
|
-
|
1591
|
-
assert !Person.column_methods_hash.include?(:last_name)
|
1592
|
-
assert !Reminder.table_exists?
|
1593
|
-
|
1594
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1595
|
-
|
1596
|
-
Person.reset_column_information
|
1597
|
-
assert Person.column_methods_hash.include?(:last_name)
|
1598
|
-
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1599
|
-
assert_equal "hello world", Reminder.find(:first).content
|
1600
|
-
end
|
1601
|
-
|
1602
|
-
def test_migrator_rollback
|
1603
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1604
|
-
assert_equal(3, ActiveRecord::Migrator.current_version)
|
1605
|
-
|
1606
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1607
|
-
assert_equal(2, ActiveRecord::Migrator.current_version)
|
1608
|
-
|
1609
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1610
|
-
assert_equal(1, ActiveRecord::Migrator.current_version)
|
1611
|
-
|
1612
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1613
|
-
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1614
|
-
|
1615
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1616
|
-
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1617
|
-
end
|
1618
|
-
|
1619
|
-
def test_migrator_forward
|
1620
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
|
1621
|
-
assert_equal(1, ActiveRecord::Migrator.current_version)
|
1622
|
-
|
1623
|
-
ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid", 2)
|
1624
|
-
assert_equal(3, ActiveRecord::Migrator.current_version)
|
1625
|
-
|
1626
|
-
ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid")
|
1627
|
-
assert_equal(3, ActiveRecord::Migrator.current_version)
|
1628
|
-
end
|
1629
|
-
|
1630
|
-
def test_get_all_versions
|
1631
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1632
|
-
assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions)
|
1633
|
-
|
1634
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1635
|
-
assert_equal([1,2], ActiveRecord::Migrator.get_all_versions)
|
1636
|
-
|
1637
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1638
|
-
assert_equal([1], ActiveRecord::Migrator.get_all_versions)
|
1639
|
-
|
1640
|
-
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1641
|
-
assert_equal([], ActiveRecord::Migrator.get_all_versions)
|
1642
|
-
end
|
1643
|
-
|
1644
|
-
def test_schema_migrations_table_name
|
1645
|
-
ActiveRecord::Base.table_name_prefix = "prefix_"
|
1646
|
-
ActiveRecord::Base.table_name_suffix = "_suffix"
|
1647
|
-
Reminder.reset_table_name
|
1648
|
-
assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
|
1649
|
-
ActiveRecord::Base.table_name_prefix = ""
|
1650
|
-
ActiveRecord::Base.table_name_suffix = ""
|
1651
|
-
Reminder.reset_table_name
|
1652
|
-
assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
|
1653
|
-
ensure
|
1654
|
-
ActiveRecord::Base.table_name_prefix = ""
|
1655
|
-
ActiveRecord::Base.table_name_suffix = ""
|
1656
|
-
end
|
1657
|
-
|
1658
|
-
def test_proper_table_name
|
1659
|
-
assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
|
1660
|
-
assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
|
1661
|
-
assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
|
1662
|
-
Reminder.reset_table_name
|
1663
|
-
assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
|
1664
|
-
|
1665
|
-
# Use the model's own prefix/suffix if a model is given
|
1666
|
-
ActiveRecord::Base.table_name_prefix = "ARprefix_"
|
1667
|
-
ActiveRecord::Base.table_name_suffix = "_ARsuffix"
|
1668
|
-
Reminder.table_name_prefix = 'prefix_'
|
1669
|
-
Reminder.table_name_suffix = '_suffix'
|
1670
|
-
Reminder.reset_table_name
|
1671
|
-
assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
|
1672
|
-
Reminder.table_name_prefix = ''
|
1673
|
-
Reminder.table_name_suffix = ''
|
1674
|
-
Reminder.reset_table_name
|
1675
|
-
|
1676
|
-
# Use AR::Base's prefix/suffix if string or symbol is given
|
1677
|
-
ActiveRecord::Base.table_name_prefix = "prefix_"
|
1678
|
-
ActiveRecord::Base.table_name_suffix = "_suffix"
|
1679
|
-
Reminder.reset_table_name
|
1680
|
-
assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
|
1681
|
-
assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
|
1682
|
-
ActiveRecord::Base.table_name_prefix = ""
|
1683
|
-
ActiveRecord::Base.table_name_suffix = ""
|
1684
|
-
Reminder.reset_table_name
|
1685
|
-
end
|
1686
|
-
|
1687
|
-
def test_rename_table_with_prefix_and_suffix
|
1688
|
-
assert !Thing.table_exists?
|
1689
|
-
ActiveRecord::Base.table_name_prefix = 'prefix_'
|
1690
|
-
ActiveRecord::Base.table_name_suffix = '_suffix'
|
1691
|
-
Thing.reset_table_name
|
1692
|
-
Thing.reset_sequence_name
|
1693
|
-
WeNeedThings.up
|
1694
|
-
|
1695
|
-
assert Thing.create("content" => "hello world")
|
1696
|
-
assert_equal "hello world", Thing.find(:first).content
|
1697
|
-
|
1698
|
-
RenameThings.up
|
1699
|
-
Thing.table_name = "prefix_awesome_things_suffix"
|
1700
|
-
|
1701
|
-
assert_equal "hello world", Thing.find(:first).content
|
1702
|
-
ensure
|
1703
|
-
ActiveRecord::Base.table_name_prefix = ''
|
1704
|
-
ActiveRecord::Base.table_name_suffix = ''
|
1705
|
-
Thing.reset_table_name
|
1706
|
-
Thing.reset_sequence_name
|
1707
|
-
end
|
1708
|
-
|
1709
|
-
def test_add_drop_table_with_prefix_and_suffix
|
1710
|
-
assert !Reminder.table_exists?
|
1711
|
-
ActiveRecord::Base.table_name_prefix = 'prefix_'
|
1712
|
-
ActiveRecord::Base.table_name_suffix = '_suffix'
|
1713
|
-
Reminder.reset_table_name
|
1714
|
-
Reminder.reset_sequence_name
|
1715
|
-
WeNeedReminders.up
|
1716
|
-
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1717
|
-
assert_equal "hello world", Reminder.find(:first).content
|
1718
|
-
|
1719
|
-
WeNeedReminders.down
|
1720
|
-
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1721
|
-
ensure
|
1722
|
-
ActiveRecord::Base.table_name_prefix = ''
|
1723
|
-
ActiveRecord::Base.table_name_suffix = ''
|
1724
|
-
Reminder.reset_table_name
|
1725
|
-
Reminder.reset_sequence_name
|
1726
|
-
end
|
1727
|
-
|
1728
|
-
def test_create_table_with_binary_column
|
1729
|
-
Person.connection.drop_table :binary_testings rescue nil
|
1730
|
-
|
1731
|
-
assert_nothing_raised {
|
1732
|
-
Person.connection.create_table :binary_testings do |t|
|
1733
|
-
t.column "data", :binary, :null => false
|
1734
|
-
end
|
1735
|
-
}
|
1736
|
-
|
1737
|
-
columns = Person.connection.columns(:binary_testings)
|
1738
|
-
data_column = columns.detect { |c| c.name == "data" }
|
1739
|
-
|
1740
|
-
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
1741
|
-
assert_equal '', data_column.default
|
1742
|
-
else
|
1743
|
-
assert_nil data_column.default
|
1744
|
-
end
|
1745
|
-
|
1746
|
-
Person.connection.drop_table :binary_testings rescue nil
|
1747
|
-
end
|
1748
|
-
|
1749
|
-
def test_migrator_with_duplicates
|
1750
|
-
assert_raise(ActiveRecord::DuplicateMigrationVersionError) do
|
1751
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
|
1752
|
-
end
|
1753
|
-
end
|
1754
|
-
|
1755
|
-
def test_migrator_with_duplicate_names
|
1756
|
-
assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
|
1757
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
|
1758
|
-
end
|
1759
|
-
end
|
1760
|
-
|
1761
|
-
def test_migrator_with_missing_version_numbers
|
1762
|
-
assert_raise(ActiveRecord::UnknownMigrationVersionError) do
|
1763
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
|
1764
|
-
end
|
1765
|
-
end
|
1766
|
-
|
1767
|
-
def test_create_table_with_custom_sequence_name
|
1768
|
-
return unless current_adapter? :OracleAdapter
|
1769
|
-
|
1770
|
-
# table name is 29 chars, the standard sequence name will
|
1771
|
-
# be 33 chars and should be shortened
|
1772
|
-
assert_nothing_raised do
|
1773
|
-
begin
|
1774
|
-
Person.connection.create_table :table_with_name_thats_just_ok do |t|
|
1775
|
-
t.column :foo, :string, :null => false
|
1776
|
-
end
|
1777
|
-
ensure
|
1778
|
-
Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
|
1779
|
-
end
|
1780
|
-
end
|
1781
|
-
|
1782
|
-
# should be all good w/ a custom sequence name
|
1783
|
-
assert_nothing_raised do
|
1784
|
-
begin
|
1785
|
-
Person.connection.create_table :table_with_name_thats_just_ok,
|
1786
|
-
:sequence_name => 'suitably_short_seq' do |t|
|
1787
|
-
t.column :foo, :string, :null => false
|
1788
|
-
end
|
1789
|
-
|
1790
|
-
Person.connection.execute("select suitably_short_seq.nextval from dual")
|
1791
|
-
|
1792
|
-
ensure
|
1793
|
-
Person.connection.drop_table :table_with_name_thats_just_ok,
|
1794
|
-
:sequence_name => 'suitably_short_seq' rescue nil
|
1795
|
-
end
|
1796
|
-
end
|
1797
|
-
|
1798
|
-
# confirm the custom sequence got dropped
|
1799
|
-
assert_raise(ActiveRecord::StatementInvalid) do
|
1800
|
-
Person.connection.execute("select suitably_short_seq.nextval from dual")
|
1801
|
-
end
|
1802
|
-
end
|
1803
|
-
|
1804
|
-
protected
|
1805
|
-
def with_env_tz(new_tz = 'US/Eastern')
|
1806
|
-
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
|
1807
|
-
yield
|
1808
|
-
ensure
|
1809
|
-
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
|
1810
|
-
end
|
1811
|
-
|
1812
|
-
end
|
1813
|
-
|
1814
|
-
class MigrationLoggerTest < ActiveRecord::TestCase
|
1815
|
-
def test_migration_should_be_run_without_logger
|
1816
|
-
previous_logger = ActiveRecord::Base.logger
|
1817
|
-
ActiveRecord::Base.logger = nil
|
1818
|
-
assert_nothing_raised do
|
1819
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1820
|
-
end
|
1821
|
-
ensure
|
1822
|
-
ActiveRecord::Base.logger = previous_logger
|
1823
|
-
end
|
1824
|
-
end
|
1825
|
-
|
1826
|
-
class InterleavedMigrationsTest < ActiveRecord::TestCase
|
1827
|
-
def test_migrator_interleaved_migrations
|
1828
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
|
1829
|
-
|
1830
|
-
assert_nothing_raised do
|
1831
|
-
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
|
1832
|
-
end
|
1833
|
-
|
1834
|
-
Person.reset_column_information
|
1835
|
-
assert Person.column_methods_hash.include?(:last_name)
|
1836
|
-
|
1837
|
-
assert_nothing_raised do
|
1838
|
-
proxies = ActiveRecord::Migrator.down(
|
1839
|
-
MIGRATIONS_ROOT + "/interleaved/pass_3")
|
1840
|
-
names = proxies.map(&:name)
|
1841
|
-
assert names.include?('InterleavedPeopleHaveLastNames')
|
1842
|
-
assert names.include?('InterleavedInnocentJointable')
|
1843
|
-
end
|
1844
|
-
end
|
1845
|
-
end
|
1846
|
-
|
1847
|
-
class ReservedWordsMigrationTest < ActiveRecord::TestCase
|
1848
|
-
def test_drop_index_from_table_named_values
|
1849
|
-
connection = Person.connection
|
1850
|
-
connection.create_table :values, :force => true do |t|
|
1851
|
-
t.integer :value
|
1852
|
-
end
|
1853
|
-
|
1854
|
-
assert_nothing_raised do
|
1855
|
-
connection.add_index :values, :value
|
1856
|
-
connection.remove_index :values, :column => :value
|
1857
|
-
end
|
1858
|
-
|
1859
|
-
connection.drop_table :values rescue nil
|
1860
|
-
end
|
1861
|
-
end
|
1862
|
-
|
1863
|
-
|
1864
|
-
class ChangeTableMigrationsTest < ActiveRecord::TestCase
|
1865
|
-
def setup
|
1866
|
-
@connection = Person.connection
|
1867
|
-
@connection.create_table :delete_me, :force => true do |t|
|
1868
|
-
end
|
1869
|
-
end
|
1870
|
-
|
1871
|
-
def teardown
|
1872
|
-
Person.connection.drop_table :delete_me rescue nil
|
1873
|
-
end
|
1874
|
-
|
1875
|
-
def test_references_column_type_adds_id
|
1876
|
-
with_change_table do |t|
|
1877
|
-
@connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
|
1878
|
-
t.references :customer
|
1879
|
-
end
|
1880
|
-
end
|
1881
|
-
|
1882
|
-
def test_remove_references_column_type_removes_id
|
1883
|
-
with_change_table do |t|
|
1884
|
-
@connection.expects(:remove_column).with(:delete_me, 'customer_id')
|
1885
|
-
t.remove_references :customer
|
1886
|
-
end
|
1887
|
-
end
|
1888
|
-
|
1889
|
-
def test_add_belongs_to_works_like_add_references
|
1890
|
-
with_change_table do |t|
|
1891
|
-
@connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
|
1892
|
-
t.belongs_to :customer
|
1893
|
-
end
|
1894
|
-
end
|
1895
|
-
|
1896
|
-
def test_remove_belongs_to_works_like_remove_references
|
1897
|
-
with_change_table do |t|
|
1898
|
-
@connection.expects(:remove_column).with(:delete_me, 'customer_id')
|
1899
|
-
t.remove_belongs_to :customer
|
1900
|
-
end
|
1901
|
-
end
|
1902
|
-
|
1903
|
-
def test_references_column_type_with_polymorphic_adds_type
|
1904
|
-
with_change_table do |t|
|
1905
|
-
@connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
|
1906
|
-
@connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
|
1907
|
-
t.references :taggable, :polymorphic => true
|
1908
|
-
end
|
1909
|
-
end
|
1910
|
-
|
1911
|
-
def test_remove_references_column_type_with_polymorphic_removes_type
|
1912
|
-
with_change_table do |t|
|
1913
|
-
@connection.expects(:remove_column).with(:delete_me, 'taggable_type')
|
1914
|
-
@connection.expects(:remove_column).with(:delete_me, 'taggable_id')
|
1915
|
-
t.remove_references :taggable, :polymorphic => true
|
1916
|
-
end
|
1917
|
-
end
|
1918
|
-
|
1919
|
-
def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
|
1920
|
-
with_change_table do |t|
|
1921
|
-
@connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
|
1922
|
-
@connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
|
1923
|
-
t.references :taggable, :polymorphic => true, :null => false
|
1924
|
-
end
|
1925
|
-
end
|
1926
|
-
|
1927
|
-
def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
|
1928
|
-
with_change_table do |t|
|
1929
|
-
@connection.expects(:remove_column).with(:delete_me, 'taggable_type')
|
1930
|
-
@connection.expects(:remove_column).with(:delete_me, 'taggable_id')
|
1931
|
-
t.remove_references :taggable, :polymorphic => true, :null => false
|
1932
|
-
end
|
1933
|
-
end
|
1934
|
-
|
1935
|
-
def test_timestamps_creates_updated_at_and_created_at
|
1936
|
-
with_change_table do |t|
|
1937
|
-
@connection.expects(:add_timestamps).with(:delete_me)
|
1938
|
-
t.timestamps
|
1939
|
-
end
|
1940
|
-
end
|
1941
|
-
|
1942
|
-
def test_remove_timestamps_creates_updated_at_and_created_at
|
1943
|
-
with_change_table do |t|
|
1944
|
-
@connection.expects(:remove_timestamps).with(:delete_me)
|
1945
|
-
t.remove_timestamps
|
1946
|
-
end
|
1947
|
-
end
|
1948
|
-
|
1949
|
-
def string_column
|
1950
|
-
if current_adapter?(:PostgreSQLAdapter)
|
1951
|
-
"character varying(255)"
|
1952
|
-
elsif current_adapter?(:OracleAdapter)
|
1953
|
-
'VARCHAR2(255)'
|
1954
|
-
else
|
1955
|
-
'varchar(255)'
|
1956
|
-
end
|
1957
|
-
end
|
1958
|
-
|
1959
|
-
def integer_column
|
1960
|
-
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
1961
|
-
'int(11)'
|
1962
|
-
elsif current_adapter?(:OracleAdapter)
|
1963
|
-
'NUMBER(38)'
|
1964
|
-
else
|
1965
|
-
'integer'
|
1966
|
-
end
|
1967
|
-
end
|
1968
|
-
|
1969
|
-
def test_integer_creates_integer_column
|
1970
|
-
with_change_table do |t|
|
1971
|
-
@connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
|
1972
|
-
@connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
|
1973
|
-
t.integer :foo, :bar
|
1974
|
-
end
|
1975
|
-
end
|
1976
|
-
|
1977
|
-
def test_string_creates_string_column
|
1978
|
-
with_change_table do |t|
|
1979
|
-
@connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
|
1980
|
-
@connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
|
1981
|
-
t.string :foo, :bar
|
1982
|
-
end
|
1983
|
-
end
|
1984
|
-
|
1985
|
-
def test_column_creates_column
|
1986
|
-
with_change_table do |t|
|
1987
|
-
@connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
|
1988
|
-
t.column :bar, :integer
|
1989
|
-
end
|
1990
|
-
end
|
1991
|
-
|
1992
|
-
def test_column_creates_column_with_options
|
1993
|
-
with_change_table do |t|
|
1994
|
-
@connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
|
1995
|
-
t.column :bar, :integer, :null => false
|
1996
|
-
end
|
1997
|
-
end
|
1998
|
-
|
1999
|
-
def test_index_creates_index
|
2000
|
-
with_change_table do |t|
|
2001
|
-
@connection.expects(:add_index).with(:delete_me, :bar, {})
|
2002
|
-
t.index :bar
|
2003
|
-
end
|
2004
|
-
end
|
2005
|
-
|
2006
|
-
def test_index_creates_index_with_options
|
2007
|
-
with_change_table do |t|
|
2008
|
-
@connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
|
2009
|
-
t.index :bar, :unique => true
|
2010
|
-
end
|
2011
|
-
end
|
2012
|
-
|
2013
|
-
def test_index_exists
|
2014
|
-
with_change_table do |t|
|
2015
|
-
@connection.expects(:index_exists?).with(:delete_me, :bar, {})
|
2016
|
-
t.index_exists?(:bar)
|
2017
|
-
end
|
2018
|
-
end
|
2019
|
-
|
2020
|
-
def test_index_exists_with_options
|
2021
|
-
with_change_table do |t|
|
2022
|
-
@connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true})
|
2023
|
-
t.index_exists?(:bar, :unique => true)
|
2024
|
-
end
|
2025
|
-
end
|
2026
|
-
|
2027
|
-
def test_change_changes_column
|
2028
|
-
with_change_table do |t|
|
2029
|
-
@connection.expects(:change_column).with(:delete_me, :bar, :string, {})
|
2030
|
-
t.change :bar, :string
|
2031
|
-
end
|
2032
|
-
end
|
2033
|
-
|
2034
|
-
def test_change_changes_column_with_options
|
2035
|
-
with_change_table do |t|
|
2036
|
-
@connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
|
2037
|
-
t.change :bar, :string, :null => true
|
2038
|
-
end
|
2039
|
-
end
|
2040
|
-
|
2041
|
-
def test_change_default_changes_column
|
2042
|
-
with_change_table do |t|
|
2043
|
-
@connection.expects(:change_column_default).with(:delete_me, :bar, :string)
|
2044
|
-
t.change_default :bar, :string
|
2045
|
-
end
|
2046
|
-
end
|
2047
|
-
|
2048
|
-
def test_remove_drops_single_column
|
2049
|
-
with_change_table do |t|
|
2050
|
-
@connection.expects(:remove_column).with(:delete_me, [:bar])
|
2051
|
-
t.remove :bar
|
2052
|
-
end
|
2053
|
-
end
|
2054
|
-
|
2055
|
-
def test_remove_drops_multiple_columns
|
2056
|
-
with_change_table do |t|
|
2057
|
-
@connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
|
2058
|
-
t.remove :bar, :baz
|
2059
|
-
end
|
2060
|
-
end
|
2061
|
-
|
2062
|
-
def test_remove_index_removes_index_with_options
|
2063
|
-
with_change_table do |t|
|
2064
|
-
@connection.expects(:remove_index).with(:delete_me, {:unique => true})
|
2065
|
-
t.remove_index :unique => true
|
2066
|
-
end
|
2067
|
-
end
|
2068
|
-
|
2069
|
-
def test_rename_renames_column
|
2070
|
-
with_change_table do |t|
|
2071
|
-
@connection.expects(:rename_column).with(:delete_me, :bar, :baz)
|
2072
|
-
t.rename :bar, :baz
|
2073
|
-
end
|
2074
|
-
end
|
2075
|
-
|
2076
|
-
protected
|
2077
|
-
def with_change_table
|
2078
|
-
Person.connection.change_table :delete_me do |t|
|
2079
|
-
yield t
|
2080
|
-
end
|
2081
|
-
end
|
2082
|
-
end
|
2083
|
-
|
2084
|
-
if ActiveRecord::Base.connection.supports_bulk_alter?
|
2085
|
-
class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
|
2086
|
-
def setup
|
2087
|
-
@connection = Person.connection
|
2088
|
-
@connection.create_table(:delete_me, :force => true) {|t| }
|
2089
|
-
end
|
2090
|
-
|
2091
|
-
def teardown
|
2092
|
-
Person.connection.drop_table(:delete_me) rescue nil
|
2093
|
-
end
|
2094
|
-
|
2095
|
-
def test_adding_multiple_columns
|
2096
|
-
assert_queries(1) do
|
2097
|
-
with_bulk_change_table do |t|
|
2098
|
-
t.column :name, :string
|
2099
|
-
t.string :qualification, :experience
|
2100
|
-
t.integer :age, :default => 0
|
2101
|
-
t.date :birthdate
|
2102
|
-
t.timestamps
|
2103
|
-
end
|
2104
|
-
end
|
2105
|
-
|
2106
|
-
assert_equal 8, columns.size
|
2107
|
-
[:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
|
2108
|
-
assert_equal 0, column(:age).default
|
2109
|
-
end
|
2110
|
-
|
2111
|
-
def test_removing_columns
|
2112
|
-
with_bulk_change_table do |t|
|
2113
|
-
t.string :qualification, :experience
|
2114
|
-
end
|
2115
|
-
|
2116
|
-
[:qualification, :experience].each {|c| assert column(c) }
|
2117
|
-
|
2118
|
-
assert_queries(1) do
|
2119
|
-
with_bulk_change_table do |t|
|
2120
|
-
t.remove :qualification, :experience
|
2121
|
-
t.string :qualification_experience
|
2122
|
-
end
|
2123
|
-
end
|
2124
|
-
|
2125
|
-
[:qualification, :experience].each {|c| assert ! column(c) }
|
2126
|
-
assert column(:qualification_experience)
|
2127
|
-
end
|
2128
|
-
|
2129
|
-
def test_adding_indexes
|
2130
|
-
with_bulk_change_table do |t|
|
2131
|
-
t.string :username
|
2132
|
-
t.string :name
|
2133
|
-
t.integer :age
|
2134
|
-
end
|
2135
|
-
|
2136
|
-
# Adding an index fires a query every time to check if an index already exists or not
|
2137
|
-
assert_queries(3) do
|
2138
|
-
with_bulk_change_table do |t|
|
2139
|
-
t.index :username, :unique => true, :name => :awesome_username_index
|
2140
|
-
t.index [:name, :age]
|
2141
|
-
end
|
2142
|
-
end
|
2143
|
-
|
2144
|
-
assert_equal 2, indexes.size
|
2145
|
-
|
2146
|
-
name_age_index = index(:index_delete_me_on_name_and_age)
|
2147
|
-
assert_equal ['name', 'age'].sort, name_age_index.columns.sort
|
2148
|
-
assert ! name_age_index.unique
|
2149
|
-
|
2150
|
-
assert index(:awesome_username_index).unique
|
2151
|
-
end
|
2152
|
-
|
2153
|
-
def test_removing_index
|
2154
|
-
with_bulk_change_table do |t|
|
2155
|
-
t.string :name
|
2156
|
-
t.index :name
|
2157
|
-
end
|
2158
|
-
|
2159
|
-
assert index(:index_delete_me_on_name)
|
2160
|
-
|
2161
|
-
assert_queries(3) do
|
2162
|
-
with_bulk_change_table do |t|
|
2163
|
-
t.remove_index :name
|
2164
|
-
t.index :name, :name => :new_name_index, :unique => true
|
2165
|
-
end
|
2166
|
-
end
|
2167
|
-
|
2168
|
-
assert ! index(:index_delete_me_on_name)
|
2169
|
-
|
2170
|
-
new_name_index = index(:new_name_index)
|
2171
|
-
assert new_name_index.unique
|
2172
|
-
end
|
2173
|
-
|
2174
|
-
def test_changing_columns
|
2175
|
-
with_bulk_change_table do |t|
|
2176
|
-
t.string :name
|
2177
|
-
t.date :birthdate
|
2178
|
-
end
|
2179
|
-
|
2180
|
-
assert ! column(:name).default
|
2181
|
-
assert_equal :date, column(:birthdate).type
|
2182
|
-
|
2183
|
-
# One query for columns (delete_me table)
|
2184
|
-
# One query for primary key (delete_me table)
|
2185
|
-
# One query to do the bulk change
|
2186
|
-
assert_queries(3) do
|
2187
|
-
with_bulk_change_table do |t|
|
2188
|
-
t.change :name, :string, :default => 'NONAME'
|
2189
|
-
t.change :birthdate, :datetime
|
2190
|
-
end
|
2191
|
-
end
|
2192
|
-
|
2193
|
-
assert_equal 'NONAME', column(:name).default
|
2194
|
-
assert_equal :datetime, column(:birthdate).type
|
2195
|
-
end
|
2196
|
-
|
2197
|
-
protected
|
2198
|
-
|
2199
|
-
def with_bulk_change_table
|
2200
|
-
# Reset columns/indexes cache as we're changing the table
|
2201
|
-
@columns = @indexes = nil
|
2202
|
-
|
2203
|
-
Person.connection.change_table(:delete_me, :bulk => true) do |t|
|
2204
|
-
yield t
|
2205
|
-
end
|
2206
|
-
end
|
2207
|
-
|
2208
|
-
def column(name)
|
2209
|
-
columns.detect {|c| c.name == name.to_s }
|
2210
|
-
end
|
2211
|
-
|
2212
|
-
def columns
|
2213
|
-
@columns ||= Person.connection.columns('delete_me')
|
2214
|
-
end
|
2215
|
-
|
2216
|
-
def index(name)
|
2217
|
-
indexes.detect {|i| i.name == name.to_s }
|
2218
|
-
end
|
2219
|
-
|
2220
|
-
def indexes
|
2221
|
-
@indexes ||= Person.connection.indexes('delete_me')
|
2222
|
-
end
|
2223
|
-
end # AlterTableMigrationsTest
|
2224
|
-
|
2225
|
-
end
|
2226
|
-
|
2227
|
-
class CopyMigrationsTest < ActiveRecord::TestCase
|
2228
|
-
def setup
|
2229
|
-
end
|
2230
|
-
|
2231
|
-
def clear
|
2232
|
-
ActiveRecord::Base.timestamped_migrations = true
|
2233
|
-
to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
|
2234
|
-
File.delete(*to_delete)
|
2235
|
-
end
|
2236
|
-
|
2237
|
-
def test_copying_migrations_without_timestamps
|
2238
|
-
ActiveRecord::Base.timestamped_migrations = false
|
2239
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid"
|
2240
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2241
|
-
|
2242
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
|
2243
|
-
assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
|
2244
|
-
assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
|
2245
|
-
assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
|
2246
|
-
|
2247
|
-
expected = "# This migration comes from bukkits (originally 1)"
|
2248
|
-
assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
|
2249
|
-
|
2250
|
-
files_count = Dir[@migrations_path + "/*.rb"].length
|
2251
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
|
2252
|
-
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2253
|
-
assert copied.empty?
|
2254
|
-
ensure
|
2255
|
-
clear
|
2256
|
-
end
|
2257
|
-
|
2258
|
-
def test_copying_migrations_without_timestamps_from_2_sources
|
2259
|
-
ActiveRecord::Base.timestamped_migrations = false
|
2260
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid"
|
2261
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2262
|
-
|
2263
|
-
sources = ActiveSupport::OrderedHash.new
|
2264
|
-
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
|
2265
|
-
sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
|
2266
|
-
ActiveRecord::Migration.copy(@migrations_path, sources)
|
2267
|
-
assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
|
2268
|
-
assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
|
2269
|
-
assert File.exists?(@migrations_path + "/6_create_articles.omg.rb")
|
2270
|
-
assert File.exists?(@migrations_path + "/7_create_comments.omg.rb")
|
2271
|
-
|
2272
|
-
files_count = Dir[@migrations_path + "/*.rb"].length
|
2273
|
-
ActiveRecord::Migration.copy(@migrations_path, sources)
|
2274
|
-
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2275
|
-
ensure
|
2276
|
-
clear
|
2277
|
-
end
|
2278
|
-
|
2279
|
-
def test_copying_migrations_with_timestamps
|
2280
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2281
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2282
|
-
|
2283
|
-
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2284
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2285
|
-
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2286
|
-
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2287
|
-
expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
|
2288
|
-
@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
|
2289
|
-
assert_equal expected, copied.map(&:filename)
|
2290
|
-
|
2291
|
-
files_count = Dir[@migrations_path + "/*.rb"].length
|
2292
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2293
|
-
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2294
|
-
assert copied.empty?
|
2295
|
-
end
|
2296
|
-
ensure
|
2297
|
-
clear
|
2298
|
-
end
|
2299
|
-
|
2300
|
-
def test_copying_migrations_with_timestamps_from_2_sources
|
2301
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2302
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2303
|
-
|
2304
|
-
sources = ActiveSupport::OrderedHash.new
|
2305
|
-
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
|
2306
|
-
sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
|
2307
|
-
|
2308
|
-
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2309
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, sources)
|
2310
|
-
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2311
|
-
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2312
|
-
assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb")
|
2313
|
-
assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb")
|
2314
|
-
assert_equal 4, copied.length
|
2315
|
-
|
2316
|
-
files_count = Dir[@migrations_path + "/*.rb"].length
|
2317
|
-
ActiveRecord::Migration.copy(@migrations_path, sources)
|
2318
|
-
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2319
|
-
end
|
2320
|
-
ensure
|
2321
|
-
clear
|
2322
|
-
end
|
2323
|
-
|
2324
|
-
def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
|
2325
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2326
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2327
|
-
|
2328
|
-
Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
|
2329
|
-
ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2330
|
-
assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
|
2331
|
-
assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
|
2332
|
-
|
2333
|
-
files_count = Dir[@migrations_path + "/*.rb"].length
|
2334
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2335
|
-
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2336
|
-
assert copied.empty?
|
2337
|
-
end
|
2338
|
-
ensure
|
2339
|
-
clear
|
2340
|
-
end
|
2341
|
-
|
2342
|
-
def test_skipping_migrations
|
2343
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2344
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2345
|
-
|
2346
|
-
sources = ActiveSupport::OrderedHash.new
|
2347
|
-
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
|
2348
|
-
sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
|
2349
|
-
|
2350
|
-
skipped = []
|
2351
|
-
on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
|
2352
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
|
2353
|
-
assert_equal 2, copied.length
|
2354
|
-
|
2355
|
-
assert_equal 1, skipped.length
|
2356
|
-
assert_equal ["omg PeopleHaveHobbies"], skipped
|
2357
|
-
ensure
|
2358
|
-
clear
|
2359
|
-
end
|
2360
|
-
|
2361
|
-
def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
|
2362
|
-
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2363
|
-
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2364
|
-
|
2365
|
-
sources = ActiveSupport::OrderedHash.new
|
2366
|
-
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
|
2367
|
-
|
2368
|
-
skipped = []
|
2369
|
-
on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
|
2370
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
|
2371
|
-
ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
|
2372
|
-
|
2373
|
-
assert_equal 2, copied.length
|
2374
|
-
assert_equal 0, skipped.length
|
2375
|
-
ensure
|
2376
|
-
clear
|
2377
|
-
end
|
2378
|
-
|
2379
|
-
def test_copying_migrations_to_non_existing_directory
|
2380
|
-
@migrations_path = MIGRATIONS_ROOT + "/non_existing"
|
2381
|
-
@existing_migrations = []
|
2382
|
-
|
2383
|
-
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2384
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2385
|
-
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2386
|
-
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2387
|
-
assert_equal 2, copied.length
|
2388
|
-
end
|
2389
|
-
ensure
|
2390
|
-
clear
|
2391
|
-
Dir.delete(@migrations_path)
|
2392
|
-
end
|
2393
|
-
|
2394
|
-
def test_copying_migrations_to_empty_directory
|
2395
|
-
@migrations_path = MIGRATIONS_ROOT + "/empty"
|
2396
|
-
@existing_migrations = []
|
2397
|
-
|
2398
|
-
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2399
|
-
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2400
|
-
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2401
|
-
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2402
|
-
assert_equal 2, copied.length
|
2403
|
-
end
|
2404
|
-
ensure
|
2405
|
-
clear
|
2406
|
-
end
|
2407
|
-
end
|
2408
|
-
end
|
1
|
+
require "cases/helper"
|
2
|
+
require 'bigdecimal/util'
|
3
|
+
|
4
|
+
require 'models/person'
|
5
|
+
require 'models/topic'
|
6
|
+
require 'models/developer'
|
7
|
+
|
8
|
+
require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
|
9
|
+
require MIGRATIONS_ROOT + "/rename/1_we_need_things"
|
10
|
+
require MIGRATIONS_ROOT + "/rename/2_rename_things"
|
11
|
+
require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
|
12
|
+
|
13
|
+
if ActiveRecord::Base.connection.supports_migrations?
|
14
|
+
class BigNumber < ActiveRecord::Base; end
|
15
|
+
|
16
|
+
class Reminder < ActiveRecord::Base; end
|
17
|
+
|
18
|
+
class Thing < ActiveRecord::Base; end
|
19
|
+
|
20
|
+
class ActiveRecord::Migration
|
21
|
+
class << self
|
22
|
+
attr_accessor :message_count
|
23
|
+
end
|
24
|
+
|
25
|
+
def puts(text="")
|
26
|
+
ActiveRecord::Migration.message_count ||= 0
|
27
|
+
ActiveRecord::Migration.message_count += 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class MigrationTableAndIndexTest < ActiveRecord::TestCase
|
32
|
+
def test_add_schema_info_respects_prefix_and_suffix
|
33
|
+
conn = ActiveRecord::Base.connection
|
34
|
+
|
35
|
+
conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
|
36
|
+
# Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
|
37
|
+
ActiveRecord::Base.table_name_prefix = 'p_'
|
38
|
+
ActiveRecord::Base.table_name_suffix = '_s'
|
39
|
+
conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
|
40
|
+
|
41
|
+
conn.initialize_schema_migrations_table
|
42
|
+
|
43
|
+
assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
|
44
|
+
ensure
|
45
|
+
ActiveRecord::Base.table_name_prefix = ""
|
46
|
+
ActiveRecord::Base.table_name_suffix = ""
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class MigrationTest < ActiveRecord::TestCase
|
51
|
+
self.use_transactional_fixtures = false
|
52
|
+
|
53
|
+
if (current_adapter?(:IBM_DBAdapter))
|
54
|
+
#Rename is supported only for server zOS 9 , DB2 COBRA and Informix
|
55
|
+
server_type = ActiveRecord::Base.connection.servertype.class.name
|
56
|
+
@ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
|
57
|
+
server_type.class.name.include?('::IBM_IDS') ||
|
58
|
+
(server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
|
59
|
+
end
|
60
|
+
|
61
|
+
fixtures :people
|
62
|
+
|
63
|
+
def setup
|
64
|
+
ActiveRecord::Migration.verbose = true
|
65
|
+
ActiveRecord::Migration.message_count = 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def teardown
|
69
|
+
ActiveRecord::Base.connection.initialize_schema_migrations_table
|
70
|
+
ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
|
71
|
+
|
72
|
+
%w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table|
|
73
|
+
Thing.connection.drop_table(table) rescue nil
|
74
|
+
end
|
75
|
+
Thing.reset_column_information
|
76
|
+
|
77
|
+
%w(reminders people_reminders prefix_reminders_suffix).each do |table|
|
78
|
+
Reminder.connection.drop_table(table) rescue nil
|
79
|
+
end
|
80
|
+
Reminder.reset_column_information
|
81
|
+
|
82
|
+
%w(last_name key bio age height wealth birthday favorite_day
|
83
|
+
moment_of_truth male administrator funny).each do |column|
|
84
|
+
Person.connection.remove_column('people', column) rescue nil
|
85
|
+
end
|
86
|
+
Person.connection.remove_column("people", "first_name") rescue nil
|
87
|
+
Person.connection.remove_column("people", "middle_name") rescue nil
|
88
|
+
Person.connection.add_column("people", "first_name", :string, :limit => 40)
|
89
|
+
Person.reset_column_information
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_add_index
|
93
|
+
# Limit size of last_name and key columns to support Firebird index limitations
|
94
|
+
Person.connection.add_column "people", "last_name", :string, :limit => 100
|
95
|
+
Person.connection.add_column "people", "key", :string, :limit => 100
|
96
|
+
Person.connection.add_column "people", "administrator", :boolean
|
97
|
+
|
98
|
+
assert_nothing_raised { Person.connection.add_index("people", "last_name") }
|
99
|
+
assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
|
100
|
+
|
101
|
+
# Orcl nds shrt indx nms. Sybs 2.
|
102
|
+
# OpenBase does not have named indexes. You must specify a single column name
|
103
|
+
unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
|
104
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
105
|
+
assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
|
106
|
+
# Oracle adapter cannot have specified index name larger than 30 characters
|
107
|
+
# Oracle adapter is shortening index name when just column list is given
|
108
|
+
unless current_adapter?(:OracleAdapter)
|
109
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
110
|
+
assert_nothing_raised { Person.connection.remove_index("people", :name => :index_people_on_last_name_and_first_name) }
|
111
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
112
|
+
assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
|
113
|
+
end
|
114
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
115
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
116
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
|
117
|
+
assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
|
118
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) }
|
119
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
|
120
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) }
|
121
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
122
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) }
|
123
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
124
|
+
end
|
125
|
+
|
126
|
+
# quoting
|
127
|
+
# Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
|
128
|
+
# OpenBase does not have named indexes. You must specify a single column name
|
129
|
+
unless current_adapter?(:OpenBaseAdapter)
|
130
|
+
unless current_adapter?(:IBM_DBAdapter)
|
131
|
+
Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique)
|
132
|
+
else
|
133
|
+
Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'first_name'}"
|
134
|
+
end
|
135
|
+
assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
|
136
|
+
assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
|
137
|
+
end
|
138
|
+
|
139
|
+
# Sybase adapter does not support indexes on :boolean columns
|
140
|
+
# OpenBase does not have named indexes. You must specify a single column
|
141
|
+
unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
|
142
|
+
assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
|
143
|
+
assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
|
144
|
+
end
|
145
|
+
|
146
|
+
# Selected adapters support index sort order
|
147
|
+
if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
148
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) }
|
149
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
|
150
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) }
|
151
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
152
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) }
|
153
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
154
|
+
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) }
|
155
|
+
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_index_symbol_names
|
160
|
+
assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name }
|
161
|
+
assert Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
|
162
|
+
assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name }
|
163
|
+
assert !Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_add_index_length_limit
|
167
|
+
good_index_name = 'x' * Person.connection.index_name_length
|
168
|
+
too_long_index_name = good_index_name + 'x'
|
169
|
+
assert_raise(ArgumentError) { Person.connection.add_index("people", "first_name", :name => too_long_index_name) }
|
170
|
+
assert !Person.connection.index_name_exists?("people", too_long_index_name, false)
|
171
|
+
assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) }
|
172
|
+
assert Person.connection.index_name_exists?("people", good_index_name, false)
|
173
|
+
Person.connection.remove_index("people", :name => good_index_name)
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_add_index_attribute_length_limit
|
177
|
+
Person.connection.add_index :people, [:first_name, :primary_contact_id], :length => {:first_name => 10, :primary_contact_id => nil}, :name => "attribute_length"
|
178
|
+
assert Person.connection.index_exists?(:people, [:first_name, :primary_contact_id], :name => "attribute_length")
|
179
|
+
ensure
|
180
|
+
Person.connection.remove_index(:people, :name => "attribute_length")
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_remove_nonexistent_index
|
184
|
+
# we do this by name, so OpenBase is a wash as noted above
|
185
|
+
unless current_adapter?(:OpenBaseAdapter)
|
186
|
+
assert_raise(ArgumentError) { Person.connection.remove_index("people", "no_such_index") }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_rename_index
|
191
|
+
unless current_adapter?(:OpenBaseAdapter)
|
192
|
+
# keep the names short to make Oracle and similar behave
|
193
|
+
Person.connection.add_index('people', [:first_name], :name => 'old_idx')
|
194
|
+
assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') }
|
195
|
+
# if the adapter doesn't support the indexes call, pick defaults that let the test pass
|
196
|
+
assert !Person.connection.index_name_exists?('people', 'old_idx', false)
|
197
|
+
assert Person.connection.index_name_exists?('people', 'new_idx', true)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_double_add_index
|
202
|
+
unless current_adapter?(:OpenBaseAdapter)
|
203
|
+
Person.connection.add_index('people', [:first_name], :name => 'some_idx')
|
204
|
+
assert_raise(ArgumentError) { Person.connection.add_index('people', [:first_name], :name => 'some_idx') }
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_index_exists
|
209
|
+
Person.connection.create_table :testings do |t|
|
210
|
+
t.column :foo, :string, :limit => 100
|
211
|
+
t.column :bar, :string, :limit => 100
|
212
|
+
end
|
213
|
+
Person.connection.add_index :testings, :foo
|
214
|
+
|
215
|
+
assert Person.connection.index_exists?(:testings, :foo)
|
216
|
+
assert !Person.connection.index_exists?(:testings, :bar)
|
217
|
+
ensure
|
218
|
+
Person.connection.drop_table :testings rescue nil
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_index_exists_on_multiple_columns
|
222
|
+
Person.connection.create_table :testings do |t|
|
223
|
+
t.column :foo, :string, :limit => 100
|
224
|
+
t.column :bar, :string, :limit => 100
|
225
|
+
end
|
226
|
+
Person.connection.add_index :testings, [:foo, :bar]
|
227
|
+
|
228
|
+
assert Person.connection.index_exists?(:testings, [:foo, :bar])
|
229
|
+
ensure
|
230
|
+
Person.connection.drop_table :testings rescue nil
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_unique_index_exists
|
234
|
+
Person.connection.create_table :testings do |t|
|
235
|
+
t.column :foo, :string, :limit => 100
|
236
|
+
end
|
237
|
+
Person.connection.add_index :testings, :foo, :unique => true
|
238
|
+
|
239
|
+
assert Person.connection.index_exists?(:testings, :foo, :unique => true)
|
240
|
+
ensure
|
241
|
+
Person.connection.drop_table :testings rescue nil
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_named_index_exists
|
245
|
+
Person.connection.create_table :testings do |t|
|
246
|
+
t.column :foo, :string, :limit => 100
|
247
|
+
end
|
248
|
+
Person.connection.add_index :testings, :foo, :name => "custom_index_name"
|
249
|
+
|
250
|
+
assert Person.connection.index_exists?(:testings, :foo, :name => "custom_index_name")
|
251
|
+
ensure
|
252
|
+
Person.connection.drop_table :testings rescue nil
|
253
|
+
end
|
254
|
+
|
255
|
+
def testing_table_with_only_foo_attribute
|
256
|
+
Person.connection.create_table :testings, :id => false do |t|
|
257
|
+
t.column :foo, :string
|
258
|
+
end
|
259
|
+
|
260
|
+
yield Person.connection
|
261
|
+
ensure
|
262
|
+
Person.connection.drop_table :testings rescue nil
|
263
|
+
end
|
264
|
+
protected :testing_table_with_only_foo_attribute
|
265
|
+
|
266
|
+
def test_create_table_without_id
|
267
|
+
testing_table_with_only_foo_attribute do |connection|
|
268
|
+
assert_equal connection.columns(:testings).size, 1
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
unless current_adapter?(:IBM_DBAdapter)
|
273
|
+
# For DB2: Cannot add a primary key to a table with some rows already in it as it violates the unique constraint
|
274
|
+
# Secondly GENERATED BY DEFAULT AS IDENTITY cannot be applied in a alter table command.
|
275
|
+
# as this will be wrong sql syntax for DB
|
276
|
+
def test_add_column_with_primary_key_attribute
|
277
|
+
testing_table_with_only_foo_attribute do |connection|
|
278
|
+
assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
|
279
|
+
assert_equal connection.columns(:testings).size, 2
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_create_table_adds_id
|
285
|
+
Person.connection.create_table :testings do |t|
|
286
|
+
t.column :foo, :string
|
287
|
+
end
|
288
|
+
|
289
|
+
assert_equal %w(foo id),
|
290
|
+
Person.connection.columns(:testings).map { |c| c.name }.sort
|
291
|
+
ensure
|
292
|
+
Person.connection.drop_table :testings rescue nil
|
293
|
+
end
|
294
|
+
|
295
|
+
def test_create_table_with_not_null_column
|
296
|
+
assert_nothing_raised do
|
297
|
+
Person.connection.create_table :testings do |t|
|
298
|
+
t.column :foo, :string, :null => false
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
303
|
+
Person.connection.execute "insert into testings (foo) values (NULL)"
|
304
|
+
end
|
305
|
+
ensure
|
306
|
+
Person.connection.drop_table :testings rescue nil
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_create_table_with_defaults
|
310
|
+
# MySQL doesn't allow defaults on TEXT or BLOB columns.
|
311
|
+
mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
|
312
|
+
|
313
|
+
Person.connection.create_table :testings do |t|
|
314
|
+
t.column :one, :string, :default => "hello"
|
315
|
+
t.column :two, :boolean, :default => true
|
316
|
+
t.column :three, :boolean, :default => false
|
317
|
+
t.column :four, :integer, :default => 1
|
318
|
+
t.column :five, :text, :default => "hello" unless mysql
|
319
|
+
end
|
320
|
+
|
321
|
+
columns = Person.connection.columns(:testings)
|
322
|
+
one = columns.detect { |c| c.name == "one" }
|
323
|
+
two = columns.detect { |c| c.name == "two" }
|
324
|
+
three = columns.detect { |c| c.name == "three" }
|
325
|
+
four = columns.detect { |c| c.name == "four" }
|
326
|
+
five = columns.detect { |c| c.name == "five" } unless mysql
|
327
|
+
|
328
|
+
assert_equal "hello", one.default
|
329
|
+
assert_equal true, two.default
|
330
|
+
assert_equal false, three.default
|
331
|
+
assert_equal 1, four.default
|
332
|
+
assert_equal "hello", five.default unless mysql
|
333
|
+
|
334
|
+
ensure
|
335
|
+
Person.connection.drop_table :testings rescue nil
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_create_table_with_limits
|
339
|
+
assert_nothing_raised do
|
340
|
+
Person.connection.create_table :testings do |t|
|
341
|
+
t.column :foo, :string, :limit => 255
|
342
|
+
|
343
|
+
t.column :default_int, :integer
|
344
|
+
|
345
|
+
t.column :one_int, :integer, :limit => 1
|
346
|
+
t.column :four_int, :integer, :limit => 4
|
347
|
+
t.column :eight_int, :integer, :limit => 8
|
348
|
+
t.column :eleven_int, :integer, :limit => 11
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
columns = Person.connection.columns(:testings)
|
353
|
+
foo = columns.detect { |c| c.name == "foo" }
|
354
|
+
assert_equal 255, foo.limit
|
355
|
+
|
356
|
+
default = columns.detect { |c| c.name == "default_int" }
|
357
|
+
one = columns.detect { |c| c.name == "one_int" }
|
358
|
+
four = columns.detect { |c| c.name == "four_int" }
|
359
|
+
eight = columns.detect { |c| c.name == "eight_int" }
|
360
|
+
eleven = columns.detect { |c| c.name == "eleven_int" }
|
361
|
+
|
362
|
+
if current_adapter?(:PostgreSQLAdapter)
|
363
|
+
assert_equal 'integer', default.sql_type
|
364
|
+
assert_equal 'smallint', one.sql_type
|
365
|
+
assert_equal 'integer', four.sql_type
|
366
|
+
assert_equal 'bigint', eight.sql_type
|
367
|
+
assert_equal 'integer', eleven.sql_type
|
368
|
+
elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
369
|
+
assert_match 'int(11)', default.sql_type
|
370
|
+
assert_match 'tinyint', one.sql_type
|
371
|
+
assert_match 'int', four.sql_type
|
372
|
+
assert_match 'bigint', eight.sql_type
|
373
|
+
assert_match 'int(11)', eleven.sql_type
|
374
|
+
elsif current_adapter?(:OracleAdapter)
|
375
|
+
assert_equal 'NUMBER(38)', default.sql_type
|
376
|
+
assert_equal 'NUMBER(1)', one.sql_type
|
377
|
+
assert_equal 'NUMBER(4)', four.sql_type
|
378
|
+
assert_equal 'NUMBER(8)', eight.sql_type
|
379
|
+
end
|
380
|
+
ensure
|
381
|
+
Person.connection.drop_table :testings rescue nil
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
|
385
|
+
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
|
386
|
+
|
387
|
+
Person.connection.create_table :testings do |t|
|
388
|
+
t.column :foo, :string
|
389
|
+
end
|
390
|
+
|
391
|
+
assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort
|
392
|
+
ensure
|
393
|
+
Person.connection.drop_table :testings rescue nil
|
394
|
+
ActiveRecord::Base.primary_key_prefix_type = nil
|
395
|
+
end
|
396
|
+
|
397
|
+
def test_create_table_with_primary_key_prefix_as_table_name
|
398
|
+
ActiveRecord::Base.primary_key_prefix_type = :table_name
|
399
|
+
|
400
|
+
Person.connection.create_table :testings do |t|
|
401
|
+
t.column :foo, :string
|
402
|
+
end
|
403
|
+
|
404
|
+
assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort
|
405
|
+
ensure
|
406
|
+
Person.connection.drop_table :testings rescue nil
|
407
|
+
ActiveRecord::Base.primary_key_prefix_type = nil
|
408
|
+
end
|
409
|
+
|
410
|
+
def test_create_table_with_force_true_does_not_drop_nonexisting_table
|
411
|
+
if Person.connection.table_exists?(:testings2)
|
412
|
+
Person.connection.drop_table :testings2
|
413
|
+
end
|
414
|
+
|
415
|
+
# using a copy as we need the drop_table method to
|
416
|
+
# continue to work for the ensure block of the test
|
417
|
+
temp_conn = Person.connection.dup
|
418
|
+
temp_conn.expects(:drop_table).never
|
419
|
+
temp_conn.create_table :testings2, :force => true do |t|
|
420
|
+
t.column :foo, :string
|
421
|
+
end
|
422
|
+
ensure
|
423
|
+
Person.connection.drop_table :testings2 rescue nil
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_create_table_with_timestamps_should_create_datetime_columns
|
427
|
+
table_name = :testings
|
428
|
+
|
429
|
+
Person.connection.create_table table_name do |t|
|
430
|
+
t.timestamps
|
431
|
+
end
|
432
|
+
created_columns = Person.connection.columns(table_name)
|
433
|
+
|
434
|
+
created_at_column = created_columns.detect {|c| c.name == 'created_at' }
|
435
|
+
updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
|
436
|
+
|
437
|
+
assert !created_at_column.null
|
438
|
+
assert !updated_at_column.null
|
439
|
+
ensure
|
440
|
+
Person.connection.drop_table table_name rescue nil
|
441
|
+
end
|
442
|
+
|
443
|
+
def test_create_table_with_timestamps_should_create_datetime_columns_with_options
|
444
|
+
table_name = :testings
|
445
|
+
|
446
|
+
Person.connection.create_table table_name do |t|
|
447
|
+
t.timestamps :null => false
|
448
|
+
end
|
449
|
+
created_columns = Person.connection.columns(table_name)
|
450
|
+
|
451
|
+
created_at_column = created_columns.detect {|c| c.name == 'created_at' }
|
452
|
+
updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
|
453
|
+
|
454
|
+
assert !created_at_column.null
|
455
|
+
assert !updated_at_column.null
|
456
|
+
ensure
|
457
|
+
Person.connection.drop_table table_name rescue nil
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_create_table_without_a_block
|
461
|
+
table_name = :testings
|
462
|
+
Person.connection.create_table table_name
|
463
|
+
ensure
|
464
|
+
Person.connection.drop_table table_name rescue nil
|
465
|
+
end
|
466
|
+
|
467
|
+
# Sybase, and SQLite3 will not allow you to add a NOT NULL
|
468
|
+
# column to a table without a default value.
|
469
|
+
unless current_adapter?(:SybaseAdapter, :SQLite3Adapter, :IBM_DBAdapter)
|
470
|
+
def test_add_column_not_null_without_default
|
471
|
+
Person.connection.create_table :testings do |t|
|
472
|
+
t.column :foo, :string
|
473
|
+
end
|
474
|
+
Person.connection.add_column :testings, :bar, :string, :null => false
|
475
|
+
|
476
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
477
|
+
Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
|
478
|
+
end
|
479
|
+
ensure
|
480
|
+
Person.connection.drop_table :testings rescue nil
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
def test_add_column_not_null_with_default
|
485
|
+
Person.connection.create_table :testings do |t|
|
486
|
+
t.column :foo, :string
|
487
|
+
end
|
488
|
+
|
489
|
+
con = Person.connection
|
490
|
+
Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
|
491
|
+
Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
|
492
|
+
Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
|
493
|
+
assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
|
494
|
+
|
495
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
496
|
+
unless current_adapter?(:OpenBaseAdapter)
|
497
|
+
Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)"
|
498
|
+
else
|
499
|
+
Person.connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)",
|
500
|
+
"Testing Insert","id",2)
|
501
|
+
end
|
502
|
+
end
|
503
|
+
ensure
|
504
|
+
Person.connection.drop_table :testings rescue nil
|
505
|
+
end
|
506
|
+
|
507
|
+
# We specifically do a manual INSERT here, and then test only the SELECT
|
508
|
+
# functionality. This allows us to more easily catch INSERT being broken,
|
509
|
+
# but SELECT actually working fine.
|
510
|
+
def test_native_decimal_insert_manual_vs_automatic
|
511
|
+
correct_value = '0012345678901234567890.0123456789'.to_d
|
512
|
+
|
513
|
+
Person.delete_all
|
514
|
+
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
515
|
+
Person.reset_column_information
|
516
|
+
|
517
|
+
# Do a manual insertion
|
518
|
+
if current_adapter?(:OracleAdapter)
|
519
|
+
Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)"
|
520
|
+
elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
|
521
|
+
Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)"
|
522
|
+
elsif current_adapter?(:PostgreSQLAdapter)
|
523
|
+
Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())"
|
524
|
+
elsif current_adapter?(:IBM_DBAdapter)
|
525
|
+
Person.connection.execute "insert into people (wealth, created_at, updated_at, lock_version, first_name) values (12345678901234567890.0123456789, CURRENT TIMESTAMP, CURRENT TIMESTAMP, 0, 'Jim')"
|
526
|
+
else
|
527
|
+
Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
|
528
|
+
end
|
529
|
+
|
530
|
+
# SELECT
|
531
|
+
row = Person.find(:first)
|
532
|
+
assert_kind_of BigDecimal, row.wealth
|
533
|
+
|
534
|
+
# If this assert fails, that means the SELECT is broken!
|
535
|
+
unless current_adapter?(:SQLite3Adapter)
|
536
|
+
assert_equal correct_value, row.wealth
|
537
|
+
end
|
538
|
+
|
539
|
+
# Reset to old state
|
540
|
+
Person.delete_all
|
541
|
+
|
542
|
+
# Now use the Rails insertion
|
543
|
+
unless current_adapter?(:IBM_DBAdapter)
|
544
|
+
assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
|
545
|
+
else
|
546
|
+
# First_name is a not null column, hence ensure a value is specified
|
547
|
+
assert_nothing_raised { Person.create ({:wealth => BigDecimal.new("12345678901234567890.0123456789"), :first_name => "James"}) }
|
548
|
+
end
|
549
|
+
|
550
|
+
# SELECT
|
551
|
+
row = Person.find(:first)
|
552
|
+
assert_kind_of BigDecimal, row.wealth
|
553
|
+
|
554
|
+
# If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
|
555
|
+
unless current_adapter?(:SQLite3Adapter)
|
556
|
+
assert_equal correct_value, row.wealth
|
557
|
+
end
|
558
|
+
|
559
|
+
# Reset to old state
|
560
|
+
Person.connection.del_column "people", "wealth" rescue nil
|
561
|
+
Person.reset_column_information
|
562
|
+
end
|
563
|
+
|
564
|
+
def test_add_column_with_precision_and_scale
|
565
|
+
Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
|
566
|
+
Person.reset_column_information
|
567
|
+
|
568
|
+
wealth_column = Person.columns_hash['wealth']
|
569
|
+
assert_equal 9, wealth_column.precision
|
570
|
+
assert_equal 7, wealth_column.scale
|
571
|
+
end
|
572
|
+
|
573
|
+
# Test SQLite adapter specifically for decimal types with precision and scale
|
574
|
+
# attributes, since these need to be maintained in schema but aren't actually
|
575
|
+
# used in SQLite itself
|
576
|
+
if current_adapter?(:SQLite3Adapter)
|
577
|
+
def test_change_column_with_new_precision_and_scale
|
578
|
+
Person.delete_all
|
579
|
+
Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
|
580
|
+
Person.reset_column_information
|
581
|
+
|
582
|
+
Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8
|
583
|
+
Person.reset_column_information
|
584
|
+
|
585
|
+
wealth_column = Person.columns_hash['wealth']
|
586
|
+
assert_equal 12, wealth_column.precision
|
587
|
+
assert_equal 8, wealth_column.scale
|
588
|
+
end
|
589
|
+
|
590
|
+
def test_change_column_preserve_other_column_precision_and_scale
|
591
|
+
Person.delete_all
|
592
|
+
Person.connection.add_column 'people', 'last_name', :string
|
593
|
+
Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
|
594
|
+
Person.reset_column_information
|
595
|
+
|
596
|
+
wealth_column = Person.columns_hash['wealth']
|
597
|
+
assert_equal 9, wealth_column.precision
|
598
|
+
assert_equal 7, wealth_column.scale
|
599
|
+
|
600
|
+
Person.connection.change_column 'people', 'last_name', :string, :null => false
|
601
|
+
Person.reset_column_information
|
602
|
+
|
603
|
+
wealth_column = Person.columns_hash['wealth']
|
604
|
+
assert_equal 9, wealth_column.precision
|
605
|
+
assert_equal 7, wealth_column.scale
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
def test_native_types
|
610
|
+
Person.delete_all
|
611
|
+
Person.connection.add_column "people", "last_name", :string
|
612
|
+
Person.connection.add_column "people", "bio", :text
|
613
|
+
Person.connection.add_column "people", "age", :integer
|
614
|
+
Person.connection.add_column "people", "height", :float
|
615
|
+
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
616
|
+
Person.connection.add_column "people", "birthday", :datetime
|
617
|
+
Person.connection.add_column "people", "favorite_day", :date
|
618
|
+
Person.connection.add_column "people", "moment_of_truth", :datetime
|
619
|
+
Person.connection.add_column "people", "male", :boolean
|
620
|
+
Person.reset_column_information
|
621
|
+
|
622
|
+
assert_nothing_raised do
|
623
|
+
Person.create :first_name => 'bob', :last_name => 'bobsen',
|
624
|
+
:bio => "I was born ....", :age => 18, :height => 1.78,
|
625
|
+
:wealth => BigDecimal.new("12345678901234567890.0123456789"),
|
626
|
+
:birthday => 18.years.ago, :favorite_day => 10.days.ago,
|
627
|
+
:moment_of_truth => "1782-10-10 21:40:18", :male => true
|
628
|
+
end
|
629
|
+
|
630
|
+
bob = Person.find(:first)
|
631
|
+
assert_equal 'bob', bob.first_name
|
632
|
+
assert_equal 'bobsen', bob.last_name
|
633
|
+
assert_equal "I was born ....", bob.bio
|
634
|
+
assert_equal 18, bob.age
|
635
|
+
|
636
|
+
# Test for 30 significant digits (beyond the 16 of float), 10 of them
|
637
|
+
# after the decimal place.
|
638
|
+
|
639
|
+
unless current_adapter?(:SQLite3Adapter)
|
640
|
+
assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
|
641
|
+
end
|
642
|
+
|
643
|
+
assert_equal true, bob.male?
|
644
|
+
|
645
|
+
assert_equal String, bob.first_name.class
|
646
|
+
assert_equal String, bob.last_name.class
|
647
|
+
assert_equal String, bob.bio.class
|
648
|
+
assert_equal Fixnum, bob.age.class
|
649
|
+
assert_equal Time, bob.birthday.class
|
650
|
+
|
651
|
+
if current_adapter?(:OracleAdapter, :SybaseAdapter)
|
652
|
+
# Sybase, and Oracle don't differentiate between date/time
|
653
|
+
assert_equal Time, bob.favorite_day.class
|
654
|
+
else
|
655
|
+
assert_equal Date, bob.favorite_day.class
|
656
|
+
end
|
657
|
+
|
658
|
+
# Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column
|
659
|
+
# therefore no timezone change is done afterwards when default timezone is changed
|
660
|
+
unless current_adapter?(:OracleAdapter)
|
661
|
+
# Test DateTime column and defaults, including timezone.
|
662
|
+
# FIXME: moment of truth may be Time on 64-bit platforms.
|
663
|
+
if bob.moment_of_truth.is_a?(DateTime)
|
664
|
+
|
665
|
+
with_env_tz 'US/Eastern' do
|
666
|
+
bob.reload
|
667
|
+
assert_equal DateTime.local_offset, bob.moment_of_truth.offset
|
668
|
+
assert_not_equal 0, bob.moment_of_truth.offset
|
669
|
+
assert_not_equal "Z", bob.moment_of_truth.zone
|
670
|
+
# US/Eastern is -5 hours from GMT
|
671
|
+
assert_equal Rational(-5, 24), bob.moment_of_truth.offset
|
672
|
+
assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM
|
673
|
+
assert_equal DateTime::ITALY, bob.moment_of_truth.start
|
674
|
+
end
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
assert_instance_of TrueClass, bob.male?
|
679
|
+
assert_kind_of BigDecimal, bob.wealth
|
680
|
+
end
|
681
|
+
|
682
|
+
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
683
|
+
def test_unabstracted_database_dependent_types
|
684
|
+
Person.delete_all
|
685
|
+
|
686
|
+
ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
|
687
|
+
Person.reset_column_information
|
688
|
+
assert_match(/tinyint/, Person.columns_hash['intelligence_quotient'].sql_type)
|
689
|
+
ensure
|
690
|
+
ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
694
|
+
def test_add_remove_single_field_using_string_arguments
|
695
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
696
|
+
|
697
|
+
ActiveRecord::Migration.add_column 'people', 'last_name', :string
|
698
|
+
|
699
|
+
Person.reset_column_information
|
700
|
+
assert Person.column_methods_hash.include?(:last_name)
|
701
|
+
|
702
|
+
ActiveRecord::Migration.remove_column 'people', 'last_name'
|
703
|
+
|
704
|
+
Person.reset_column_information
|
705
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
706
|
+
end
|
707
|
+
|
708
|
+
def test_add_remove_single_field_using_symbol_arguments
|
709
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
710
|
+
|
711
|
+
ActiveRecord::Migration.add_column :people, :last_name, :string
|
712
|
+
|
713
|
+
Person.reset_column_information
|
714
|
+
assert Person.column_methods_hash.include?(:last_name)
|
715
|
+
|
716
|
+
ActiveRecord::Migration.remove_column :people, :last_name
|
717
|
+
|
718
|
+
Person.reset_column_information
|
719
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
720
|
+
end
|
721
|
+
|
722
|
+
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
723
|
+
def testing_table_for_positioning
|
724
|
+
Person.connection.create_table :testings, :id => false do |t|
|
725
|
+
t.column :first, :integer
|
726
|
+
t.column :second, :integer
|
727
|
+
t.column :third, :integer
|
728
|
+
end
|
729
|
+
|
730
|
+
yield Person.connection
|
731
|
+
ensure
|
732
|
+
Person.connection.drop_table :testings rescue nil
|
733
|
+
end
|
734
|
+
protected :testing_table_for_positioning
|
735
|
+
|
736
|
+
def test_column_positioning
|
737
|
+
testing_table_for_positioning do |conn|
|
738
|
+
assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name }
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
def test_add_column_with_positioning
|
743
|
+
testing_table_for_positioning do |conn|
|
744
|
+
conn.add_column :testings, :new_col, :integer
|
745
|
+
assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name }
|
746
|
+
end
|
747
|
+
testing_table_for_positioning do |conn|
|
748
|
+
conn.add_column :testings, :new_col, :integer, :first => true
|
749
|
+
assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name }
|
750
|
+
end
|
751
|
+
testing_table_for_positioning do |conn|
|
752
|
+
conn.add_column :testings, :new_col, :integer, :after => :first
|
753
|
+
assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name }
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
def test_change_column_with_positioning
|
758
|
+
testing_table_for_positioning do |conn|
|
759
|
+
conn.change_column :testings, :second, :integer, :first => true
|
760
|
+
assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name }
|
761
|
+
end
|
762
|
+
testing_table_for_positioning do |conn|
|
763
|
+
conn.change_column :testings, :second, :integer, :after => :third
|
764
|
+
assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name }
|
765
|
+
end
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
if(!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
|
770
|
+
def test_add_rename
|
771
|
+
Person.delete_all
|
772
|
+
|
773
|
+
begin
|
774
|
+
Person.connection.add_column "people", "girlfriend", :string
|
775
|
+
Person.reset_column_information
|
776
|
+
Person.create :girlfriend => 'bobette'
|
777
|
+
|
778
|
+
Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
|
779
|
+
|
780
|
+
Person.reset_column_information
|
781
|
+
bob = Person.find(:first)
|
782
|
+
|
783
|
+
assert_equal "bobette", bob.exgirlfriend
|
784
|
+
ensure
|
785
|
+
Person.connection.remove_column("people", "girlfriend") rescue nil
|
786
|
+
Person.connection.remove_column("people", "exgirlfriend") rescue nil
|
787
|
+
end
|
788
|
+
|
789
|
+
end
|
790
|
+
|
791
|
+
def test_rename_column_using_symbol_arguments
|
792
|
+
begin
|
793
|
+
names_before = Person.find(:all).map(&:first_name)
|
794
|
+
Person.connection.rename_column :people, :first_name, :nick_name
|
795
|
+
Person.reset_column_information
|
796
|
+
assert Person.column_names.include?("nick_name")
|
797
|
+
assert_equal names_before, Person.find(:all).map(&:nick_name)
|
798
|
+
ensure
|
799
|
+
Person.connection.remove_column("people","nick_name")
|
800
|
+
Person.connection.add_column("people","first_name", :string)
|
801
|
+
end
|
802
|
+
end
|
803
|
+
|
804
|
+
def test_rename_column
|
805
|
+
begin
|
806
|
+
names_before = Person.find(:all).map(&:first_name)
|
807
|
+
Person.connection.rename_column "people", "first_name", "nick_name"
|
808
|
+
Person.reset_column_information
|
809
|
+
assert Person.column_names.include?("nick_name")
|
810
|
+
assert_equal names_before, Person.find(:all).map(&:nick_name)
|
811
|
+
ensure
|
812
|
+
Person.connection.remove_column("people","nick_name")
|
813
|
+
Person.connection.add_column("people","first_name", :string)
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
def test_rename_column_preserves_default_value_not_null
|
818
|
+
begin
|
819
|
+
default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
|
820
|
+
assert_equal 70000, default_before
|
821
|
+
Developer.connection.rename_column "developers", "salary", "anual_salary"
|
822
|
+
Developer.reset_column_information
|
823
|
+
assert Developer.column_names.include?("anual_salary")
|
824
|
+
default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
|
825
|
+
assert_equal 70000, default_after
|
826
|
+
ensure
|
827
|
+
Developer.connection.rename_column "developers", "anual_salary", "salary"
|
828
|
+
Developer.reset_column_information
|
829
|
+
end
|
830
|
+
end
|
831
|
+
|
832
|
+
def test_rename_nonexistent_column
|
833
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
834
|
+
table.column :hat_name, :string, :default => nil
|
835
|
+
end
|
836
|
+
exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
|
837
|
+
ActiveRecord::StatementInvalid
|
838
|
+
else
|
839
|
+
ActiveRecord::ActiveRecordError
|
840
|
+
end
|
841
|
+
assert_raise(exception) do
|
842
|
+
Person.connection.rename_column "hats", "nonexistent", "should_fail"
|
843
|
+
end
|
844
|
+
ensure
|
845
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
846
|
+
end
|
847
|
+
|
848
|
+
def test_rename_column_with_sql_reserved_word
|
849
|
+
begin
|
850
|
+
assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
|
851
|
+
Person.reset_column_information
|
852
|
+
assert Person.column_names.include?("group")
|
853
|
+
ensure
|
854
|
+
Person.connection.remove_column("people", "group") rescue nil
|
855
|
+
Person.connection.add_column("people", "first_name", :string) rescue nil
|
856
|
+
end
|
857
|
+
end
|
858
|
+
end
|
859
|
+
|
860
|
+
unless current_adapter?(:IBM_DBAdapter)
|
861
|
+
def test_rename_column_with_an_index
|
862
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
863
|
+
table.column :hat_name, :string, :limit => 100
|
864
|
+
table.column :hat_size, :integer
|
865
|
+
end
|
866
|
+
Person.connection.add_index :hats, :hat_name
|
867
|
+
assert_nothing_raised do
|
868
|
+
Person.connection.rename_column "hats", "hat_name", "name"
|
869
|
+
end
|
870
|
+
ensure
|
871
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
872
|
+
end
|
873
|
+
end
|
874
|
+
|
875
|
+
def test_remove_column_with_index
|
876
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
877
|
+
table.column :hat_name, :string, :limit => 100
|
878
|
+
table.column :hat_size, :integer
|
879
|
+
end
|
880
|
+
ActiveRecord::Base.connection.add_index "hats", "hat_size"
|
881
|
+
|
882
|
+
assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
|
883
|
+
ensure
|
884
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
885
|
+
end
|
886
|
+
|
887
|
+
def test_remove_column_with_multi_column_index
|
888
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
889
|
+
table.column :hat_name, :string, :limit => 100
|
890
|
+
table.column :hat_size, :integer
|
891
|
+
table.column :hat_style, :string, :limit => 100
|
892
|
+
end
|
893
|
+
ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
|
894
|
+
|
895
|
+
assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
|
896
|
+
ensure
|
897
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
898
|
+
end
|
899
|
+
|
900
|
+
def test_remove_column_no_second_parameter_raises_exception
|
901
|
+
assert_raise(ArgumentError) { Person.connection.remove_column("funny") }
|
902
|
+
end
|
903
|
+
|
904
|
+
def test_change_type_of_not_null_column
|
905
|
+
assert_nothing_raised do
|
906
|
+
unless current_adapter?(:IBM_DBAdapter)
|
907
|
+
Topic.connection.change_column "topics", "written_on", :datetime, :null => false
|
908
|
+
else
|
909
|
+
Topic.connection.change_column_null "topics", "written_on", false
|
910
|
+
end
|
911
|
+
Topic.reset_column_information
|
912
|
+
|
913
|
+
unless current_adapter?(:IBM_DBAdapter)
|
914
|
+
Topic.connection.change_column "topics", "written_on", :datetime, :null => false
|
915
|
+
else
|
916
|
+
Topic.connection.change_column_null "topics", "written_on", false
|
917
|
+
end
|
918
|
+
Topic.reset_column_information
|
919
|
+
|
920
|
+
unless current_adapter?(:IBM_DBAdapter)
|
921
|
+
Topic.connection.change_column "topics", "written_on", :datetime, :null => true
|
922
|
+
else
|
923
|
+
Topic.connection.change_column_null "topics", "written_on", true
|
924
|
+
end
|
925
|
+
|
926
|
+
Topic.reset_column_information
|
927
|
+
end
|
928
|
+
end
|
929
|
+
|
930
|
+
if current_adapter?(:SQLite3Adapter)
|
931
|
+
def test_rename_table_for_sqlite_should_work_with_reserved_words
|
932
|
+
begin
|
933
|
+
assert_nothing_raised do
|
934
|
+
ActiveRecord::Base.connection.rename_table :references, :old_references
|
935
|
+
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
936
|
+
t.column :url, :string
|
937
|
+
end
|
938
|
+
end
|
939
|
+
|
940
|
+
assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references }
|
941
|
+
|
942
|
+
# Using explicit id in insert for compatibility across all databases
|
943
|
+
con = ActiveRecord::Base.connection
|
944
|
+
assert_nothing_raised do
|
945
|
+
con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')"
|
946
|
+
end
|
947
|
+
assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1")
|
948
|
+
|
949
|
+
ensure
|
950
|
+
ActiveRecord::Base.connection.drop_table :references
|
951
|
+
ActiveRecord::Base.connection.rename_table :old_references, :references
|
952
|
+
end
|
953
|
+
end
|
954
|
+
end
|
955
|
+
|
956
|
+
def test_rename_table
|
957
|
+
begin
|
958
|
+
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
959
|
+
t.column :url, :string
|
960
|
+
end
|
961
|
+
ActiveRecord::Base.connection.rename_table :octopuses, :octopi
|
962
|
+
|
963
|
+
# Using explicit id in insert for compatibility across all databases
|
964
|
+
con = ActiveRecord::Base.connection
|
965
|
+
con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
|
966
|
+
assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
|
967
|
+
con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
|
968
|
+
|
969
|
+
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
|
970
|
+
|
971
|
+
ensure
|
972
|
+
ActiveRecord::Base.connection.drop_table :octopuses rescue nil
|
973
|
+
ActiveRecord::Base.connection.drop_table :octopi rescue nil
|
974
|
+
end
|
975
|
+
end
|
976
|
+
|
977
|
+
def test_change_column_nullability
|
978
|
+
Person.delete_all
|
979
|
+
Person.connection.add_column "people", "funny", :boolean
|
980
|
+
Person.reset_column_information
|
981
|
+
assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
|
982
|
+
unless current_adapter?(:IBM_DBAdapter)
|
983
|
+
Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true
|
984
|
+
else
|
985
|
+
Person.connection.change_column_null "people", "funny",false
|
986
|
+
end
|
987
|
+
Person.reset_column_information
|
988
|
+
assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
|
989
|
+
unless current_adapter?(:IBM_DBAdapter)
|
990
|
+
Person.connection.change_column "people", "funny", :boolean, :null => true
|
991
|
+
else
|
992
|
+
Person.connection.change_column_null "people", "funny",true
|
993
|
+
end
|
994
|
+
Person.reset_column_information
|
995
|
+
assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
|
996
|
+
end
|
997
|
+
|
998
|
+
def test_rename_table_with_an_index
|
999
|
+
begin
|
1000
|
+
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
1001
|
+
t.column :url, :string
|
1002
|
+
end
|
1003
|
+
ActiveRecord::Base.connection.add_index :octopuses, :url
|
1004
|
+
|
1005
|
+
ActiveRecord::Base.connection.rename_table :octopuses, :octopi
|
1006
|
+
|
1007
|
+
# Using explicit id in insert for compatibility across all databases
|
1008
|
+
con = ActiveRecord::Base.connection
|
1009
|
+
con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
|
1010
|
+
assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
|
1011
|
+
con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
|
1012
|
+
|
1013
|
+
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
|
1014
|
+
assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
|
1015
|
+
ensure
|
1016
|
+
ActiveRecord::Base.connection.drop_table :octopuses rescue nil
|
1017
|
+
ActiveRecord::Base.connection.drop_table :octopi rescue nil
|
1018
|
+
end
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1022
|
+
# Cannot convert from type integer to varchar.
|
1023
|
+
# Safe to not run this test as add_column will be covered in other test cases
|
1024
|
+
def test_change_column
|
1025
|
+
Person.connection.add_column 'people', 'age', :integer
|
1026
|
+
label = "test_change_column Columns"
|
1027
|
+
old_columns = Person.connection.columns(Person.table_name, label)
|
1028
|
+
assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
|
1029
|
+
|
1030
|
+
assert_nothing_raised { Person.connection.change_column "people", "age", :string }
|
1031
|
+
|
1032
|
+
new_columns = Person.connection.columns(Person.table_name, label)
|
1033
|
+
assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
|
1034
|
+
assert new_columns.find { |c| c.name == 'age' and c.type == :string }
|
1035
|
+
|
1036
|
+
old_columns = Topic.connection.columns(Topic.table_name, label)
|
1037
|
+
assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
1038
|
+
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
|
1039
|
+
new_columns = Topic.connection.columns(Topic.table_name, label)
|
1040
|
+
assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
1041
|
+
assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
|
1042
|
+
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
def test_change_column_with_nil_default
|
1047
|
+
Person.connection.add_column "people", "contributor", :boolean, :default => true
|
1048
|
+
Person.reset_column_information
|
1049
|
+
assert Person.new.contributor?
|
1050
|
+
|
1051
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1052
|
+
assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
|
1053
|
+
else
|
1054
|
+
assert_nothing_raised { Person.connection.change_column_default "people", "contributor", nil }
|
1055
|
+
end
|
1056
|
+
Person.reset_column_information
|
1057
|
+
assert !Person.new.contributor?
|
1058
|
+
assert_nil Person.new.contributor
|
1059
|
+
ensure
|
1060
|
+
Person.connection.remove_column("people", "contributor") rescue nil
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
def test_change_column_with_new_default
|
1064
|
+
Person.connection.add_column "people", "administrator", :boolean, :default => true
|
1065
|
+
Person.reset_column_information
|
1066
|
+
assert Person.new.administrator?
|
1067
|
+
|
1068
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1069
|
+
assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
|
1070
|
+
else
|
1071
|
+
assert_nothing_raised { Person.connection.change_column_default "people", "administrator", false }
|
1072
|
+
end
|
1073
|
+
Person.reset_column_information
|
1074
|
+
assert !Person.new.administrator?
|
1075
|
+
ensure
|
1076
|
+
Person.connection.remove_column("people", "administrator") rescue nil
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
def test_change_column_default
|
1080
|
+
Person.connection.change_column_default "people", "first_name", "Tester"
|
1081
|
+
Person.reset_column_information
|
1082
|
+
assert_equal "Tester", Person.new.first_name
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
def test_change_column_quotes_column_names
|
1086
|
+
Person.connection.create_table :testings do |t|
|
1087
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1088
|
+
t.column :select, :string
|
1089
|
+
else
|
1090
|
+
# If no limit specified by default column of length 255 is created, which later cannot be scaled down to 10
|
1091
|
+
t.column :select, :string, :limit => 5
|
1092
|
+
end
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 }
|
1096
|
+
|
1097
|
+
# Oracle needs primary key value from sequence
|
1098
|
+
if current_adapter?(:OracleAdapter)
|
1099
|
+
assert_nothing_raised { Person.connection.execute "insert into testings (id, #{Person.connection.quote_column_name('select')}) values (testings_seq.nextval, '7 chars')" }
|
1100
|
+
else
|
1101
|
+
assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
|
1102
|
+
end
|
1103
|
+
ensure
|
1104
|
+
Person.connection.drop_table :testings rescue nil
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def test_keeping_default_and_notnull_constaint_on_change
|
1108
|
+
Person.connection.create_table :testings do |t|
|
1109
|
+
t.column :title, :string
|
1110
|
+
end
|
1111
|
+
person_klass = Class.new(Person)
|
1112
|
+
person_klass.table_name = 'testings'
|
1113
|
+
|
1114
|
+
person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
|
1115
|
+
person_klass.reset_column_information
|
1116
|
+
assert_equal 99, person_klass.columns_hash["wealth"].default
|
1117
|
+
assert_equal false, person_klass.columns_hash["wealth"].null
|
1118
|
+
# Oracle needs primary key value from sequence
|
1119
|
+
if current_adapter?(:OracleAdapter)
|
1120
|
+
assert_nothing_raised {person_klass.connection.execute("insert into testings (id, title) values (testings_seq.nextval, 'tester')")}
|
1121
|
+
else
|
1122
|
+
assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
# change column default to see that column doesn't lose its not null definition
|
1126
|
+
person_klass.connection.change_column_default "testings", "wealth", 100
|
1127
|
+
person_klass.reset_column_information
|
1128
|
+
assert_equal 100, person_klass.columns_hash["wealth"].default
|
1129
|
+
assert_equal false, person_klass.columns_hash["wealth"].null
|
1130
|
+
|
1131
|
+
# rename column to see that column doesn't lose its not null and/or default definition
|
1132
|
+
if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
|
1133
|
+
person_klass.connection.rename_column "testings", "wealth", "money"
|
1134
|
+
person_klass.reset_column_information
|
1135
|
+
assert_nil person_klass.columns_hash["wealth"]
|
1136
|
+
assert_equal 100, person_klass.columns_hash["money"].default
|
1137
|
+
assert_equal false, person_klass.columns_hash["money"].null
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
# change column
|
1141
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1142
|
+
person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
|
1143
|
+
person_klass.reset_column_information
|
1144
|
+
assert_equal 1000, person_klass.columns_hash["money"].default
|
1145
|
+
assert_equal false, person_klass.columns_hash["money"].null
|
1146
|
+
else
|
1147
|
+
person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 15, :scale => 1,:null => false, :default => 1000
|
1148
|
+
person_klass.reset_column_information
|
1149
|
+
assert_equal 1000, person_klass.columns_hash["wealth"].default
|
1150
|
+
assert_equal false, person_klass.columns_hash["wealth"].null
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
# change column, make it nullable and clear default
|
1154
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1155
|
+
person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
|
1156
|
+
person_klass.reset_column_information
|
1157
|
+
assert_nil person_klass.columns_hash["money"].default
|
1158
|
+
assert_equal true, person_klass.columns_hash["money"].null
|
1159
|
+
else
|
1160
|
+
person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 20, :scale => 2, :null => true, :default => nil
|
1161
|
+
person_klass.reset_column_information
|
1162
|
+
assert_nil person_klass.columns_hash["wealth"].default
|
1163
|
+
assert_equal true, person_klass.columns_hash["wealth"].null
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
# change_column_null, make it not nullable and set null values to a default value
|
1167
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1168
|
+
person_klass.connection.execute('UPDATE testings SET money = NULL')
|
1169
|
+
person_klass.connection.change_column_null "testings", "money", false, 2000
|
1170
|
+
person_klass.reset_column_information
|
1171
|
+
assert_nil person_klass.columns_hash["money"].default
|
1172
|
+
assert_equal false, person_klass.columns_hash["money"].null
|
1173
|
+
assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
|
1174
|
+
else
|
1175
|
+
# Trying to set the value of the column wealth to NULL and
|
1176
|
+
# in the next statement a not null constraint is being applied which is wrong
|
1177
|
+
#person_klass.connection.execute('UPDATE testings SET money = NULL')
|
1178
|
+
person_klass.connection.change_column_null "testings", "wealth", false, 2000
|
1179
|
+
person_klass.reset_column_information
|
1180
|
+
#assert_nil person_klass.columns_hash["wealth"].default #Setting default to 2000 and expecting nil is nor correct
|
1181
|
+
assert_not_nil person_klass.columns_hash["wealth"].default
|
1182
|
+
assert_equal false, person_klass.columns_hash["wealth"].null
|
1183
|
+
#Changing default does not change the already inserted value. Hence expecting 2000 is wrong.
|
1184
|
+
assert_equal [99], Person.connection.select_values("SELECT wealth FROM testings").map { |s| s.to_i }.sort
|
1185
|
+
end
|
1186
|
+
ensure
|
1187
|
+
Person.connection.drop_table :testings rescue nil
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def test_change_column_default_to_null
|
1191
|
+
Person.connection.change_column_default "people", "first_name", nil
|
1192
|
+
Person.reset_column_information
|
1193
|
+
assert_nil Person.new.first_name
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
def test_column_exists
|
1197
|
+
Person.connection.create_table :testings do |t|
|
1198
|
+
t.column :foo, :string
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
assert Person.connection.column_exists?(:testings, :foo)
|
1202
|
+
assert !Person.connection.column_exists?(:testings, :bar)
|
1203
|
+
ensure
|
1204
|
+
Person.connection.drop_table :testings rescue nil
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
def test_column_exists_with_type
|
1208
|
+
Person.connection.create_table :testings do |t|
|
1209
|
+
t.column :foo, :string
|
1210
|
+
t.column :bar, :decimal, :precision => 8, :scale => 2
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
assert Person.connection.column_exists?(:testings, :foo, :string)
|
1214
|
+
assert !Person.connection.column_exists?(:testings, :foo, :integer)
|
1215
|
+
assert Person.connection.column_exists?(:testings, :bar, :decimal)
|
1216
|
+
assert !Person.connection.column_exists?(:testings, :bar, :integer)
|
1217
|
+
ensure
|
1218
|
+
Person.connection.drop_table :testings rescue nil
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
def test_column_exists_with_definition
|
1222
|
+
Person.connection.create_table :testings do |t|
|
1223
|
+
t.column :foo, :string, :limit => 100
|
1224
|
+
t.column :bar, :decimal, :precision => 8, :scale => 2
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100)
|
1228
|
+
assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50)
|
1229
|
+
assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2)
|
1230
|
+
assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2)
|
1231
|
+
ensure
|
1232
|
+
Person.connection.drop_table :testings rescue nil
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
def test_column_exists_on_table_with_no_options_parameter_supplied
|
1236
|
+
Person.connection.create_table :testings do |t|
|
1237
|
+
t.string :foo
|
1238
|
+
end
|
1239
|
+
Person.connection.change_table :testings do |t|
|
1240
|
+
assert t.column_exists?(:foo)
|
1241
|
+
assert !(t.column_exists?(:bar))
|
1242
|
+
end
|
1243
|
+
ensure
|
1244
|
+
Person.connection.drop_table :testings rescue nil
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
def test_add_table
|
1248
|
+
assert !Reminder.table_exists?
|
1249
|
+
|
1250
|
+
WeNeedReminders.up
|
1251
|
+
|
1252
|
+
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1253
|
+
assert_equal "hello world", Reminder.find(:first).content
|
1254
|
+
|
1255
|
+
WeNeedReminders.down
|
1256
|
+
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
def test_add_table_with_decimals
|
1260
|
+
Person.connection.drop_table :big_numbers rescue nil
|
1261
|
+
|
1262
|
+
assert !BigNumber.table_exists?
|
1263
|
+
GiveMeBigNumbers.up
|
1264
|
+
|
1265
|
+
assert BigNumber.create(
|
1266
|
+
:bank_balance => 1586.43,
|
1267
|
+
:big_bank_balance => BigDecimal("1000234000567.95"),
|
1268
|
+
:world_population => 6000000000,
|
1269
|
+
:my_house_population => 3,
|
1270
|
+
:value_of_e => BigDecimal("2.7182818284590452353602875")
|
1271
|
+
)
|
1272
|
+
|
1273
|
+
b = BigNumber.find(:first)
|
1274
|
+
assert_not_nil b
|
1275
|
+
|
1276
|
+
assert_not_nil b.bank_balance
|
1277
|
+
assert_not_nil b.big_bank_balance
|
1278
|
+
assert_not_nil b.world_population
|
1279
|
+
assert_not_nil b.my_house_population
|
1280
|
+
assert_not_nil b.value_of_e
|
1281
|
+
|
1282
|
+
# TODO: set world_population >= 2**62 to cover 64-bit platforms and test
|
1283
|
+
# is_a?(Bignum)
|
1284
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1285
|
+
assert_kind_of Integer, b.world_population
|
1286
|
+
else
|
1287
|
+
assert_kind_of BigDecimal, b.world_population
|
1288
|
+
end
|
1289
|
+
assert_equal 6000000000, b.world_population
|
1290
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1291
|
+
assert_kind_of Fixnum, b.my_house_population
|
1292
|
+
else
|
1293
|
+
assert_kind_of BigDecimal, b.my_house_population
|
1294
|
+
end
|
1295
|
+
assert_equal 3, b.my_house_population
|
1296
|
+
assert_kind_of BigDecimal, b.bank_balance
|
1297
|
+
assert_equal BigDecimal("1586.43"), b.bank_balance
|
1298
|
+
assert_kind_of BigDecimal, b.big_bank_balance
|
1299
|
+
assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
|
1300
|
+
|
1301
|
+
# This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
|
1302
|
+
# precision/scale explicitly left out. By the SQL standard, numbers
|
1303
|
+
# assigned to this field should be truncated but that's seldom respected.
|
1304
|
+
if current_adapter?(:PostgreSQLAdapter)
|
1305
|
+
# - PostgreSQL changes the SQL spec on columns declared simply as
|
1306
|
+
# "decimal" to something more useful: instead of being given a scale
|
1307
|
+
# of 0, they take on the compile-time limit for precision and scale,
|
1308
|
+
# so the following should succeed unless you have used really wacky
|
1309
|
+
# compilation options
|
1310
|
+
# - SQLite2 has the default behavior of preserving all data sent in,
|
1311
|
+
# so this happens there too
|
1312
|
+
assert_kind_of BigDecimal, b.value_of_e
|
1313
|
+
assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
|
1314
|
+
elsif current_adapter?(:SQLite3Adapter)
|
1315
|
+
# - SQLite3 stores a float, in violation of SQL
|
1316
|
+
assert_kind_of BigDecimal, b.value_of_e
|
1317
|
+
assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
|
1318
|
+
else
|
1319
|
+
# - SQL standard is an integer
|
1320
|
+
unless current_adapter?(:IBM_DBAdapter)
|
1321
|
+
assert_kind_of Fixnum, b.value_of_e
|
1322
|
+
else
|
1323
|
+
assert_kind_of BigDecimal, b.value_of_e
|
1324
|
+
end
|
1325
|
+
assert_equal 2, b.value_of_e
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
GiveMeBigNumbers.down
|
1329
|
+
assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
def test_migrator
|
1333
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1334
|
+
assert !Reminder.table_exists?
|
1335
|
+
|
1336
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
|
1337
|
+
|
1338
|
+
assert_equal 3, ActiveRecord::Migrator.current_version
|
1339
|
+
Person.reset_column_information
|
1340
|
+
assert Person.column_methods_hash.include?(:last_name)
|
1341
|
+
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1342
|
+
assert_equal "hello world", Reminder.find(:first).content
|
1343
|
+
|
1344
|
+
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
|
1345
|
+
|
1346
|
+
assert_equal 0, ActiveRecord::Migrator.current_version
|
1347
|
+
Person.reset_column_information
|
1348
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1349
|
+
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
def test_filtering_migrations
|
1353
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1354
|
+
assert !Reminder.table_exists?
|
1355
|
+
|
1356
|
+
name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
|
1357
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
|
1358
|
+
|
1359
|
+
Person.reset_column_information
|
1360
|
+
assert Person.column_methods_hash.include?(:last_name)
|
1361
|
+
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1362
|
+
|
1363
|
+
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
|
1364
|
+
|
1365
|
+
Person.reset_column_information
|
1366
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1367
|
+
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
class MockMigration < ActiveRecord::Migration
|
1371
|
+
attr_reader :went_up, :went_down
|
1372
|
+
def initialize
|
1373
|
+
@went_up = false
|
1374
|
+
@went_down = false
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
def up
|
1378
|
+
@went_up = true
|
1379
|
+
super
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
def down
|
1383
|
+
@went_down = true
|
1384
|
+
super
|
1385
|
+
end
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
def test_instance_based_migration_up
|
1389
|
+
migration = MockMigration.new
|
1390
|
+
assert !migration.went_up, 'have not gone up'
|
1391
|
+
assert !migration.went_down, 'have not gone down'
|
1392
|
+
|
1393
|
+
migration.migrate :up
|
1394
|
+
assert migration.went_up, 'have gone up'
|
1395
|
+
assert !migration.went_down, 'have not gone down'
|
1396
|
+
end
|
1397
|
+
|
1398
|
+
def test_instance_based_migration_down
|
1399
|
+
migration = MockMigration.new
|
1400
|
+
assert !migration.went_up, 'have not gone up'
|
1401
|
+
assert !migration.went_down, 'have not gone down'
|
1402
|
+
|
1403
|
+
migration.migrate :down
|
1404
|
+
assert !migration.went_up, 'have gone up'
|
1405
|
+
assert migration.went_down, 'have not gone down'
|
1406
|
+
end
|
1407
|
+
|
1408
|
+
def test_migrator_one_up
|
1409
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1410
|
+
assert !Reminder.table_exists?
|
1411
|
+
|
1412
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1413
|
+
|
1414
|
+
Person.reset_column_information
|
1415
|
+
assert Person.column_methods_hash.include?(:last_name)
|
1416
|
+
assert !Reminder.table_exists?
|
1417
|
+
|
1418
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
|
1419
|
+
|
1420
|
+
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1421
|
+
assert_equal "hello world", Reminder.find(:first).content
|
1422
|
+
end
|
1423
|
+
|
1424
|
+
def test_migrator_one_down
|
1425
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
|
1426
|
+
|
1427
|
+
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
|
1428
|
+
|
1429
|
+
Person.reset_column_information
|
1430
|
+
assert Person.column_methods_hash.include?(:last_name)
|
1431
|
+
assert !Reminder.table_exists?
|
1432
|
+
end
|
1433
|
+
|
1434
|
+
def test_migrator_one_up_one_down
|
1435
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1436
|
+
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
|
1437
|
+
|
1438
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1439
|
+
assert !Reminder.table_exists?
|
1440
|
+
end
|
1441
|
+
|
1442
|
+
def test_migrator_double_up
|
1443
|
+
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1444
|
+
ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
|
1445
|
+
assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) }
|
1446
|
+
assert_equal(1, ActiveRecord::Migrator.current_version)
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
def test_migrator_double_down
|
1450
|
+
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1451
|
+
ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
|
1452
|
+
ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1)
|
1453
|
+
assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) }
|
1454
|
+
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
if ActiveRecord::Base.connection.supports_ddl_transactions?
|
1458
|
+
def test_migrator_one_up_with_exception_and_rollback
|
1459
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1460
|
+
|
1461
|
+
e = assert_raise(StandardError) do
|
1462
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
|
1463
|
+
end
|
1464
|
+
|
1465
|
+
assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
|
1466
|
+
|
1467
|
+
Person.reset_column_information
|
1468
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1469
|
+
end
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
def test_finds_migrations
|
1473
|
+
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
|
1474
|
+
|
1475
|
+
[[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
|
1476
|
+
assert_equal migrations[i].version, pair.first
|
1477
|
+
assert_equal migrations[i].name, pair.last
|
1478
|
+
end
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
def test_finds_migrations_in_subdirectories
|
1482
|
+
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations
|
1483
|
+
|
1484
|
+
[[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
|
1485
|
+
assert_equal migrations[i].version, pair.first
|
1486
|
+
assert_equal migrations[i].name, pair.last
|
1487
|
+
end
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
def test_finds_migrations_from_two_directories
|
1491
|
+
directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps']
|
1492
|
+
migrations = ActiveRecord::Migrator.new(:up, directories).migrations
|
1493
|
+
|
1494
|
+
[[20090101010101, "PeopleHaveHobbies"],
|
1495
|
+
[20090101010202, "PeopleHaveDescriptions"],
|
1496
|
+
[20100101010101, "ValidWithTimestampsPeopleHaveLastNames"],
|
1497
|
+
[20100201010101, "ValidWithTimestampsWeNeedReminders"],
|
1498
|
+
[20100301010101, "ValidWithTimestampsInnocentJointable"]].each_with_index do |pair, i|
|
1499
|
+
assert_equal pair.first, migrations[i].version
|
1500
|
+
assert_equal pair.last, migrations[i].name
|
1501
|
+
end
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
def test_dump_schema_information_outputs_lexically_ordered_versions
|
1505
|
+
migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps'
|
1506
|
+
ActiveRecord::Migrator.run(:up, migration_path, 20100301010101)
|
1507
|
+
ActiveRecord::Migrator.run(:up, migration_path, 20100201010101)
|
1508
|
+
|
1509
|
+
schema_info = ActiveRecord::Base.connection.dump_schema_information
|
1510
|
+
assert_match(/20100201010101.*20100301010101/m, schema_info)
|
1511
|
+
end
|
1512
|
+
|
1513
|
+
def test_finds_pending_migrations
|
1514
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
|
1515
|
+
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
|
1516
|
+
|
1517
|
+
assert_equal 1, migrations.size
|
1518
|
+
assert_equal migrations[0].version, 3
|
1519
|
+
assert_equal migrations[0].name, 'InterleavedInnocentJointable'
|
1520
|
+
end
|
1521
|
+
|
1522
|
+
def test_relative_migrations
|
1523
|
+
list = Dir.chdir(MIGRATIONS_ROOT) do
|
1524
|
+
ActiveRecord::Migrator.up("valid/", 1)
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
migration_proxy = list.find { |item|
|
1528
|
+
item.name == 'ValidPeopleHaveLastNames'
|
1529
|
+
}
|
1530
|
+
assert migration_proxy, 'should find pending migration'
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
def test_only_loads_pending_migrations
|
1534
|
+
# migrate up to 1
|
1535
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1536
|
+
|
1537
|
+
proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
|
1538
|
+
|
1539
|
+
names = proxies.map(&:name)
|
1540
|
+
assert !names.include?('ValidPeopleHaveLastNames')
|
1541
|
+
assert names.include?('WeNeedReminders')
|
1542
|
+
assert names.include?('InnocentJointable')
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
def test_target_version_zero_should_run_only_once
|
1546
|
+
# migrate up to 1
|
1547
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
|
1548
|
+
|
1549
|
+
# migrate down to 0
|
1550
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
|
1551
|
+
|
1552
|
+
# migrate down to 0 again
|
1553
|
+
proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
|
1554
|
+
assert_equal [], proxies
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
def test_migrator_db_has_no_schema_migrations_table
|
1558
|
+
# Oracle adapter raises error if semicolon is present as last character
|
1559
|
+
if current_adapter?(:OracleAdapter)
|
1560
|
+
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
|
1561
|
+
else
|
1562
|
+
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
|
1563
|
+
end
|
1564
|
+
assert_nothing_raised do
|
1565
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
|
1566
|
+
end
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
def test_migrator_verbosity
|
1570
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1571
|
+
assert_not_equal 0, ActiveRecord::Migration.message_count
|
1572
|
+
ActiveRecord::Migration.message_count = 0
|
1573
|
+
|
1574
|
+
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
|
1575
|
+
assert_not_equal 0, ActiveRecord::Migration.message_count
|
1576
|
+
ActiveRecord::Migration.message_count = 0
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
def test_migrator_verbosity_off
|
1580
|
+
ActiveRecord::Migration.verbose = false
|
1581
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1582
|
+
assert_equal 0, ActiveRecord::Migration.message_count
|
1583
|
+
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
|
1584
|
+
assert_equal 0, ActiveRecord::Migration.message_count
|
1585
|
+
end
|
1586
|
+
|
1587
|
+
def test_migrator_going_down_due_to_version_target
|
1588
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
1589
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
|
1590
|
+
|
1591
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
1592
|
+
assert !Reminder.table_exists?
|
1593
|
+
|
1594
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1595
|
+
|
1596
|
+
Person.reset_column_information
|
1597
|
+
assert Person.column_methods_hash.include?(:last_name)
|
1598
|
+
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1599
|
+
assert_equal "hello world", Reminder.find(:first).content
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def test_migrator_rollback
|
1603
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1604
|
+
assert_equal(3, ActiveRecord::Migrator.current_version)
|
1605
|
+
|
1606
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1607
|
+
assert_equal(2, ActiveRecord::Migrator.current_version)
|
1608
|
+
|
1609
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1610
|
+
assert_equal(1, ActiveRecord::Migrator.current_version)
|
1611
|
+
|
1612
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1613
|
+
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1614
|
+
|
1615
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1616
|
+
assert_equal(0, ActiveRecord::Migrator.current_version)
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
def test_migrator_forward
|
1620
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
|
1621
|
+
assert_equal(1, ActiveRecord::Migrator.current_version)
|
1622
|
+
|
1623
|
+
ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid", 2)
|
1624
|
+
assert_equal(3, ActiveRecord::Migrator.current_version)
|
1625
|
+
|
1626
|
+
ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid")
|
1627
|
+
assert_equal(3, ActiveRecord::Migrator.current_version)
|
1628
|
+
end
|
1629
|
+
|
1630
|
+
def test_get_all_versions
|
1631
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1632
|
+
assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions)
|
1633
|
+
|
1634
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1635
|
+
assert_equal([1,2], ActiveRecord::Migrator.get_all_versions)
|
1636
|
+
|
1637
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1638
|
+
assert_equal([1], ActiveRecord::Migrator.get_all_versions)
|
1639
|
+
|
1640
|
+
ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
|
1641
|
+
assert_equal([], ActiveRecord::Migrator.get_all_versions)
|
1642
|
+
end
|
1643
|
+
|
1644
|
+
def test_schema_migrations_table_name
|
1645
|
+
ActiveRecord::Base.table_name_prefix = "prefix_"
|
1646
|
+
ActiveRecord::Base.table_name_suffix = "_suffix"
|
1647
|
+
Reminder.reset_table_name
|
1648
|
+
assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
|
1649
|
+
ActiveRecord::Base.table_name_prefix = ""
|
1650
|
+
ActiveRecord::Base.table_name_suffix = ""
|
1651
|
+
Reminder.reset_table_name
|
1652
|
+
assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
|
1653
|
+
ensure
|
1654
|
+
ActiveRecord::Base.table_name_prefix = ""
|
1655
|
+
ActiveRecord::Base.table_name_suffix = ""
|
1656
|
+
end
|
1657
|
+
|
1658
|
+
def test_proper_table_name
|
1659
|
+
assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
|
1660
|
+
assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
|
1661
|
+
assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
|
1662
|
+
Reminder.reset_table_name
|
1663
|
+
assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
|
1664
|
+
|
1665
|
+
# Use the model's own prefix/suffix if a model is given
|
1666
|
+
ActiveRecord::Base.table_name_prefix = "ARprefix_"
|
1667
|
+
ActiveRecord::Base.table_name_suffix = "_ARsuffix"
|
1668
|
+
Reminder.table_name_prefix = 'prefix_'
|
1669
|
+
Reminder.table_name_suffix = '_suffix'
|
1670
|
+
Reminder.reset_table_name
|
1671
|
+
assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
|
1672
|
+
Reminder.table_name_prefix = ''
|
1673
|
+
Reminder.table_name_suffix = ''
|
1674
|
+
Reminder.reset_table_name
|
1675
|
+
|
1676
|
+
# Use AR::Base's prefix/suffix if string or symbol is given
|
1677
|
+
ActiveRecord::Base.table_name_prefix = "prefix_"
|
1678
|
+
ActiveRecord::Base.table_name_suffix = "_suffix"
|
1679
|
+
Reminder.reset_table_name
|
1680
|
+
assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
|
1681
|
+
assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
|
1682
|
+
ActiveRecord::Base.table_name_prefix = ""
|
1683
|
+
ActiveRecord::Base.table_name_suffix = ""
|
1684
|
+
Reminder.reset_table_name
|
1685
|
+
end
|
1686
|
+
|
1687
|
+
def test_rename_table_with_prefix_and_suffix
|
1688
|
+
assert !Thing.table_exists?
|
1689
|
+
ActiveRecord::Base.table_name_prefix = 'prefix_'
|
1690
|
+
ActiveRecord::Base.table_name_suffix = '_suffix'
|
1691
|
+
Thing.reset_table_name
|
1692
|
+
Thing.reset_sequence_name
|
1693
|
+
WeNeedThings.up
|
1694
|
+
|
1695
|
+
assert Thing.create("content" => "hello world")
|
1696
|
+
assert_equal "hello world", Thing.find(:first).content
|
1697
|
+
|
1698
|
+
RenameThings.up
|
1699
|
+
Thing.table_name = "prefix_awesome_things_suffix"
|
1700
|
+
|
1701
|
+
assert_equal "hello world", Thing.find(:first).content
|
1702
|
+
ensure
|
1703
|
+
ActiveRecord::Base.table_name_prefix = ''
|
1704
|
+
ActiveRecord::Base.table_name_suffix = ''
|
1705
|
+
Thing.reset_table_name
|
1706
|
+
Thing.reset_sequence_name
|
1707
|
+
end
|
1708
|
+
|
1709
|
+
def test_add_drop_table_with_prefix_and_suffix
|
1710
|
+
assert !Reminder.table_exists?
|
1711
|
+
ActiveRecord::Base.table_name_prefix = 'prefix_'
|
1712
|
+
ActiveRecord::Base.table_name_suffix = '_suffix'
|
1713
|
+
Reminder.reset_table_name
|
1714
|
+
Reminder.reset_sequence_name
|
1715
|
+
WeNeedReminders.up
|
1716
|
+
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
1717
|
+
assert_equal "hello world", Reminder.find(:first).content
|
1718
|
+
|
1719
|
+
WeNeedReminders.down
|
1720
|
+
assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
1721
|
+
ensure
|
1722
|
+
ActiveRecord::Base.table_name_prefix = ''
|
1723
|
+
ActiveRecord::Base.table_name_suffix = ''
|
1724
|
+
Reminder.reset_table_name
|
1725
|
+
Reminder.reset_sequence_name
|
1726
|
+
end
|
1727
|
+
|
1728
|
+
def test_create_table_with_binary_column
|
1729
|
+
Person.connection.drop_table :binary_testings rescue nil
|
1730
|
+
|
1731
|
+
assert_nothing_raised {
|
1732
|
+
Person.connection.create_table :binary_testings do |t|
|
1733
|
+
t.column "data", :binary, :null => false
|
1734
|
+
end
|
1735
|
+
}
|
1736
|
+
|
1737
|
+
columns = Person.connection.columns(:binary_testings)
|
1738
|
+
data_column = columns.detect { |c| c.name == "data" }
|
1739
|
+
|
1740
|
+
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
1741
|
+
assert_equal '', data_column.default
|
1742
|
+
else
|
1743
|
+
assert_nil data_column.default
|
1744
|
+
end
|
1745
|
+
|
1746
|
+
Person.connection.drop_table :binary_testings rescue nil
|
1747
|
+
end
|
1748
|
+
|
1749
|
+
def test_migrator_with_duplicates
|
1750
|
+
assert_raise(ActiveRecord::DuplicateMigrationVersionError) do
|
1751
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
|
1752
|
+
end
|
1753
|
+
end
|
1754
|
+
|
1755
|
+
def test_migrator_with_duplicate_names
|
1756
|
+
assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
|
1757
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
|
1758
|
+
end
|
1759
|
+
end
|
1760
|
+
|
1761
|
+
def test_migrator_with_missing_version_numbers
|
1762
|
+
assert_raise(ActiveRecord::UnknownMigrationVersionError) do
|
1763
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
|
1764
|
+
end
|
1765
|
+
end
|
1766
|
+
|
1767
|
+
def test_create_table_with_custom_sequence_name
|
1768
|
+
return unless current_adapter? :OracleAdapter
|
1769
|
+
|
1770
|
+
# table name is 29 chars, the standard sequence name will
|
1771
|
+
# be 33 chars and should be shortened
|
1772
|
+
assert_nothing_raised do
|
1773
|
+
begin
|
1774
|
+
Person.connection.create_table :table_with_name_thats_just_ok do |t|
|
1775
|
+
t.column :foo, :string, :null => false
|
1776
|
+
end
|
1777
|
+
ensure
|
1778
|
+
Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
|
1779
|
+
end
|
1780
|
+
end
|
1781
|
+
|
1782
|
+
# should be all good w/ a custom sequence name
|
1783
|
+
assert_nothing_raised do
|
1784
|
+
begin
|
1785
|
+
Person.connection.create_table :table_with_name_thats_just_ok,
|
1786
|
+
:sequence_name => 'suitably_short_seq' do |t|
|
1787
|
+
t.column :foo, :string, :null => false
|
1788
|
+
end
|
1789
|
+
|
1790
|
+
Person.connection.execute("select suitably_short_seq.nextval from dual")
|
1791
|
+
|
1792
|
+
ensure
|
1793
|
+
Person.connection.drop_table :table_with_name_thats_just_ok,
|
1794
|
+
:sequence_name => 'suitably_short_seq' rescue nil
|
1795
|
+
end
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
# confirm the custom sequence got dropped
|
1799
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
1800
|
+
Person.connection.execute("select suitably_short_seq.nextval from dual")
|
1801
|
+
end
|
1802
|
+
end
|
1803
|
+
|
1804
|
+
protected
|
1805
|
+
def with_env_tz(new_tz = 'US/Eastern')
|
1806
|
+
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
|
1807
|
+
yield
|
1808
|
+
ensure
|
1809
|
+
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
|
1810
|
+
end
|
1811
|
+
|
1812
|
+
end
|
1813
|
+
|
1814
|
+
class MigrationLoggerTest < ActiveRecord::TestCase
|
1815
|
+
def test_migration_should_be_run_without_logger
|
1816
|
+
previous_logger = ActiveRecord::Base.logger
|
1817
|
+
ActiveRecord::Base.logger = nil
|
1818
|
+
assert_nothing_raised do
|
1819
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
|
1820
|
+
end
|
1821
|
+
ensure
|
1822
|
+
ActiveRecord::Base.logger = previous_logger
|
1823
|
+
end
|
1824
|
+
end
|
1825
|
+
|
1826
|
+
class InterleavedMigrationsTest < ActiveRecord::TestCase
|
1827
|
+
def test_migrator_interleaved_migrations
|
1828
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
|
1829
|
+
|
1830
|
+
assert_nothing_raised do
|
1831
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
|
1832
|
+
end
|
1833
|
+
|
1834
|
+
Person.reset_column_information
|
1835
|
+
assert Person.column_methods_hash.include?(:last_name)
|
1836
|
+
|
1837
|
+
assert_nothing_raised do
|
1838
|
+
proxies = ActiveRecord::Migrator.down(
|
1839
|
+
MIGRATIONS_ROOT + "/interleaved/pass_3")
|
1840
|
+
names = proxies.map(&:name)
|
1841
|
+
assert names.include?('InterleavedPeopleHaveLastNames')
|
1842
|
+
assert names.include?('InterleavedInnocentJointable')
|
1843
|
+
end
|
1844
|
+
end
|
1845
|
+
end
|
1846
|
+
|
1847
|
+
class ReservedWordsMigrationTest < ActiveRecord::TestCase
|
1848
|
+
def test_drop_index_from_table_named_values
|
1849
|
+
connection = Person.connection
|
1850
|
+
connection.create_table :values, :force => true do |t|
|
1851
|
+
t.integer :value
|
1852
|
+
end
|
1853
|
+
|
1854
|
+
assert_nothing_raised do
|
1855
|
+
connection.add_index :values, :value
|
1856
|
+
connection.remove_index :values, :column => :value
|
1857
|
+
end
|
1858
|
+
|
1859
|
+
connection.drop_table :values rescue nil
|
1860
|
+
end
|
1861
|
+
end
|
1862
|
+
|
1863
|
+
|
1864
|
+
class ChangeTableMigrationsTest < ActiveRecord::TestCase
|
1865
|
+
def setup
|
1866
|
+
@connection = Person.connection
|
1867
|
+
@connection.create_table :delete_me, :force => true do |t|
|
1868
|
+
end
|
1869
|
+
end
|
1870
|
+
|
1871
|
+
def teardown
|
1872
|
+
Person.connection.drop_table :delete_me rescue nil
|
1873
|
+
end
|
1874
|
+
|
1875
|
+
def test_references_column_type_adds_id
|
1876
|
+
with_change_table do |t|
|
1877
|
+
@connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
|
1878
|
+
t.references :customer
|
1879
|
+
end
|
1880
|
+
end
|
1881
|
+
|
1882
|
+
def test_remove_references_column_type_removes_id
|
1883
|
+
with_change_table do |t|
|
1884
|
+
@connection.expects(:remove_column).with(:delete_me, 'customer_id')
|
1885
|
+
t.remove_references :customer
|
1886
|
+
end
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
def test_add_belongs_to_works_like_add_references
|
1890
|
+
with_change_table do |t|
|
1891
|
+
@connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
|
1892
|
+
t.belongs_to :customer
|
1893
|
+
end
|
1894
|
+
end
|
1895
|
+
|
1896
|
+
def test_remove_belongs_to_works_like_remove_references
|
1897
|
+
with_change_table do |t|
|
1898
|
+
@connection.expects(:remove_column).with(:delete_me, 'customer_id')
|
1899
|
+
t.remove_belongs_to :customer
|
1900
|
+
end
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
def test_references_column_type_with_polymorphic_adds_type
|
1904
|
+
with_change_table do |t|
|
1905
|
+
@connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
|
1906
|
+
@connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
|
1907
|
+
t.references :taggable, :polymorphic => true
|
1908
|
+
end
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
def test_remove_references_column_type_with_polymorphic_removes_type
|
1912
|
+
with_change_table do |t|
|
1913
|
+
@connection.expects(:remove_column).with(:delete_me, 'taggable_type')
|
1914
|
+
@connection.expects(:remove_column).with(:delete_me, 'taggable_id')
|
1915
|
+
t.remove_references :taggable, :polymorphic => true
|
1916
|
+
end
|
1917
|
+
end
|
1918
|
+
|
1919
|
+
def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
|
1920
|
+
with_change_table do |t|
|
1921
|
+
@connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
|
1922
|
+
@connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
|
1923
|
+
t.references :taggable, :polymorphic => true, :null => false
|
1924
|
+
end
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
|
1928
|
+
with_change_table do |t|
|
1929
|
+
@connection.expects(:remove_column).with(:delete_me, 'taggable_type')
|
1930
|
+
@connection.expects(:remove_column).with(:delete_me, 'taggable_id')
|
1931
|
+
t.remove_references :taggable, :polymorphic => true, :null => false
|
1932
|
+
end
|
1933
|
+
end
|
1934
|
+
|
1935
|
+
def test_timestamps_creates_updated_at_and_created_at
|
1936
|
+
with_change_table do |t|
|
1937
|
+
@connection.expects(:add_timestamps).with(:delete_me)
|
1938
|
+
t.timestamps
|
1939
|
+
end
|
1940
|
+
end
|
1941
|
+
|
1942
|
+
def test_remove_timestamps_creates_updated_at_and_created_at
|
1943
|
+
with_change_table do |t|
|
1944
|
+
@connection.expects(:remove_timestamps).with(:delete_me)
|
1945
|
+
t.remove_timestamps
|
1946
|
+
end
|
1947
|
+
end
|
1948
|
+
|
1949
|
+
def string_column
|
1950
|
+
if current_adapter?(:PostgreSQLAdapter)
|
1951
|
+
"character varying(255)"
|
1952
|
+
elsif current_adapter?(:OracleAdapter)
|
1953
|
+
'VARCHAR2(255)'
|
1954
|
+
else
|
1955
|
+
'varchar(255)'
|
1956
|
+
end
|
1957
|
+
end
|
1958
|
+
|
1959
|
+
def integer_column
|
1960
|
+
if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
|
1961
|
+
'int(11)'
|
1962
|
+
elsif current_adapter?(:OracleAdapter)
|
1963
|
+
'NUMBER(38)'
|
1964
|
+
else
|
1965
|
+
'integer'
|
1966
|
+
end
|
1967
|
+
end
|
1968
|
+
|
1969
|
+
def test_integer_creates_integer_column
|
1970
|
+
with_change_table do |t|
|
1971
|
+
@connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
|
1972
|
+
@connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
|
1973
|
+
t.integer :foo, :bar
|
1974
|
+
end
|
1975
|
+
end
|
1976
|
+
|
1977
|
+
def test_string_creates_string_column
|
1978
|
+
with_change_table do |t|
|
1979
|
+
@connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
|
1980
|
+
@connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
|
1981
|
+
t.string :foo, :bar
|
1982
|
+
end
|
1983
|
+
end
|
1984
|
+
|
1985
|
+
def test_column_creates_column
|
1986
|
+
with_change_table do |t|
|
1987
|
+
@connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
|
1988
|
+
t.column :bar, :integer
|
1989
|
+
end
|
1990
|
+
end
|
1991
|
+
|
1992
|
+
def test_column_creates_column_with_options
|
1993
|
+
with_change_table do |t|
|
1994
|
+
@connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
|
1995
|
+
t.column :bar, :integer, :null => false
|
1996
|
+
end
|
1997
|
+
end
|
1998
|
+
|
1999
|
+
def test_index_creates_index
|
2000
|
+
with_change_table do |t|
|
2001
|
+
@connection.expects(:add_index).with(:delete_me, :bar, {})
|
2002
|
+
t.index :bar
|
2003
|
+
end
|
2004
|
+
end
|
2005
|
+
|
2006
|
+
def test_index_creates_index_with_options
|
2007
|
+
with_change_table do |t|
|
2008
|
+
@connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
|
2009
|
+
t.index :bar, :unique => true
|
2010
|
+
end
|
2011
|
+
end
|
2012
|
+
|
2013
|
+
def test_index_exists
|
2014
|
+
with_change_table do |t|
|
2015
|
+
@connection.expects(:index_exists?).with(:delete_me, :bar, {})
|
2016
|
+
t.index_exists?(:bar)
|
2017
|
+
end
|
2018
|
+
end
|
2019
|
+
|
2020
|
+
def test_index_exists_with_options
|
2021
|
+
with_change_table do |t|
|
2022
|
+
@connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true})
|
2023
|
+
t.index_exists?(:bar, :unique => true)
|
2024
|
+
end
|
2025
|
+
end
|
2026
|
+
|
2027
|
+
def test_change_changes_column
|
2028
|
+
with_change_table do |t|
|
2029
|
+
@connection.expects(:change_column).with(:delete_me, :bar, :string, {})
|
2030
|
+
t.change :bar, :string
|
2031
|
+
end
|
2032
|
+
end
|
2033
|
+
|
2034
|
+
def test_change_changes_column_with_options
|
2035
|
+
with_change_table do |t|
|
2036
|
+
@connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
|
2037
|
+
t.change :bar, :string, :null => true
|
2038
|
+
end
|
2039
|
+
end
|
2040
|
+
|
2041
|
+
def test_change_default_changes_column
|
2042
|
+
with_change_table do |t|
|
2043
|
+
@connection.expects(:change_column_default).with(:delete_me, :bar, :string)
|
2044
|
+
t.change_default :bar, :string
|
2045
|
+
end
|
2046
|
+
end
|
2047
|
+
|
2048
|
+
def test_remove_drops_single_column
|
2049
|
+
with_change_table do |t|
|
2050
|
+
@connection.expects(:remove_column).with(:delete_me, [:bar])
|
2051
|
+
t.remove :bar
|
2052
|
+
end
|
2053
|
+
end
|
2054
|
+
|
2055
|
+
def test_remove_drops_multiple_columns
|
2056
|
+
with_change_table do |t|
|
2057
|
+
@connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
|
2058
|
+
t.remove :bar, :baz
|
2059
|
+
end
|
2060
|
+
end
|
2061
|
+
|
2062
|
+
def test_remove_index_removes_index_with_options
|
2063
|
+
with_change_table do |t|
|
2064
|
+
@connection.expects(:remove_index).with(:delete_me, {:unique => true})
|
2065
|
+
t.remove_index :unique => true
|
2066
|
+
end
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
def test_rename_renames_column
|
2070
|
+
with_change_table do |t|
|
2071
|
+
@connection.expects(:rename_column).with(:delete_me, :bar, :baz)
|
2072
|
+
t.rename :bar, :baz
|
2073
|
+
end
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
protected
|
2077
|
+
def with_change_table
|
2078
|
+
Person.connection.change_table :delete_me do |t|
|
2079
|
+
yield t
|
2080
|
+
end
|
2081
|
+
end
|
2082
|
+
end
|
2083
|
+
|
2084
|
+
if ActiveRecord::Base.connection.supports_bulk_alter?
|
2085
|
+
class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
|
2086
|
+
def setup
|
2087
|
+
@connection = Person.connection
|
2088
|
+
@connection.create_table(:delete_me, :force => true) {|t| }
|
2089
|
+
end
|
2090
|
+
|
2091
|
+
def teardown
|
2092
|
+
Person.connection.drop_table(:delete_me) rescue nil
|
2093
|
+
end
|
2094
|
+
|
2095
|
+
def test_adding_multiple_columns
|
2096
|
+
assert_queries(1) do
|
2097
|
+
with_bulk_change_table do |t|
|
2098
|
+
t.column :name, :string
|
2099
|
+
t.string :qualification, :experience
|
2100
|
+
t.integer :age, :default => 0
|
2101
|
+
t.date :birthdate
|
2102
|
+
t.timestamps
|
2103
|
+
end
|
2104
|
+
end
|
2105
|
+
|
2106
|
+
assert_equal 8, columns.size
|
2107
|
+
[:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
|
2108
|
+
assert_equal 0, column(:age).default
|
2109
|
+
end
|
2110
|
+
|
2111
|
+
def test_removing_columns
|
2112
|
+
with_bulk_change_table do |t|
|
2113
|
+
t.string :qualification, :experience
|
2114
|
+
end
|
2115
|
+
|
2116
|
+
[:qualification, :experience].each {|c| assert column(c) }
|
2117
|
+
|
2118
|
+
assert_queries(1) do
|
2119
|
+
with_bulk_change_table do |t|
|
2120
|
+
t.remove :qualification, :experience
|
2121
|
+
t.string :qualification_experience
|
2122
|
+
end
|
2123
|
+
end
|
2124
|
+
|
2125
|
+
[:qualification, :experience].each {|c| assert ! column(c) }
|
2126
|
+
assert column(:qualification_experience)
|
2127
|
+
end
|
2128
|
+
|
2129
|
+
def test_adding_indexes
|
2130
|
+
with_bulk_change_table do |t|
|
2131
|
+
t.string :username
|
2132
|
+
t.string :name
|
2133
|
+
t.integer :age
|
2134
|
+
end
|
2135
|
+
|
2136
|
+
# Adding an index fires a query every time to check if an index already exists or not
|
2137
|
+
assert_queries(3) do
|
2138
|
+
with_bulk_change_table do |t|
|
2139
|
+
t.index :username, :unique => true, :name => :awesome_username_index
|
2140
|
+
t.index [:name, :age]
|
2141
|
+
end
|
2142
|
+
end
|
2143
|
+
|
2144
|
+
assert_equal 2, indexes.size
|
2145
|
+
|
2146
|
+
name_age_index = index(:index_delete_me_on_name_and_age)
|
2147
|
+
assert_equal ['name', 'age'].sort, name_age_index.columns.sort
|
2148
|
+
assert ! name_age_index.unique
|
2149
|
+
|
2150
|
+
assert index(:awesome_username_index).unique
|
2151
|
+
end
|
2152
|
+
|
2153
|
+
def test_removing_index
|
2154
|
+
with_bulk_change_table do |t|
|
2155
|
+
t.string :name
|
2156
|
+
t.index :name
|
2157
|
+
end
|
2158
|
+
|
2159
|
+
assert index(:index_delete_me_on_name)
|
2160
|
+
|
2161
|
+
assert_queries(3) do
|
2162
|
+
with_bulk_change_table do |t|
|
2163
|
+
t.remove_index :name
|
2164
|
+
t.index :name, :name => :new_name_index, :unique => true
|
2165
|
+
end
|
2166
|
+
end
|
2167
|
+
|
2168
|
+
assert ! index(:index_delete_me_on_name)
|
2169
|
+
|
2170
|
+
new_name_index = index(:new_name_index)
|
2171
|
+
assert new_name_index.unique
|
2172
|
+
end
|
2173
|
+
|
2174
|
+
def test_changing_columns
|
2175
|
+
with_bulk_change_table do |t|
|
2176
|
+
t.string :name
|
2177
|
+
t.date :birthdate
|
2178
|
+
end
|
2179
|
+
|
2180
|
+
assert ! column(:name).default
|
2181
|
+
assert_equal :date, column(:birthdate).type
|
2182
|
+
|
2183
|
+
# One query for columns (delete_me table)
|
2184
|
+
# One query for primary key (delete_me table)
|
2185
|
+
# One query to do the bulk change
|
2186
|
+
assert_queries(3) do
|
2187
|
+
with_bulk_change_table do |t|
|
2188
|
+
t.change :name, :string, :default => 'NONAME'
|
2189
|
+
t.change :birthdate, :datetime
|
2190
|
+
end
|
2191
|
+
end
|
2192
|
+
|
2193
|
+
assert_equal 'NONAME', column(:name).default
|
2194
|
+
assert_equal :datetime, column(:birthdate).type
|
2195
|
+
end
|
2196
|
+
|
2197
|
+
protected
|
2198
|
+
|
2199
|
+
def with_bulk_change_table
|
2200
|
+
# Reset columns/indexes cache as we're changing the table
|
2201
|
+
@columns = @indexes = nil
|
2202
|
+
|
2203
|
+
Person.connection.change_table(:delete_me, :bulk => true) do |t|
|
2204
|
+
yield t
|
2205
|
+
end
|
2206
|
+
end
|
2207
|
+
|
2208
|
+
def column(name)
|
2209
|
+
columns.detect {|c| c.name == name.to_s }
|
2210
|
+
end
|
2211
|
+
|
2212
|
+
def columns
|
2213
|
+
@columns ||= Person.connection.columns('delete_me')
|
2214
|
+
end
|
2215
|
+
|
2216
|
+
def index(name)
|
2217
|
+
indexes.detect {|i| i.name == name.to_s }
|
2218
|
+
end
|
2219
|
+
|
2220
|
+
def indexes
|
2221
|
+
@indexes ||= Person.connection.indexes('delete_me')
|
2222
|
+
end
|
2223
|
+
end # AlterTableMigrationsTest
|
2224
|
+
|
2225
|
+
end
|
2226
|
+
|
2227
|
+
class CopyMigrationsTest < ActiveRecord::TestCase
|
2228
|
+
def setup
|
2229
|
+
end
|
2230
|
+
|
2231
|
+
def clear
|
2232
|
+
ActiveRecord::Base.timestamped_migrations = true
|
2233
|
+
to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
|
2234
|
+
File.delete(*to_delete)
|
2235
|
+
end
|
2236
|
+
|
2237
|
+
def test_copying_migrations_without_timestamps
|
2238
|
+
ActiveRecord::Base.timestamped_migrations = false
|
2239
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid"
|
2240
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2241
|
+
|
2242
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
|
2243
|
+
assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
|
2244
|
+
assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
|
2245
|
+
assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
|
2246
|
+
|
2247
|
+
expected = "# This migration comes from bukkits (originally 1)"
|
2248
|
+
assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
|
2249
|
+
|
2250
|
+
files_count = Dir[@migrations_path + "/*.rb"].length
|
2251
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
|
2252
|
+
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2253
|
+
assert copied.empty?
|
2254
|
+
ensure
|
2255
|
+
clear
|
2256
|
+
end
|
2257
|
+
|
2258
|
+
def test_copying_migrations_without_timestamps_from_2_sources
|
2259
|
+
ActiveRecord::Base.timestamped_migrations = false
|
2260
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid"
|
2261
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2262
|
+
|
2263
|
+
sources = ActiveSupport::OrderedHash.new
|
2264
|
+
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
|
2265
|
+
sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
|
2266
|
+
ActiveRecord::Migration.copy(@migrations_path, sources)
|
2267
|
+
assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
|
2268
|
+
assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
|
2269
|
+
assert File.exists?(@migrations_path + "/6_create_articles.omg.rb")
|
2270
|
+
assert File.exists?(@migrations_path + "/7_create_comments.omg.rb")
|
2271
|
+
|
2272
|
+
files_count = Dir[@migrations_path + "/*.rb"].length
|
2273
|
+
ActiveRecord::Migration.copy(@migrations_path, sources)
|
2274
|
+
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2275
|
+
ensure
|
2276
|
+
clear
|
2277
|
+
end
|
2278
|
+
|
2279
|
+
def test_copying_migrations_with_timestamps
|
2280
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2281
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2282
|
+
|
2283
|
+
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2284
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2285
|
+
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2286
|
+
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2287
|
+
expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
|
2288
|
+
@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
|
2289
|
+
assert_equal expected, copied.map(&:filename)
|
2290
|
+
|
2291
|
+
files_count = Dir[@migrations_path + "/*.rb"].length
|
2292
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2293
|
+
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2294
|
+
assert copied.empty?
|
2295
|
+
end
|
2296
|
+
ensure
|
2297
|
+
clear
|
2298
|
+
end
|
2299
|
+
|
2300
|
+
def test_copying_migrations_with_timestamps_from_2_sources
|
2301
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2302
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2303
|
+
|
2304
|
+
sources = ActiveSupport::OrderedHash.new
|
2305
|
+
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
|
2306
|
+
sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
|
2307
|
+
|
2308
|
+
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2309
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, sources)
|
2310
|
+
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2311
|
+
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2312
|
+
assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb")
|
2313
|
+
assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb")
|
2314
|
+
assert_equal 4, copied.length
|
2315
|
+
|
2316
|
+
files_count = Dir[@migrations_path + "/*.rb"].length
|
2317
|
+
ActiveRecord::Migration.copy(@migrations_path, sources)
|
2318
|
+
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2319
|
+
end
|
2320
|
+
ensure
|
2321
|
+
clear
|
2322
|
+
end
|
2323
|
+
|
2324
|
+
def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
|
2325
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2326
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2327
|
+
|
2328
|
+
Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
|
2329
|
+
ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2330
|
+
assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
|
2331
|
+
assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
|
2332
|
+
|
2333
|
+
files_count = Dir[@migrations_path + "/*.rb"].length
|
2334
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2335
|
+
assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
|
2336
|
+
assert copied.empty?
|
2337
|
+
end
|
2338
|
+
ensure
|
2339
|
+
clear
|
2340
|
+
end
|
2341
|
+
|
2342
|
+
def test_skipping_migrations
|
2343
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2344
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2345
|
+
|
2346
|
+
sources = ActiveSupport::OrderedHash.new
|
2347
|
+
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
|
2348
|
+
sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
|
2349
|
+
|
2350
|
+
skipped = []
|
2351
|
+
on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
|
2352
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
|
2353
|
+
assert_equal 2, copied.length
|
2354
|
+
|
2355
|
+
assert_equal 1, skipped.length
|
2356
|
+
assert_equal ["omg PeopleHaveHobbies"], skipped
|
2357
|
+
ensure
|
2358
|
+
clear
|
2359
|
+
end
|
2360
|
+
|
2361
|
+
def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
|
2362
|
+
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
|
2363
|
+
@existing_migrations = Dir[@migrations_path + "/*.rb"]
|
2364
|
+
|
2365
|
+
sources = ActiveSupport::OrderedHash.new
|
2366
|
+
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
|
2367
|
+
|
2368
|
+
skipped = []
|
2369
|
+
on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
|
2370
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
|
2371
|
+
ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
|
2372
|
+
|
2373
|
+
assert_equal 2, copied.length
|
2374
|
+
assert_equal 0, skipped.length
|
2375
|
+
ensure
|
2376
|
+
clear
|
2377
|
+
end
|
2378
|
+
|
2379
|
+
def test_copying_migrations_to_non_existing_directory
|
2380
|
+
@migrations_path = MIGRATIONS_ROOT + "/non_existing"
|
2381
|
+
@existing_migrations = []
|
2382
|
+
|
2383
|
+
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2384
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2385
|
+
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2386
|
+
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2387
|
+
assert_equal 2, copied.length
|
2388
|
+
end
|
2389
|
+
ensure
|
2390
|
+
clear
|
2391
|
+
Dir.delete(@migrations_path)
|
2392
|
+
end
|
2393
|
+
|
2394
|
+
def test_copying_migrations_to_empty_directory
|
2395
|
+
@migrations_path = MIGRATIONS_ROOT + "/empty"
|
2396
|
+
@existing_migrations = []
|
2397
|
+
|
2398
|
+
Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
|
2399
|
+
copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
|
2400
|
+
assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
|
2401
|
+
assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
|
2402
|
+
assert_equal 2, copied.length
|
2403
|
+
end
|
2404
|
+
ensure
|
2405
|
+
clear
|
2406
|
+
end
|
2407
|
+
end
|
2408
|
+
end
|