odbc-rails 1.2

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.
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