aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/migration
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/migration')
-rw-r--r--activerecord/test/cases/migration/change_schema_test.rb40
-rw-r--r--activerecord/test/cases/migration/column_attributes_test.rb188
-rw-r--r--activerecord/test/cases/migration/command_recorder_test.rb12
-rw-r--r--activerecord/test/cases/migration/create_join_table_test.rb70
-rw-r--r--activerecord/test/cases/migration/helper.rb64
-rw-r--r--activerecord/test/cases/migration/index_test.rb185
-rw-r--r--activerecord/test/cases/migration/logger_test.rb37
-rw-r--r--activerecord/test/cases/migration/references_index_test.rb99
-rw-r--r--activerecord/test/cases/migration/rename_column_test.rb194
-rw-r--r--activerecord/test/cases/migration/rename_table_test.rb72
10 files changed, 921 insertions, 40 deletions
diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb
index f8eedc712f..f0b1f74bd3 100644
--- a/activerecord/test/cases/migration/change_schema_test.rb
+++ b/activerecord/test/cases/migration/change_schema_test.rb
@@ -17,45 +17,6 @@ module ActiveRecord
ActiveRecord::Base.primary_key_prefix_type = nil
end
- def test_index_exists
- connection.create_table :testings do |t|
- t.column :foo, :string, :limit => 100
- t.column :bar, :string, :limit => 100
- end
- connection.add_index :testings, :foo
-
- assert connection.index_exists?(:testings, :foo)
- assert !connection.index_exists?(:testings, :bar)
- end
-
- def test_index_exists_on_multiple_columns
- connection.create_table :testings do |t|
- t.column :foo, :string, :limit => 100
- t.column :bar, :string, :limit => 100
- end
- connection.add_index :testings, [:foo, :bar]
-
- assert connection.index_exists?(:testings, [:foo, :bar])
- end
-
- def test_unique_index_exists
- connection.create_table :testings do |t|
- t.column :foo, :string, :limit => 100
- end
- connection.add_index :testings, :foo, :unique => true
-
- assert connection.index_exists?(:testings, :foo, :unique => true)
- end
-
- def test_named_index_exists
- connection.create_table :testings do |t|
- t.column :foo, :string, :limit => 100
- end
- connection.add_index :testings, :foo, :name => "custom_index_name"
-
- assert connection.index_exists?(:testings, :foo, :name => "custom_index_name")
- end
-
def test_create_table_without_id
testing_table_with_only_foo_attribute do
assert_equal connection.columns(:testings).size, 1
@@ -212,7 +173,6 @@ module ActiveRecord
skip "not supported on #{connection.class}"
end
-
connection.create_table :testings do |t|
t.column :foo, :string
end
diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb
new file mode 100644
index 0000000000..409a558f5c
--- /dev/null
+++ b/activerecord/test/cases/migration/column_attributes_test.rb
@@ -0,0 +1,188 @@
+require "cases/migration/helper"
+
+module ActiveRecord
+ class Migration
+ class ColumnAttributesTest < ActiveRecord::TestCase
+ include ActiveRecord::Migration::TestHelper
+
+ self.use_transactional_fixtures = false
+
+ def test_add_remove_single_field_using_string_arguments
+ refute TestModel.column_methods_hash.key?(:last_name)
+
+ add_column 'test_models', 'last_name', :string
+
+ TestModel.reset_column_information
+
+ assert TestModel.column_methods_hash.key?(:last_name)
+
+ remove_column 'test_models', 'last_name'
+
+ TestModel.reset_column_information
+ refute TestModel.column_methods_hash.key?(:last_name)
+ end
+
+ def test_add_remove_single_field_using_symbol_arguments
+ refute TestModel.column_methods_hash.key?(:last_name)
+
+ add_column :test_models, :last_name, :string
+
+ TestModel.reset_column_information
+ assert TestModel.column_methods_hash.key?(:last_name)
+
+ remove_column :test_models, :last_name
+
+ TestModel.reset_column_information
+ refute TestModel.column_methods_hash.key?(:last_name)
+ end
+
+ def test_unabstracted_database_dependent_types
+ skip "not supported" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
+
+ add_column :test_models, :intelligence_quotient, :tinyint
+ TestModel.reset_column_information
+ assert_match(/tinyint/, TestModel.columns_hash['intelligence_quotient'].sql_type)
+ end
+
+ # We specifically do a manual INSERT here, and then test only the SELECT
+ # functionality. This allows us to more easily catch INSERT being broken,
+ # but SELECT actually working fine.
+ def test_native_decimal_insert_manual_vs_automatic
+ correct_value = '0012345678901234567890.0123456789'.to_d
+
+ connection.add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10'
+
+ # Do a manual insertion
+ if current_adapter?(:OracleAdapter)
+ connection.execute "insert into test_models (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)"
+ elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
+ connection.execute "insert into test_models (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)"
+ elsif current_adapter?(:PostgreSQLAdapter)
+ connection.execute "insert into test_models (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())"
+ else
+ connection.execute "insert into test_models (wealth, created_at, updated_at) values (12345678901234567890.0123456789, 0, 0)"
+ end
+
+ # SELECT
+ row = TestModel.first
+ assert_kind_of BigDecimal, row.wealth
+
+ # If this assert fails, that means the SELECT is broken!
+ unless current_adapter?(:SQLite3Adapter)
+ assert_equal correct_value, row.wealth
+ end
+
+ # Reset to old state
+ TestModel.delete_all
+
+ # Now use the Rails insertion
+ TestModel.create :wealth => BigDecimal.new("12345678901234567890.0123456789")
+
+ # SELECT
+ row = TestModel.first
+ assert_kind_of BigDecimal, row.wealth
+
+ # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
+ unless current_adapter?(:SQLite3Adapter)
+ assert_equal correct_value, row.wealth
+ end
+ end
+
+ def test_add_column_with_precision_and_scale
+ connection.add_column 'test_models', 'wealth', :decimal, :precision => 9, :scale => 7
+
+ wealth_column = TestModel.columns_hash['wealth']
+ assert_equal 9, wealth_column.precision
+ assert_equal 7, wealth_column.scale
+ end
+
+ def test_change_column_preserve_other_column_precision_and_scale
+ skip "only on sqlite3" unless current_adapter?(:SQLite3Adapter)
+
+ connection.add_column 'test_models', 'last_name', :string
+ connection.add_column 'test_models', 'wealth', :decimal, :precision => 9, :scale => 7
+
+ wealth_column = TestModel.columns_hash['wealth']
+ assert_equal 9, wealth_column.precision
+ assert_equal 7, wealth_column.scale
+
+ connection.change_column 'test_models', 'last_name', :string, :null => false
+ TestModel.reset_column_information
+
+ wealth_column = TestModel.columns_hash['wealth']
+ assert_equal 9, wealth_column.precision
+ assert_equal 7, wealth_column.scale
+ end
+
+ def test_native_types
+ add_column "test_models", "first_name", :string
+ add_column "test_models", "last_name", :string
+ add_column "test_models", "bio", :text
+ add_column "test_models", "age", :integer
+ add_column "test_models", "height", :float
+ add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10'
+ add_column "test_models", "birthday", :datetime
+ add_column "test_models", "favorite_day", :date
+ add_column "test_models", "moment_of_truth", :datetime
+ add_column "test_models", "male", :boolean
+
+ TestModel.create :first_name => 'bob', :last_name => 'bobsen',
+ :bio => "I was born ....", :age => 18, :height => 1.78,
+ :wealth => BigDecimal.new("12345678901234567890.0123456789"),
+ :birthday => 18.years.ago, :favorite_day => 10.days.ago,
+ :moment_of_truth => "1782-10-10 21:40:18", :male => true
+
+ bob = TestModel.first
+ assert_equal 'bob', bob.first_name
+ assert_equal 'bobsen', bob.last_name
+ assert_equal "I was born ....", bob.bio
+ assert_equal 18, bob.age
+
+ # Test for 30 significant digits (beyond the 16 of float), 10 of them
+ # after the decimal place.
+
+ unless current_adapter?(:SQLite3Adapter)
+ assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
+ end
+
+ assert_equal true, bob.male?
+
+ assert_equal String, bob.first_name.class
+ assert_equal String, bob.last_name.class
+ assert_equal String, bob.bio.class
+ assert_equal Fixnum, bob.age.class
+ assert_equal Time, bob.birthday.class
+
+ if current_adapter?(:OracleAdapter, :SybaseAdapter)
+ # Sybase, and Oracle don't differentiate between date/time
+ assert_equal Time, bob.favorite_day.class
+ else
+ assert_equal Date, bob.favorite_day.class
+ end
+
+ # Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column
+ # therefore no timezone change is done afterwards when default timezone is changed
+ unless current_adapter?(:OracleAdapter)
+ # Test DateTime column and defaults, including timezone.
+ # FIXME: moment of truth may be Time on 64-bit platforms.
+ if bob.moment_of_truth.is_a?(DateTime)
+
+ with_env_tz 'US/Eastern' do
+ bob.reload
+ assert_equal DateTime.local_offset, bob.moment_of_truth.offset
+ assert_not_equal 0, bob.moment_of_truth.offset
+ assert_not_equal "Z", bob.moment_of_truth.zone
+ # US/Eastern is -5 hours from GMT
+ assert_equal Rational(-5, 24), bob.moment_of_truth.offset
+ assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM
+ assert_equal DateTime::ITALY, bob.moment_of_truth.start
+ end
+ end
+ end
+
+ assert_instance_of TrueClass, bob.male?
+ assert_kind_of BigDecimal, bob.wealth
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb
index 8f136bce2b..7d026961be 100644
--- a/activerecord/test/cases/migration/command_recorder_test.rb
+++ b/activerecord/test/cases/migration/command_recorder_test.rb
@@ -73,6 +73,18 @@ module ActiveRecord
assert_equal [:drop_table, [:people_reminders]], drop_table
end
+ def test_invert_create_join_table
+ @recorder.record :create_join_table, [:musics, :artists]
+ drop_table = @recorder.inverse.first
+ assert_equal [:drop_table, [:artists_musics]], drop_table
+ end
+
+ def test_invert_create_join_table_with_table_name
+ @recorder.record :create_join_table, [:musics, :artists, {:table_name => :catalog}]
+ drop_table = @recorder.inverse.first
+ assert_equal [:drop_table, [:catalog]], drop_table
+ end
+
def test_invert_rename_table
@recorder.record :rename_table, [:old, :new]
rename = @recorder.inverse.first
diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb
new file mode 100644
index 0000000000..0428d9ba76
--- /dev/null
+++ b/activerecord/test/cases/migration/create_join_table_test.rb
@@ -0,0 +1,70 @@
+require 'cases/helper'
+
+module ActiveRecord
+ class Migration
+ class CreateJoinTableTest < ActiveRecord::TestCase
+ attr_reader :connection
+
+ def setup
+ super
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def test_create_join_table
+ connection.create_join_table :artists, :musics
+
+ assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort
+ ensure
+ connection.drop_table :artists_musics
+ end
+
+ def test_create_join_table_set_not_null_by_default
+ connection.create_join_table :artists, :musics
+
+ assert_equal [false, false], connection.columns(:artists_musics).map(&:null)
+ ensure
+ connection.drop_table :artists_musics
+ end
+
+ def test_create_join_table_with_strings
+ connection.create_join_table 'artists', 'musics'
+
+ assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort
+ ensure
+ connection.drop_table :artists_musics
+ end
+
+ def test_create_join_table_with_the_proper_order
+ connection.create_join_table :videos, :musics
+
+ assert_equal %w(music_id video_id), connection.columns(:musics_videos).map(&:name).sort
+ ensure
+ connection.drop_table :musics_videos
+ end
+
+ def test_create_join_table_with_the_table_name
+ connection.create_join_table :artists, :musics, :table_name => :catalog
+
+ assert_equal %w(artist_id music_id), connection.columns(:catalog).map(&:name).sort
+ ensure
+ connection.drop_table :catalog
+ end
+
+ def test_create_join_table_with_the_table_name_as_string
+ connection.create_join_table :artists, :musics, :table_name => 'catalog'
+
+ assert_equal %w(artist_id music_id), connection.columns(:catalog).map(&:name).sort
+ ensure
+ connection.drop_table :catalog
+ end
+
+ def test_create_join_table_with_column_options
+ connection.create_join_table :artists, :musics, :column_options => {:null => true}
+
+ assert_equal [true, true], connection.columns(:artists_musics).map(&:null)
+ ensure
+ connection.drop_table :artists_musics
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/migration/helper.rb b/activerecord/test/cases/migration/helper.rb
new file mode 100644
index 0000000000..fe53510ba2
--- /dev/null
+++ b/activerecord/test/cases/migration/helper.rb
@@ -0,0 +1,64 @@
+require "cases/helper"
+
+module ActiveRecord
+ class Migration
+ class << self
+ attr_accessor :message_count
+ end
+
+ def puts(text="")
+ ActiveRecord::Migration.message_count ||= 0
+ ActiveRecord::Migration.message_count += 1
+ end
+
+ module TestHelper
+ attr_reader :connection, :table_name
+
+ class TestModel < ActiveRecord::Base
+ self.table_name = 'test_models'
+ end
+
+ def setup
+ super
+ @connection = ActiveRecord::Base.connection
+ connection.create_table :test_models do |t|
+ t.timestamps
+ end
+
+ TestModel.reset_column_information
+ end
+
+ def teardown
+ super
+ TestModel.reset_table_name
+ TestModel.reset_sequence_name
+ connection.drop_table :test_models rescue nil
+ end
+
+ private
+ def add_column(*args)
+ connection.add_column(*args)
+ end
+
+ def remove_column(*args)
+ connection.remove_column(*args)
+ end
+
+ def rename_column(*args)
+ connection.rename_column(*args)
+ end
+
+ def add_index(*args)
+ connection.add_index(*args)
+ end
+
+ def change_column(*args)
+ connection.change_column(*args)
+ end
+
+ def rename_table(*args)
+ connection.rename_table(*args)
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb
new file mode 100644
index 0000000000..dd9492924c
--- /dev/null
+++ b/activerecord/test/cases/migration/index_test.rb
@@ -0,0 +1,185 @@
+require 'cases/helper'
+
+module ActiveRecord
+ class Migration
+ class IndexTest < ActiveRecord::TestCase
+ attr_reader :connection, :table_name
+
+ def setup
+ super
+ @connection = ActiveRecord::Base.connection
+ @table_name = :testings
+
+ connection.create_table table_name do |t|
+ t.column :foo, :string, :limit => 100
+ t.column :bar, :string, :limit => 100
+
+ t.string :first_name
+ t.string :last_name, :limit => 100
+ t.string :key, :limit => 100
+ t.boolean :administrator
+ end
+ end
+
+ def teardown
+ super
+ connection.drop_table :testings rescue nil
+ ActiveRecord::Base.primary_key_prefix_type = nil
+ end
+
+ def test_rename_index
+ skip "not supported on openbase" if current_adapter?(:OpenBaseAdapter)
+
+ # keep the names short to make Oracle and similar behave
+ connection.add_index(table_name, [:foo], :name => 'old_idx')
+ connection.rename_index(table_name, 'old_idx', 'new_idx')
+
+ # if the adapter doesn't support the indexes call, pick defaults that let the test pass
+ refute connection.index_name_exists?(table_name, 'old_idx', false)
+ assert connection.index_name_exists?(table_name, 'new_idx', true)
+ end
+
+ def test_double_add_index
+ skip "not supported on openbase" if current_adapter?(:OpenBaseAdapter)
+
+ connection.add_index(table_name, [:foo], :name => 'some_idx')
+ assert_raises(ArgumentError) {
+ connection.add_index(table_name, [:foo], :name => 'some_idx')
+ }
+ end
+
+ def test_remove_nonexistent_index
+ skip "not supported on openbase" if current_adapter?(:OpenBaseAdapter)
+
+ # we do this by name, so OpenBase is a wash as noted above
+ assert_raise(ArgumentError) { connection.remove_index(table_name, "no_such_index") }
+ end
+
+ def test_add_index_name_length_limit
+ good_index_name = 'x' * connection.index_name_length
+ too_long_index_name = good_index_name + 'x'
+
+ assert_raises(ArgumentError) {
+ connection.add_index(table_name, "foo", :name => too_long_index_name)
+ }
+
+ refute connection.index_name_exists?(table_name, too_long_index_name, false)
+ connection.add_index(table_name, "foo", :name => good_index_name)
+
+ assert connection.index_name_exists?(table_name, good_index_name, false)
+ connection.remove_index(table_name, :name => good_index_name)
+ end
+
+ def test_index_symbol_names
+ connection.add_index table_name, :foo, :name => :symbol_index_name
+ assert connection.index_exists?(table_name, :foo, :name => :symbol_index_name)
+
+ connection.remove_index table_name, :name => :symbol_index_name
+ refute connection.index_exists?(table_name, :foo, :name => :symbol_index_name)
+ end
+
+ def test_index_exists
+ connection.add_index :testings, :foo
+
+ assert connection.index_exists?(:testings, :foo)
+ assert !connection.index_exists?(:testings, :bar)
+ end
+
+ def test_index_exists_on_multiple_columns
+ connection.add_index :testings, [:foo, :bar]
+
+ assert connection.index_exists?(:testings, [:foo, :bar])
+ end
+
+ def test_unique_index_exists
+ connection.add_index :testings, :foo, :unique => true
+
+ assert connection.index_exists?(:testings, :foo, :unique => true)
+ end
+
+ def test_named_index_exists
+ connection.add_index :testings, :foo, :name => "custom_index_name"
+
+ assert connection.index_exists?(:testings, :foo, :name => "custom_index_name")
+ end
+
+ def test_add_index_attribute_length_limit
+ connection.add_index :testings, [:foo, :bar], :length => {:foo => 10, :bar => nil}
+
+ assert connection.index_exists?(:testings, [:foo, :bar])
+ end
+
+ def test_add_index
+ connection.add_index("testings", "last_name")
+ connection.remove_index("testings", "last_name")
+
+ # Orcl nds shrt indx nms. Sybs 2.
+ # OpenBase does not have named indexes. You must specify a single column name
+ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
+ connection.add_index("testings", ["last_name", "first_name"])
+ connection.remove_index("testings", :column => ["last_name", "first_name"])
+
+ # Oracle adapter cannot have specified index name larger than 30 characters
+ # Oracle adapter is shortening index name when just column list is given
+ unless current_adapter?(:OracleAdapter)
+ connection.add_index("testings", ["last_name", "first_name"])
+ connection.remove_index("testings", :name => :index_testings_on_last_name_and_first_name)
+ connection.add_index("testings", ["last_name", "first_name"])
+ connection.remove_index("testings", "last_name_and_first_name")
+ end
+ connection.add_index("testings", ["last_name", "first_name"])
+ connection.remove_index("testings", ["last_name", "first_name"])
+
+ connection.add_index("testings", ["last_name"], :length => 10)
+ connection.remove_index("testings", "last_name")
+
+ connection.add_index("testings", ["last_name"], :length => {:last_name => 10})
+ connection.remove_index("testings", ["last_name"])
+
+ connection.add_index("testings", ["last_name", "first_name"], :length => 10)
+ connection.remove_index("testings", ["last_name", "first_name"])
+
+ connection.add_index("testings", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20})
+ connection.remove_index("testings", ["last_name", "first_name"])
+ end
+
+ # quoting
+ # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
+ # OpenBase does not have named indexes. You must specify a single column name
+ unless current_adapter?(:OpenBaseAdapter)
+ connection.add_index("testings", ["key"], :name => "key_idx", :unique => true)
+ connection.remove_index("testings", :name => "key_idx", :unique => true)
+ end
+
+ # Sybase adapter does not support indexes on :boolean columns
+ # OpenBase does not have named indexes. You must specify a single column
+ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
+ connection.add_index("testings", %w(last_name first_name administrator), :name => "named_admin")
+ connection.remove_index("testings", :name => "named_admin")
+ end
+
+ # Selected adapters support index sort order
+ if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
+ connection.add_index("testings", ["last_name"], :order => {:last_name => :desc})
+ connection.remove_index("testings", ["last_name"])
+ connection.add_index("testings", ["last_name", "first_name"], :order => {:last_name => :desc})
+ connection.remove_index("testings", ["last_name", "first_name"])
+ connection.add_index("testings", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc})
+ connection.remove_index("testings", ["last_name", "first_name"])
+ connection.add_index("testings", ["last_name", "first_name"], :order => :desc)
+ connection.remove_index("testings", ["last_name", "first_name"])
+ end
+ end
+
+ def test_add_partial_index
+ skip 'only on pg' unless current_adapter?(:PostgreSQLAdapter)
+
+ connection.add_index("testings", "last_name", :where => "first_name = 'john doe'")
+ assert connection.index_exists?("testings", "last_name")
+
+ connection.remove_index("testings", "last_name")
+ assert !connection.index_exists?("testings", "last_name")
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/migration/logger_test.rb b/activerecord/test/cases/migration/logger_test.rb
new file mode 100644
index 0000000000..ee0c20747e
--- /dev/null
+++ b/activerecord/test/cases/migration/logger_test.rb
@@ -0,0 +1,37 @@
+require "cases/helper"
+
+module ActiveRecord
+ class Migration
+ class LoggerTest < ActiveRecord::TestCase
+ # mysql can't roll back ddl changes
+ self.use_transactional_fixtures = false
+
+ Migration = Struct.new(:name, :version) do
+ def migrate direction
+ # do nothing
+ end
+ end
+
+ def setup
+ super
+ ActiveRecord::SchemaMigration.create_table
+ ActiveRecord::SchemaMigration.delete_all
+ end
+
+ def teardown
+ super
+ ActiveRecord::SchemaMigration.drop_table
+ end
+
+ def test_migration_should_be_run_without_logger
+ previous_logger = ActiveRecord::Base.logger
+ ActiveRecord::Base.logger = nil
+ migrations = [Migration.new('a', 1), Migration.new('b', 2), Migration.new('c', 3)]
+ ActiveRecord::Migrator.new(:up, migrations).migrate
+ ensure
+ ActiveRecord::Base.logger = previous_logger
+ end
+ end
+ end
+end
+
diff --git a/activerecord/test/cases/migration/references_index_test.rb b/activerecord/test/cases/migration/references_index_test.rb
new file mode 100644
index 0000000000..8ab1c59724
--- /dev/null
+++ b/activerecord/test/cases/migration/references_index_test.rb
@@ -0,0 +1,99 @@
+require 'cases/helper'
+
+module ActiveRecord
+ class Migration
+ class ReferencesIndexTest < ActiveRecord::TestCase
+ attr_reader :connection, :table_name
+
+ def setup
+ super
+ @connection = ActiveRecord::Base.connection
+ @table_name = :testings
+ end
+
+ def teardown
+ super
+ connection.drop_table :testings rescue nil
+ end
+
+ def test_creates_index
+ connection.create_table table_name do |t|
+ t.references :foo, :index => true
+ end
+
+ assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ end
+
+ def test_does_not_create_index
+ connection.create_table table_name do |t|
+ t.references :foo
+ end
+
+ refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ end
+
+ def test_does_not_create_index_explicit
+ connection.create_table table_name do |t|
+ t.references :foo, :index => false
+ end
+
+ refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ end
+
+ def test_creates_index_with_options
+ connection.create_table table_name do |t|
+ t.references :foo, :index => {:name => :index_testings_on_yo_momma}
+ t.references :bar, :index => {:unique => true}
+ end
+
+ assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_yo_momma)
+ assert connection.index_exists?(table_name, :bar_id, :name => :index_testings_on_bar_id, :unique => true)
+ end
+
+ def test_creates_polymorphic_index
+ connection.create_table table_name do |t|
+ t.references :foo, :polymorphic => true, :index => true
+ end
+
+ assert connection.index_exists?(table_name, [:foo_id, :foo_type], :name => :index_testings_on_foo_id_and_foo_type)
+ end
+
+ def test_creates_index_for_existing_table
+ connection.create_table table_name
+ connection.change_table table_name do |t|
+ t.references :foo, :index => true
+ end
+
+ assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ end
+
+ def test_does_not_create_index_for_existing_table
+ connection.create_table table_name
+ connection.change_table table_name do |t|
+ t.references :foo
+ end
+
+ refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ end
+
+ def test_does_not_create_index_for_existing_table_explicit
+ connection.create_table table_name
+ connection.change_table table_name do |t|
+ t.references :foo, :index => false
+ end
+
+ refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ end
+
+ def test_creates_polymorphic_index_for_existing_table
+ connection.create_table table_name
+ connection.change_table table_name do |t|
+ t.references :foo, :polymorphic => true, :index => true
+ end
+
+ assert connection.index_exists?(table_name, [:foo_id, :foo_type], :name => :index_testings_on_foo_id_and_foo_type)
+ end
+
+ end
+ end
+end
diff --git a/activerecord/test/cases/migration/rename_column_test.rb b/activerecord/test/cases/migration/rename_column_test.rb
new file mode 100644
index 0000000000..d1a85ee5e4
--- /dev/null
+++ b/activerecord/test/cases/migration/rename_column_test.rb
@@ -0,0 +1,194 @@
+require "cases/migration/helper"
+
+module ActiveRecord
+ class Migration
+ class RenameColumnTest < ActiveRecord::TestCase
+ include ActiveRecord::Migration::TestHelper
+
+ self.use_transactional_fixtures = false
+
+ # FIXME: this is more of an integration test with AR::Base and the
+ # schema modifications. Maybe we should move this?
+ def test_add_rename
+ add_column "test_models", "girlfriend", :string
+ TestModel.reset_column_information
+
+ TestModel.create :girlfriend => 'bobette'
+
+ rename_column "test_models", "girlfriend", "exgirlfriend"
+
+ TestModel.reset_column_information
+ bob = TestModel.first
+
+ assert_equal "bobette", bob.exgirlfriend
+ end
+
+ # FIXME: another integration test. We should decouple this from the
+ # AR::Base implementation.
+ def test_rename_column_using_symbol_arguments
+ add_column :test_models, :first_name, :string
+
+ TestModel.create :first_name => 'foo'
+
+ rename_column :test_models, :first_name, :nick_name
+ TestModel.reset_column_information
+ assert TestModel.column_names.include?("nick_name")
+ assert_equal ['foo'], TestModel.all.map(&:nick_name)
+ end
+
+ # FIXME: another integration test. We should decouple this from the
+ # AR::Base implementation.
+ def test_rename_column
+ add_column "test_models", "first_name", "string"
+
+ TestModel.create :first_name => 'foo'
+
+ rename_column "test_models", "first_name", "nick_name"
+ TestModel.reset_column_information
+ assert TestModel.column_names.include?("nick_name")
+ assert_equal ['foo'], TestModel.all.map(&:nick_name)
+ end
+
+ def test_rename_column_preserves_default_value_not_null
+ add_column 'test_models', 'salary', :integer, :default => 70000
+
+ default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
+ assert_equal 70000, default_before
+
+ rename_column "test_models", "salary", "anual_salary"
+
+ assert TestModel.column_names.include?("anual_salary")
+ default_after = connection.columns("test_models").find { |c| c.name == "anual_salary" }.default
+ assert_equal 70000, default_after
+ end
+
+ def test_rename_nonexistent_column
+ exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
+ ActiveRecord::StatementInvalid
+ else
+ ActiveRecord::ActiveRecordError
+ end
+ assert_raise(exception) do
+ rename_column "test_models", "nonexistent", "should_fail"
+ end
+ end
+
+ def test_rename_column_with_sql_reserved_word
+ add_column 'test_models', 'first_name', :string
+ rename_column "test_models", "first_name", "group"
+
+ assert TestModel.column_names.include?("group")
+ end
+
+ def test_rename_column_with_an_index
+ add_column "test_models", :hat_name, :string
+ add_index :test_models, :hat_name
+
+ # FIXME: we should test that the index goes away
+ rename_column "test_models", "hat_name", "name"
+ end
+
+ def test_remove_column_with_index
+ add_column "test_models", :hat_name, :string
+ add_index :test_models, :hat_name
+
+ # FIXME: we should test that the index goes away
+ remove_column("test_models", "hat_name")
+ end
+
+ def test_remove_column_with_multi_column_index
+ add_column "test_models", :hat_size, :integer
+ add_column "test_models", :hat_style, :string, :limit => 100
+ add_index "test_models", ["hat_style", "hat_size"], :unique => true
+
+ # FIXME: we should test that the index goes away
+ remove_column("test_models", "hat_size")
+ end
+
+ # FIXME: we need to test that these calls do something
+ def test_change_type_of_not_null_column
+ change_column "test_models", "updated_at", :datetime, :null => false
+ change_column "test_models", "updated_at", :datetime, :null => false
+ change_column "test_models", "updated_at", :datetime, :null => true
+ end
+
+ def test_change_column_nullability
+ add_column "test_models", "funny", :boolean
+ assert TestModel.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
+
+ change_column "test_models", "funny", :boolean, :null => false, :default => true
+
+ TestModel.reset_column_information
+ refute TestModel.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
+
+ change_column "test_models", "funny", :boolean, :null => true
+ TestModel.reset_column_information
+ assert TestModel.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
+ end
+
+ def test_change_column
+ add_column 'test_models', 'age', :integer
+ add_column 'test_models', 'approved', :boolean, :default => true
+
+ old_columns = connection.columns(TestModel.table_name)
+
+ assert old_columns.find { |c| c.name == 'age' && c.type == :integer }
+
+ change_column "test_models", "age", :string
+
+ new_columns = connection.columns(TestModel.table_name)
+
+ refute new_columns.find { |c| c.name == 'age' and c.type == :integer }
+ assert new_columns.find { |c| c.name == 'age' and c.type == :string }
+
+ old_columns = connection.columns(TestModel.table_name)
+ assert old_columns.find { |c|
+ c.name == 'approved' && c.type == :boolean && c.default == true
+ }
+
+ change_column :test_models, :approved, :boolean, :default => false
+ new_columns = connection.columns(TestModel.table_name)
+
+ refute new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
+ assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
+ change_column :test_models, :approved, :boolean, :default => true
+ end
+
+ def test_change_column_with_nil_default
+ add_column "test_models", "contributor", :boolean, :default => true
+ assert TestModel.new.contributor?
+
+ change_column "test_models", "contributor", :boolean, :default => nil
+ TestModel.reset_column_information
+ refute TestModel.new.contributor?
+ assert_nil TestModel.new.contributor
+ end
+
+ def test_change_column_with_new_default
+ add_column "test_models", "administrator", :boolean, :default => true
+ assert TestModel.new.administrator?
+
+ change_column "test_models", "administrator", :boolean, :default => false
+ TestModel.reset_column_information
+ refute TestModel.new.administrator?
+ end
+
+ def test_change_column_default
+ add_column "test_models", "first_name", :string
+ connection.change_column_default "test_models", "first_name", "Tester"
+
+ assert_equal "Tester", TestModel.new.first_name
+ end
+
+ def test_change_column_default_to_null
+ add_column "test_models", "first_name", :string
+ connection.change_column_default "test_models", "first_name", nil
+ assert_nil TestModel.new.first_name
+ end
+
+ def test_remove_column_no_second_parameter_raises_exception
+ assert_raise(ArgumentError) { connection.remove_column("funny") }
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb
new file mode 100644
index 0000000000..d5ff2c607f
--- /dev/null
+++ b/activerecord/test/cases/migration/rename_table_test.rb
@@ -0,0 +1,72 @@
+require "cases/migration/helper"
+
+module ActiveRecord
+ class Migration
+ class RenameTableTest < ActiveRecord::TestCase
+ include ActiveRecord::Migration::TestHelper
+
+ self.use_transactional_fixtures = false
+
+ def setup
+ super
+ add_column 'test_models', :url, :string
+ remove_column 'test_models', :created_at
+ remove_column 'test_models', :updated_at
+ end
+
+ def test_rename_table_for_sqlite_should_work_with_reserved_words
+ renamed = false
+
+ skip "not supported" unless current_adapter?(:SQLite3Adapter)
+
+ add_column :test_models, :url, :string
+ connection.rename_table :references, :old_references
+ connection.rename_table :test_models, :references
+
+ renamed = true
+
+ # Using explicit id in insert for compatibility across all databases
+ con = connection
+ con.execute "INSERT INTO 'references' (url, created_at, updated_at) VALUES ('http://rubyonrails.com', 0, 0)"
+ assert_equal 'http://rubyonrails.com', connection.select_value("SELECT url FROM 'references' WHERE id=1")
+ ensure
+ return unless renamed
+ connection.rename_table :references, :test_models
+ connection.rename_table :old_references, :references
+ end
+
+ def test_rename_table
+ rename_table :test_models, :octopi
+
+ # Using explicit id in insert for compatibility across all databases
+ con = connection
+ con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
+
+ con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
+
+ con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
+
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
+
+ rename_table :octopi, :test_models
+ end
+
+ def test_rename_table_with_an_index
+ add_index :test_models, :url
+
+ rename_table :test_models, :octopi
+
+ # Using explicit id in insert for compatibility across all databases
+ con = ActiveRecord::Base.connection
+ con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
+ con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
+ con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
+
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1")
+ assert connection.indexes(:octopi).first.columns.include?("url")
+
+ rename_table :octopi, :test_models
+ end
+ end
+ end
+end