aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/migration_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/migration_test.rb')
-rw-r--r--activerecord/test/migration_test.rb153
1 files changed, 135 insertions, 18 deletions
diff --git a/activerecord/test/migration_test.rb b/activerecord/test/migration_test.rb
index 9514eb369d..337d4c8861 100644
--- a/activerecord/test/migration_test.rb
+++ b/activerecord/test/migration_test.rb
@@ -1,10 +1,15 @@
require 'abstract_unit'
+require 'bigdecimal/util'
+
require 'fixtures/person'
require 'fixtures/topic'
require File.dirname(__FILE__) + '/fixtures/migrations/1_people_have_last_names'
require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders'
+require File.dirname(__FILE__) + '/fixtures/migrations_with_decimal/1_give_me_big_numbers'
if ActiveRecord::Base.connection.supports_migrations?
+ class BigNumber < ActiveRecord::Base; end
+
class Reminder < ActiveRecord::Base; end
class ActiveRecord::Migration
@@ -29,20 +34,15 @@ if ActiveRecord::Base.connection.supports_migrations?
ActiveRecord::Base.connection.initialize_schema_information
ActiveRecord::Base.connection.update "UPDATE #{ActiveRecord::Migrator.schema_info_table_name} SET version = 0"
- Reminder.connection.drop_table("reminders") rescue nil
- Reminder.connection.drop_table("people_reminders") rescue nil
- Reminder.connection.drop_table("prefix_reminders_suffix") rescue nil
+ %w(reminders people_reminders prefix_reminders_suffix).each do |table|
+ Reminder.connection.drop_table(table) rescue nil
+ end
Reminder.reset_column_information
- Person.connection.remove_column("people", "last_name") rescue nil
- Person.connection.remove_column("people", "key") rescue nil
- Person.connection.remove_column("people", "bio") rescue nil
- Person.connection.remove_column("people", "age") rescue nil
- Person.connection.remove_column("people", "height") rescue nil
- Person.connection.remove_column("people", "birthday") rescue nil
- Person.connection.remove_column("people", "favorite_day") rescue nil
- Person.connection.remove_column("people", "male") rescue nil
- Person.connection.remove_column("people", "administrator") rescue nil
+ %w(last_name key bio age height wealth birthday favorite_day
+ mail administrator).each do |column|
+ Person.connection.remove_column('people', column) rescue nil
+ end
Person.connection.remove_column("people", "first_name") rescue nil
Person.connection.add_column("people", "first_name", :string, :limit => 40)
Person.reset_column_information
@@ -187,23 +187,74 @@ if ActiveRecord::Base.connection.supports_migrations?
Person.connection.drop_table :testings rescue nil
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
+ # SQLite3 always uses float in violation of SQL
+ # 16 decimal places
+ correct_value = (current_adapter?(:SQLiteAdapter) ? '0.123456789012346E20' : '0012345678901234567890.0123456789').to_d
+
+ Person.delete_all
+ Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
+ Person.reset_column_information
+
+ # Do a manual insertion
+ Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
+
+ # SELECT
+ row = Person.find(:first)
+ assert_kind_of BigDecimal, row.wealth
+
+ # If this assert fails, that means the SELECT is broken!
+ assert_equal correct_value, row.wealth
+
+ # Reset to old state
+ Person.delete_all
+
+ # Now use the Rails insertion
+ assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
+
+ # SELECT
+ row = Person.find(:first)
+ assert_kind_of BigDecimal, row.wealth
+
+ # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
+ assert_equal correct_value, row.wealth
+
+ # Reset to old state
+ Person.connection.del_column "people", "wealth" rescue nil
+ Person.reset_column_information
+ end
+
def test_native_types
Person.delete_all
Person.connection.add_column "people", "last_name", :string
Person.connection.add_column "people", "bio", :text
Person.connection.add_column "people", "age", :integer
Person.connection.add_column "people", "height", :float
+ Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
Person.connection.add_column "people", "birthday", :datetime
Person.connection.add_column "people", "favorite_day", :date
Person.connection.add_column "people", "male", :boolean
- 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 }
+ assert_nothing_raised { Person.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, :male => true }
bob = Person.find(:first)
- assert_equal bob.first_name, 'bob'
- assert_equal bob.last_name, 'bobsen'
- assert_equal bob.bio, "I was born ...."
- assert_equal bob.age, 18
- assert_equal bob.male?, true
+ 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 significent digits (beyond the 16 of float), 10 of them
+ # after the decimal place.
+ if current_adapter?(:SQLiteAdapter)
+ # SQLite3 uses float in violation of SQL. Test for 16 decimal places.
+ assert_equal BigDecimal.new('0.123456789012346E20'), bob.wealth
+ else
+ 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
@@ -219,6 +270,7 @@ if ActiveRecord::Base.connection.supports_migrations?
end
assert_equal TrueClass, bob.male?.class
+ assert_kind_of BigDecimal, bob.wealth
end
def test_add_remove_single_field_using_string_arguments
@@ -351,6 +403,71 @@ if ActiveRecord::Base.connection.supports_migrations?
assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
end
+ def test_add_table_with_decimals
+ Person.connection.drop_table :big_numbers rescue nil
+
+ assert !BigNumber.table_exists?
+ GiveMeBigNumbers.up
+
+ assert BigNumber.create(
+ :bank_balance => 1586.43,
+ :big_bank_balance => BigDecimal("1000234000567.95"),
+ :world_population => 6000000000,
+ :my_house_population => 3,
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
+ )
+
+ b = BigNumber.find(:first)
+ assert_not_nil b
+
+ assert_not_nil b.bank_balance
+ assert_not_nil b.big_bank_balance
+ assert_not_nil b.world_population
+ assert_not_nil b.my_house_population
+ assert_not_nil b.value_of_e
+
+ # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
+ # is_a?(Bignum)
+ assert_kind_of Integer, b.world_population
+ assert_equal 6000000000, b.world_population
+ assert_kind_of Fixnum, b.my_house_population
+ assert_equal 3, b.my_house_population
+ assert_kind_of BigDecimal, b.bank_balance
+ assert_equal BigDecimal("1586.43"), b.bank_balance
+ assert_kind_of BigDecimal, b.big_bank_balance
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
+
+ # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
+ # precision/scale explictly left out. By the SQL standard, numbers
+ # assigned to this field should be truncated but that's seldom respected.
+ if current_adapter?(:PostgreSQLAdapter, :SQLite2Adapter)
+ # - PostgreSQL changes the SQL spec on columns declared simply as
+ # "decimal" to something more useful: instead of being given a scale
+ # of 0, they take on the compile-time limit for precision and scale,
+ # so the following should succeed unless you have used really wacky
+ # compilation options
+ # - SQLite2 has the default behavior of preserving all data sent in,
+ # so this happens there too
+ assert_kind_of BigDecimal, b.value_of_e
+ assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
+ elsif current_adapter?(:SQLiteAdapter)
+ # - SQLite3 stores a float, in violation of SQL
+ assert_kind_of BigDecimal, b.value_of_e
+ assert_equal BigDecimal("2.71828182845905"), b.value_of_e
+ elsif current_adapter?(:SQLServer)
+ # - SQL Server rounds instead of truncating
+ assert_kind_of Fixnum, b.value_of_e
+ assert_equal 3, b.value_of_e
+ else
+ # - SQL standard is an integer
+ assert_kind_of Fixnum, b.value_of_e
+ assert_equal 2, b.value_of_e
+ end
+
+ GiveMeBigNumbers.down
+ assert_raises(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
+ end
+
def test_migrator
assert !Person.column_methods_hash.include?(:last_name)
assert !Reminder.table_exists?