odbc-rails 1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/AUTHORS +16 -0
  2. data/COPYING +21 -0
  3. data/ChangeLog +89 -0
  4. data/LICENSE +5 -0
  5. data/NEWS +12 -0
  6. data/README +282 -0
  7. data/lib/active_record/connection_adapters/odbc_adapter.rb +1792 -0
  8. data/lib/active_record/vendor/odbcext_db2.rb +87 -0
  9. data/lib/active_record/vendor/odbcext_informix.rb +132 -0
  10. data/lib/active_record/vendor/odbcext_informix_col.rb +45 -0
  11. data/lib/active_record/vendor/odbcext_ingres.rb +156 -0
  12. data/lib/active_record/vendor/odbcext_microsoftsqlserver.rb +185 -0
  13. data/lib/active_record/vendor/odbcext_microsoftsqlserver_col.rb +40 -0
  14. data/lib/active_record/vendor/odbcext_mysql.rb +136 -0
  15. data/lib/active_record/vendor/odbcext_oracle.rb +220 -0
  16. data/lib/active_record/vendor/odbcext_postgresql.rb +179 -0
  17. data/lib/active_record/vendor/odbcext_progress.rb +139 -0
  18. data/lib/active_record/vendor/odbcext_progress89.rb +259 -0
  19. data/lib/active_record/vendor/odbcext_sybase.rb +212 -0
  20. data/lib/active_record/vendor/odbcext_sybase_col.rb +49 -0
  21. data/lib/active_record/vendor/odbcext_virtuoso.rb +146 -0
  22. data/lib/odbc_adapter.rb +28 -0
  23. data/support/lib/active_record/connection_adapters/abstract/schema_definitions.rb +259 -0
  24. data/support/odbc_rails.diff +707 -0
  25. data/support/pack_odbc.rb +119 -0
  26. data/support/rake/rails_plugin_package_task.rb +212 -0
  27. data/support/test/base_test.rb +1349 -0
  28. data/support/test/migration_test.rb +566 -0
  29. data/test/connections/native_odbc/connection.rb +95 -0
  30. data/test/fixtures/db_definitions/db2.drop.sql +30 -0
  31. data/test/fixtures/db_definitions/db2.sql +217 -0
  32. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  33. data/test/fixtures/db_definitions/db22.sql +5 -0
  34. data/test/fixtures/db_definitions/informix.drop.sql +30 -0
  35. data/test/fixtures/db_definitions/informix.sql +205 -0
  36. data/test/fixtures/db_definitions/informix2.drop.sql +2 -0
  37. data/test/fixtures/db_definitions/informix2.sql +5 -0
  38. data/test/fixtures/db_definitions/ingres.drop.sql +62 -0
  39. data/test/fixtures/db_definitions/ingres.sql +232 -0
  40. data/test/fixtures/db_definitions/ingres2.drop.sql +2 -0
  41. data/test/fixtures/db_definitions/ingres2.sql +5 -0
  42. data/test/fixtures/db_definitions/mysql.drop.sql +30 -0
  43. data/test/fixtures/db_definitions/mysql.sql +219 -0
  44. data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
  45. data/test/fixtures/db_definitions/mysql2.sql +5 -0
  46. data/test/fixtures/db_definitions/oracle_odbc.drop.sql +64 -0
  47. data/test/fixtures/db_definitions/oracle_odbc.sql +257 -0
  48. data/test/fixtures/db_definitions/oracle_odbc2.drop.sql +2 -0
  49. data/test/fixtures/db_definitions/oracle_odbc2.sql +6 -0
  50. data/test/fixtures/db_definitions/progress.drop.sql +61 -0
  51. data/test/fixtures/db_definitions/progress.sql +234 -0
  52. data/test/fixtures/db_definitions/progress2.drop.sql +2 -0
  53. data/test/fixtures/db_definitions/progress2.sql +6 -0
  54. data/test/fixtures/db_definitions/sqlserver.drop.sql +30 -0
  55. data/test/fixtures/db_definitions/sqlserver.sql +203 -0
  56. data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
  57. data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
  58. data/test/fixtures/db_definitions/sybase.drop.sql +31 -0
  59. data/test/fixtures/db_definitions/sybase.sql +204 -0
  60. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  61. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  62. data/test/fixtures/db_definitions/virtuoso.drop.sql +30 -0
  63. data/test/fixtures/db_definitions/virtuoso.sql +200 -0
  64. data/test/fixtures/db_definitions/virtuoso2.drop.sql +2 -0
  65. data/test/fixtures/db_definitions/virtuoso2.sql +5 -0
  66. metadata +149 -0
@@ -0,0 +1,566 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/person'
3
+ require File.dirname(__FILE__) + '/fixtures/migrations/1_people_have_last_names'
4
+ require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders'
5
+
6
+ if ActiveRecord::Base.connection.supports_migrations?
7
+ class Reminder < ActiveRecord::Base; end
8
+
9
+ class ActiveRecord::Migration
10
+ class <<self
11
+ attr_accessor :message_count
12
+ def puts(text="")
13
+ self.message_count ||= 0
14
+ self.message_count += 1
15
+ end
16
+ end
17
+ end
18
+
19
+ class MigrationTest < Test::Unit::TestCase
20
+ self.use_transactional_fixtures = false
21
+
22
+ def setup
23
+ ActiveRecord::Migration.verbose = true
24
+ PeopleHaveLastNames.message_count = 0
25
+ end
26
+
27
+ def teardown
28
+ ActiveRecord::Base.connection.initialize_schema_information
29
+ ActiveRecord::Base.connection.update "UPDATE #{ActiveRecord::Migrator.schema_info_table_name} SET version = 0"
30
+
31
+ Reminder.connection.drop_table("reminders") rescue nil
32
+ Reminder.connection.drop_table("people_reminders") rescue nil
33
+ Reminder.connection.drop_table("prefix_reminders_suffix") rescue nil
34
+ Reminder.reset_column_information
35
+
36
+ Person.connection.remove_column("people", "last_name") rescue nil
37
+ Person.connection.remove_column("people", "key") rescue nil
38
+ Person.connection.remove_column("people", "bio") rescue nil
39
+ Person.connection.remove_column("people", "age") rescue nil
40
+ Person.connection.remove_column("people", "height") rescue nil
41
+ Person.connection.remove_column("people", "birthday") rescue nil
42
+ Person.connection.remove_column("people", "favorite_day") rescue nil
43
+ Person.connection.remove_column("people", "male") rescue nil
44
+ Person.connection.remove_column("people", "administrator") rescue nil
45
+ Person.reset_column_information
46
+ end
47
+
48
+ def test_add_index
49
+ if current_adapter?(:ODBCAdapter) && ActiveRecord::Base.connection.dbmsName == :informix
50
+ # Index on (last_name, first_name) exceeds max. index width supported by Informix if
51
+ # both columns are created with a default width of 255, in which case
52
+ # Informix may return error -517: "The total size of the index is too large..."
53
+ Person.connection.add_column "people", "last_name", :string, {:limit => 40}
54
+ else
55
+ Person.connection.add_column "people", "last_name", :string
56
+ end
57
+ Person.connection.add_column "people", "administrator", :boolean
58
+ Person.connection.add_column "people", "key", :string
59
+
60
+ assert_nothing_raised { Person.connection.add_index("people", "last_name") }
61
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
62
+
63
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
64
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
65
+
66
+ # quoting
67
+ assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key", :unique => true) }
68
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "key") }
69
+
70
+ # Sybase adapter does not support indexes on :boolean columns
71
+ unless current_adapter?(:SybaseAdapter) ||
72
+ current_adapter?(:ODBCAdapter) && ActiveRecord::Base.connection.dbmsName == :sybase
73
+ assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
74
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
75
+ end
76
+ end
77
+
78
+ def test_create_table_adds_id
79
+ Person.connection.create_table :testings do |t|
80
+ t.column :foo, :string
81
+ end
82
+
83
+ assert_equal %w(foo id),
84
+ Person.connection.columns(:testings).map { |c| c.name }.sort
85
+ ensure
86
+ Person.connection.drop_table :testings rescue nil
87
+ end
88
+
89
+ def test_create_table_with_not_null_column
90
+ Person.connection.create_table :testings do |t|
91
+ t.column :foo, :string, :null => false
92
+ end
93
+
94
+ assert_raises(ActiveRecord::StatementInvalid) do
95
+ Person.connection.execute "insert into testings (foo) values (NULL)"
96
+ end
97
+ ensure
98
+ Person.connection.drop_table :testings rescue nil
99
+ end
100
+
101
+ def test_create_table_with_defaults
102
+ Person.connection.create_table :testings do |t|
103
+ t.column :one, :string, :default => "hello"
104
+ t.column :two, :boolean, :default => true
105
+ t.column :three, :boolean, :default => false
106
+ t.column :four, :integer, :default => 1
107
+ end
108
+
109
+ columns = Person.connection.columns(:testings)
110
+ one = columns.detect { |c| c.name == "one" }
111
+ two = columns.detect { |c| c.name == "two" }
112
+ three = columns.detect { |c| c.name == "three" }
113
+ four = columns.detect { |c| c.name == "four" }
114
+
115
+ assert_equal "hello", one.default
116
+ if current_adapter?(:OracleAdapter)
117
+ # Oracle doesn't support native booleans
118
+ assert_equal true, two.default == 1
119
+ assert_equal false, three.default != 0
120
+ elsif current_adapter?(:ODBCAdapter) &&
121
+ [:informix, :ingres, :virtuoso, :oracle, :mysql, :microsoftsqlserver].include?(ActiveRecord::Base.connection.dbmsName)
122
+ # Above databases/ODBC drivers don't support native booleans.
123
+ # They use an integer type instead.
124
+ assert_equal true, two.default == 1
125
+ assert_equal false, three.default != 0
126
+ else
127
+ assert_equal true, two.default
128
+ assert_equal false, three.default
129
+ end
130
+ assert_equal 1, four.default
131
+
132
+ ensure
133
+ Person.connection.drop_table :testings rescue nil
134
+ end
135
+
136
+ # SQL Server and Sybase will not allow you to add a NOT NULL column
137
+ # to a table without specifying a default value, so the
138
+ # following test must be skipped
139
+ unless current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) ||
140
+ current_adapter?(:ODBCAdapter) && [:microsoftsqlserver, :sybase].include?(ActiveRecord::Base.connection.dbmsName)
141
+ def test_add_column_not_null_without_default
142
+
143
+ Person.connection.create_table :testings do |t|
144
+ t.column :foo, :string
145
+ end
146
+ Person.connection.add_column :testings, :bar, :string, :null => false
147
+
148
+ assert_raises(ActiveRecord::StatementInvalid) do
149
+ Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
150
+ end
151
+ ensure
152
+ Person.connection.drop_table :testings rescue nil
153
+ end
154
+ end
155
+
156
+ def test_add_column_not_null_with_default
157
+ Person.connection.create_table :testings do |t|
158
+ t.column :foo, :string
159
+ end
160
+ if current_adapter?(:ODBCAdapter) && [:ingres].include?(ActiveRecord::Base.connection.dbmsName)
161
+ # Ingres requires that if 'ALTER TABLE table ADD column' specifies a NOT NULL constraint,
162
+ # then 'WITH DEFAULT' must also be specified *without* a default value.
163
+ Person.connection.add_column :testings, :bar, :string, :null => false
164
+ else
165
+ Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default"
166
+ end
167
+
168
+ assert_raises(ActiveRecord::StatementInvalid) do
169
+ Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
170
+ end
171
+ ensure
172
+ Person.connection.drop_table :testings rescue nil
173
+ end
174
+
175
+ def test_native_types
176
+ Person.delete_all
177
+ Person.connection.add_column "people", "last_name", :string
178
+ Person.connection.add_column "people", "bio", :text
179
+ Person.connection.add_column "people", "age", :integer
180
+ Person.connection.add_column "people", "height", :float
181
+ Person.connection.add_column "people", "birthday", :datetime
182
+ Person.connection.add_column "people", "favorite_day", :date
183
+ Person.connection.add_column "people", "male", :boolean
184
+ assert_nothing_raised { Person.create :first_name => 'bob', :last_name => 'bobsen', :bio => "I was born ....", :age => 18, :height => 1.78, :birthday => 18.years.ago, :favorite_day => 10.days.ago, :male => true }
185
+ bob = Person.find(:first)
186
+
187
+ assert_equal bob.first_name, 'bob'
188
+ assert_equal bob.last_name, 'bobsen'
189
+ assert_equal bob.bio, "I was born ...."
190
+ assert_equal bob.age, 18
191
+ assert_equal bob.male?, true
192
+
193
+ assert_equal String, bob.first_name.class
194
+ assert_equal String, bob.last_name.class
195
+ assert_equal String, bob.bio.class
196
+ assert_equal Fixnum, bob.age.class
197
+ assert_equal Time, bob.birthday.class
198
+
199
+ if current_adapter?(:SQLServerAdapter) ||
200
+ current_adapter?(:OracleAdapter) ||
201
+ current_adapter?(:SybaseAdapter) ||
202
+ (current_adapter?(:ODBCAdapter) &&
203
+ [:ingres, :oracle, :microsoftsqlserver].include?(ActiveRecord::Base.connection.dbmsName))
204
+ # SQL Server, Sybase, Oracle and Ingres don't differentiate between date/time
205
+ assert_equal Time, bob.favorite_day.class
206
+ else
207
+ assert_equal Date, bob.favorite_day.class
208
+ end
209
+
210
+ assert_equal TrueClass, bob.male?.class
211
+ end
212
+
213
+ def test_add_remove_single_field_using_string_arguments
214
+ assert !Person.column_methods_hash.include?(:last_name)
215
+
216
+ ActiveRecord::Migration.add_column 'people', 'last_name', :string
217
+
218
+ Person.reset_column_information
219
+ assert Person.column_methods_hash.include?(:last_name)
220
+
221
+ ActiveRecord::Migration.remove_column 'people', 'last_name'
222
+
223
+ Person.reset_column_information
224
+ assert !Person.column_methods_hash.include?(:last_name)
225
+ end
226
+
227
+ def test_add_remove_single_field_using_symbol_arguments
228
+ assert !Person.column_methods_hash.include?(:last_name)
229
+
230
+ ActiveRecord::Migration.add_column :people, :last_name, :string
231
+
232
+ Person.reset_column_information
233
+ assert Person.column_methods_hash.include?(:last_name)
234
+
235
+ ActiveRecord::Migration.remove_column :people, :last_name
236
+
237
+ Person.reset_column_information
238
+ assert !Person.column_methods_hash.include?(:last_name)
239
+ end
240
+
241
+ # Ingres, Virtuoso:
242
+ # Neither supports renaming of columns. Skip test.
243
+ unless current_adapter?(:ODBCAdapter) &&
244
+ [:ingres, :virtuoso].include?(ActiveRecord::Base.connection.dbmsName)
245
+ def test_add_rename
246
+ Person.delete_all
247
+
248
+ begin
249
+ # Some DBs complain girlfriend column already exists on two consecutive add_column calls
250
+ unless current_adapter?(:ODBCAdapter) && [:informix, :oracle, :mysql, :microsoftsqlserver, :sybase].include?(ActiveRecord::Base.connection.dbmsName)
251
+ Person.connection.add_column "people", "girlfriend", :string
252
+ end
253
+ Person.connection.add_column "people", "girlfriend", :string, :limit => 40
254
+ Person.create :girlfriend => 'bobette'
255
+
256
+ Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
257
+
258
+ Person.reset_column_information
259
+ bob = Person.find(:first)
260
+
261
+ assert_equal "bobette", bob.exgirlfriend
262
+ ensure
263
+ Person.connection.remove_column("people", "girlfriend") rescue nil
264
+ Person.connection.remove_column("people", "exgirlfriend") rescue nil
265
+ end
266
+ end
267
+ end
268
+
269
+ # Ingres and Virtuoso don't support renaming of columns. Skip test.
270
+ unless current_adapter?(:ODBCAdapter) && [:ingres, :virtuoso].include?(ActiveRecord::Base.connection.dbmsName)
271
+ def test_rename_column_using_symbol_arguments
272
+ begin
273
+ Person.connection.rename_column :people, :first_name, :nick_name
274
+ Person.reset_column_information
275
+ assert Person.column_names.include?("nick_name")
276
+ ensure
277
+ Person.connection.remove_column("people","nick_name")
278
+ Person.connection.add_column("people","first_name", :string)
279
+ end
280
+ end
281
+ end
282
+
283
+ # Ingres and Virtuoso don't support renaming of columns. Skip test.
284
+ unless current_adapter?(:ODBCAdapter) && [:ingres, :virtuoso].include?(ActiveRecord::Base.connection.dbmsName)
285
+ def test_rename_column
286
+ begin
287
+ Person.connection.rename_column "people", "first_name", "nick_name"
288
+ Person.reset_column_information
289
+ assert Person.column_names.include?("nick_name")
290
+ ensure
291
+ Person.connection.remove_column("people","nick_name")
292
+ Person.connection.add_column("people","first_name", :string)
293
+ end
294
+ end
295
+ end
296
+
297
+ # Ingres doesn't support renaming of tables. Skip test.
298
+ unless current_adapter?(:ODBCAdapter) && [:ingres].include?(ActiveRecord::Base.connection.dbmsName)
299
+ def test_rename_table
300
+ begin
301
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
302
+ t.column :url, :string
303
+ end
304
+ ActiveRecord::Base.connection.rename_table :octopuses, :octopi
305
+
306
+ assert_nothing_raised do
307
+ if current_adapter?(:OracleAdapter) ||
308
+ current_adapter?(:ODBCAdapter) && [:oracle].include?(ActiveRecord::Base.connection.dbmsName)
309
+ # Oracle requires the explicit sequence value for the pk
310
+ ActiveRecord::Base.connection.execute "INSERT INTO octopi (id, url) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
311
+ else
312
+ ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')"
313
+ end
314
+ end
315
+
316
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
317
+
318
+ ensure
319
+ ActiveRecord::Base.connection.drop_table :octopuses rescue nil
320
+ ActiveRecord::Base.connection.drop_table :octopi rescue nil
321
+ end
322
+ end
323
+ end
324
+
325
+ # Virtuoso disallows virtually all column type conversions.
326
+ # Conversion between any of the native types used by the ActiveRecord generic types is not allowed.
327
+ # Skip the test.
328
+ unless current_adapter?(:ODBCAdapter) && [:virtuoso].include?(ActiveRecord::Base.connection.dbmsName)
329
+ def test_change_column
330
+ #Ingres doesn't support changing an integer column to varchar/text.
331
+ if current_adapter?(:ODBCAdapter) && [:ingres].include?(ActiveRecord::Base.connection.dbmsName)
332
+ initial_type = :integer
333
+ new_type = :float
334
+ else
335
+ initial_type = :integer
336
+ new_type = :string
337
+ end
338
+
339
+ Person.connection.add_column 'people', 'age', initial_type
340
+ old_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
341
+ assert old_columns.find { |c| c.name == 'age' and c.type == initial_type }
342
+
343
+ assert_nothing_raised { Person.connection.change_column "people", "age", new_type }
344
+
345
+ new_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
346
+ assert_nil new_columns.find { |c| c.name == 'age' and c.type == initial_type }
347
+ assert new_columns.find { |c| c.name == 'age' and c.type == new_type }
348
+ end
349
+ end
350
+
351
+ # Ingres doesn't support ALTER TABLE ADD COLUMN WITH NULL WITH DEFAULT.
352
+ # Sybase ASE's ALTER TABLE doesn't support altering a column's DEFAULT definition.
353
+ unless current_adapter?(:ODBCAdapter) && [:ingres, :sybase].include?(ActiveRecord::Base.connection.dbmsName)
354
+ def test_change_column_with_new_default
355
+ Person.connection.add_column "people", "administrator", :boolean, :default => 1
356
+ Person.reset_column_information
357
+ assert Person.new.administrator?
358
+
359
+ assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => 0 }
360
+ Person.reset_column_information
361
+ assert !Person.new.administrator?
362
+ end
363
+ end
364
+
365
+ def test_add_table
366
+ assert !Reminder.table_exists?
367
+
368
+ WeNeedReminders.up
369
+
370
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
371
+ assert_equal "hello world", Reminder.find(:first).content
372
+
373
+ WeNeedReminders.down
374
+ assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
375
+ end
376
+
377
+ def test_migrator
378
+ assert !Person.column_methods_hash.include?(:last_name)
379
+ assert !Reminder.table_exists?
380
+
381
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
382
+
383
+ assert_equal 3, ActiveRecord::Migrator.current_version
384
+ Person.reset_column_information
385
+ assert Person.column_methods_hash.include?(:last_name)
386
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
387
+ assert_equal "hello world", Reminder.find(:first).content
388
+
389
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/')
390
+
391
+ assert_equal 0, ActiveRecord::Migrator.current_version
392
+ Person.reset_column_information
393
+ assert !Person.column_methods_hash.include?(:last_name)
394
+ assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
395
+ end
396
+
397
+ def test_migrator_one_up
398
+ assert !Person.column_methods_hash.include?(:last_name)
399
+ assert !Reminder.table_exists?
400
+
401
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
402
+
403
+ Person.reset_column_information
404
+ assert Person.column_methods_hash.include?(:last_name)
405
+ assert !Reminder.table_exists?
406
+
407
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 2)
408
+
409
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
410
+ assert_equal "hello world", Reminder.find(:first).content
411
+ end
412
+
413
+ def test_migrator_one_down
414
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
415
+
416
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
417
+
418
+ Person.reset_column_information
419
+ assert Person.column_methods_hash.include?(:last_name)
420
+ assert !Reminder.table_exists?
421
+ end
422
+
423
+ def test_migrator_one_up_one_down
424
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
425
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
426
+
427
+ assert !Person.column_methods_hash.include?(:last_name)
428
+ assert !Reminder.table_exists?
429
+ end
430
+
431
+ def test_migrator_verbosity
432
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
433
+ assert PeopleHaveLastNames.message_count > 0
434
+ PeopleHaveLastNames.message_count = 0
435
+
436
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
437
+ assert PeopleHaveLastNames.message_count > 0
438
+ PeopleHaveLastNames.message_count = 0
439
+ end
440
+
441
+ def test_migrator_verbosity_off
442
+ PeopleHaveLastNames.verbose = false
443
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
444
+ assert PeopleHaveLastNames.message_count.zero?
445
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
446
+ assert PeopleHaveLastNames.message_count.zero?
447
+ end
448
+
449
+ def test_migrator_going_down_due_to_version_target
450
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
451
+ ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
452
+
453
+ assert !Person.column_methods_hash.include?(:last_name)
454
+ assert !Reminder.table_exists?
455
+
456
+ ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/')
457
+
458
+ Person.reset_column_information
459
+ assert Person.column_methods_hash.include?(:last_name)
460
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
461
+ assert_equal "hello world", Reminder.find(:first).content
462
+ end
463
+
464
+ def test_schema_info_table_name
465
+ ActiveRecord::Base.table_name_prefix = "prefix_"
466
+ ActiveRecord::Base.table_name_suffix = "_suffix"
467
+ Reminder.reset_table_name
468
+ assert_equal "prefix_schema_info_suffix", ActiveRecord::Migrator.schema_info_table_name
469
+ ActiveRecord::Base.table_name_prefix = ""
470
+ ActiveRecord::Base.table_name_suffix = ""
471
+ Reminder.reset_table_name
472
+ assert_equal "schema_info", ActiveRecord::Migrator.schema_info_table_name
473
+ ensure
474
+ ActiveRecord::Base.table_name_prefix = ""
475
+ ActiveRecord::Base.table_name_suffix = ""
476
+ end
477
+
478
+ def test_proper_table_name
479
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
480
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
481
+ assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
482
+ Reminder.reset_table_name
483
+ assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
484
+
485
+ # Use the model's own prefix/suffix if a model is given
486
+ ActiveRecord::Base.table_name_prefix = "ARprefix_"
487
+ ActiveRecord::Base.table_name_suffix = "_ARsuffix"
488
+ Reminder.table_name_prefix = 'prefix_'
489
+ Reminder.table_name_suffix = '_suffix'
490
+ Reminder.reset_table_name
491
+ assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
492
+ Reminder.table_name_prefix = ''
493
+ Reminder.table_name_suffix = ''
494
+ Reminder.reset_table_name
495
+
496
+ # Use AR::Base's prefix/suffix if string or symbol is given
497
+ ActiveRecord::Base.table_name_prefix = "prefix_"
498
+ ActiveRecord::Base.table_name_suffix = "_suffix"
499
+ Reminder.reset_table_name
500
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
501
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
502
+ ActiveRecord::Base.table_name_prefix = ""
503
+ ActiveRecord::Base.table_name_suffix = ""
504
+ Reminder.reset_table_name
505
+ end
506
+
507
+ def test_add_drop_table_with_prefix_and_suffix
508
+ assert !Reminder.table_exists?
509
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
510
+ ActiveRecord::Base.table_name_suffix = '_suffix'
511
+ Reminder.reset_table_name
512
+ Reminder.reset_sequence_name
513
+ WeNeedReminders.up
514
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
515
+ assert_equal "hello world", Reminder.find(:first).content
516
+
517
+ WeNeedReminders.down
518
+ assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
519
+ ensure
520
+ ActiveRecord::Base.table_name_prefix = ''
521
+ ActiveRecord::Base.table_name_suffix = ''
522
+ Reminder.reset_table_name
523
+ Reminder.reset_sequence_name
524
+ end
525
+
526
+ def test_create_table_with_binary_column
527
+ Person.connection.drop_table :binary_testings rescue nil
528
+
529
+ assert_nothing_raised {
530
+ if current_adapter?(:ODBCAdapter) && [:informix, :ingres].include?(ActiveRecord::Base.connection.dbmsName)
531
+ # Specifying a non-null default generates the following error:
532
+ # Informix:
533
+ # "Cannot specify non-null default value for blob column. (-594)"
534
+ # Ingres:
535
+ # "Cannot create a default on column of type 'long byte'"
536
+ Person.connection.create_table :binary_testings do |t|
537
+ t.column "data", :binary
538
+ end
539
+ else
540
+ Person.connection.create_table :binary_testings do |t|
541
+ t.column "data", :binary, :default => "", :null => false
542
+ end
543
+ end
544
+ }
545
+
546
+ columns = Person.connection.columns(:binary_testings)
547
+ data_column = columns.detect { |c| c.name == "data" }
548
+
549
+ if current_adapter?(:OracleAdapter)
550
+ assert_equal "empty_blob()", data_column.default
551
+ elsif current_adapter?(:ODBCAdapter) && [:informix, :ingres].include?(ActiveRecord::Base.connection.dbmsName)
552
+ assert_nil data_column.default
553
+ else
554
+ assert_equal "", data_column.default
555
+ end
556
+
557
+ Person.connection.drop_table :binary_testings rescue nil
558
+ end
559
+
560
+ def test_migrator_with_duplicates
561
+ assert_raises(ActiveRecord::DuplicateMigrationVersionError) do
562
+ ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil)
563
+ end
564
+ end
565
+ end
566
+ end