Skip to content
Browse files

Move to the schema-migrations-metadata branch.

Pending work on graceful app upgrades.

Revert "Merge pull request #8439 from joshsusser/fixes"

This reverts commit ce8ac39, reversing
changes made to b0e7b6f.

Revert "Merge pull request #8431 from joshsusser/schemadump"

This reverts commit 036d3e1, reversing
changes made to 0c692f4.

Revert "Merge branch 'joshsusser-master' into merge"

This reverts commit 0c692f4, reversing
changes made to 2e299fc.

Conflicts:
	activerecord/CHANGELOG.md
	activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
	activerecord/test/cases/schema_dumper_test.rb
  • Loading branch information...
1 parent 3c2c1a4 commit cff747d304f008c103a7ba92440400a9a0848bee @jeremy jeremy committed Dec 9, 2012
View
16 activerecord/CHANGELOG.md
@@ -46,22 +46,6 @@
*Chris Feist*
-* Add migration history to `schema.rb` dump. Loading `schema.rb` with full migration
- history restores the exact list of migrations that created that schema (including names
- and fingerprints). This avoids possible mistakes caused by assuming all migrations with
- a lower version have been run when loading `schema.rb`. Old `schema.rb` files without
- migration history but with the `:version` setting still work as before.
-
- *Josh Susser*
-
-* Add metadata columns to `schema_migrations` table. New columns are:
-
- * `migrated_at`: timestamp
- * `fingerprint`: md5 hash of migration source
- * `name`: filename minus version and extension
-
- *Josh Susser*
-
* Fix performance problem with `primary_key` method in PostgreSQL adapter when having many schemas.
Uses `pg_constraint` table instead of `pg_depend` table which has many records in general.
Fix #8414
View
8 activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -490,8 +490,8 @@ def dump_schema_information #:nodoc:
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
ActiveRecord::SchemaMigration.order('version').map { |sm|
- "INSERT INTO #{sm_table} (version, migrated_at, fingerprint, name) VALUES ('#{sm.version}',CURRENT_TIMESTAMP,'#{sm.fingerprint}','#{sm.name}');"
- }.join("\n\n")
+ "INSERT INTO #{sm_table} (version) VALUES ('#{sm.version}');"
+ }.join "\n\n"
end
# Should not be called normally, but this operation is non-destructive.
@@ -512,15 +512,15 @@ def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migra
end
unless migrated.include?(version)
- ActiveRecord::SchemaMigration.create!(:version => version, :migrated_at => Time.now)
+ execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')"
end
inserted = Set.new
(versions - migrated).each do |v|
if inserted.include?(v)
raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict."
elsif v < version
- ActiveRecord::SchemaMigration.create!(:version => v, :migrated_at => Time.now)
+ execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')"
inserted << v
end
end
View
24 activerecord/lib/active_record/migration.rb
@@ -1,6 +1,5 @@
require "active_support/core_ext/class/attribute_accessors"
require 'set'
-require 'digest/md5'
module ActiveRecord
# Exception that can be raised to stop migrations from going backwards.
@@ -555,10 +554,6 @@ def basename
delegate :migrate, :announce, :write, :to => :migration
- def fingerprint
- @fingerprint ||= Digest::MD5.hexdigest(File.read(filename))
- end
-
private
def migration
@@ -729,7 +724,7 @@ def run
raise UnknownMigrationVersionError.new(@target_version) if target.nil?
unless (up? && migrated.include?(target.version.to_i)) || (down? && !migrated.include?(target.version.to_i))
target.migrate(@direction)
- record_version_state_after_migrating(target)
+ record_version_state_after_migrating(target.version)
end
end
@@ -752,7 +747,7 @@ def migrate
begin
ddl_transaction do
migration.migrate(@direction)
- record_version_state_after_migrating(migration)
+ record_version_state_after_migrating(migration.version)
end
rescue => e
canceled_msg = Base.connection.supports_ddl_transactions? ? "this and " : ""
@@ -810,18 +805,13 @@ def validate(migrations)
raise DuplicateMigrationVersionError.new(version) if version
end
- def record_version_state_after_migrating(target)
+ def record_version_state_after_migrating(version)
if down?
- migrated.delete(target.version)
- ActiveRecord::SchemaMigration.where(:version => target.version.to_s).delete_all
+ migrated.delete(version)
+ ActiveRecord::SchemaMigration.where(:version => version.to_s).delete_all
else
- migrated << target.version
- ActiveRecord::SchemaMigration.create!(
- :version => target.version.to_s,
- :migrated_at => Time.now,
- :fingerprint => target.fingerprint,
- :name => File.basename(target.filename,'.rb').gsub(/^\d+_/,'')
- )
+ migrated << version
+ ActiveRecord::SchemaMigration.create!(:version => version.to_s)
end
end
View
40 activerecord/lib/active_record/schema.rb
@@ -39,45 +39,27 @@ def migrations_paths
end
def define(info, &block) # :nodoc:
- @using_deprecated_version_setting = info[:version].present?
- SchemaMigration.drop_table
- initialize_schema_migrations_table
-
instance_eval(&block)
- # handle files from pre-4.0 that used :version option instead of dumping migration table
- assume_migrated_upto_version(info[:version], migrations_paths) if @using_deprecated_version_setting
+ unless info[:version].blank?
+ initialize_schema_migrations_table
+ assume_migrated_upto_version(info[:version], migrations_paths)
+ end
end
# Eval the given block. All methods available to the current connection
# adapter are available within the block, so you can easily use the
# database definition DSL to build up your schema (+create_table+,
# +add_index+, etc.).
- def self.define(info={}, &block)
- new.define(info, &block)
- end
-
- # Create schema migration history. Include migration statements in a block to this method.
- #
- # migrations do
- # migration 20121128235959, "44f1397e3b92442ca7488a029068a5ad", "add_horn_color_to_unicorns"
- # migration 20121129235959, "4a1eb3965d94406b00002b370854eae8", "add_magic_power_to_unicorns"
- # end
- def migrations
- raise(ArgumentError, "Can't set migrations while using :version option") if @using_deprecated_version_setting
- yield
- end
-
- # Add a migration to the ActiveRecord::SchemaMigration table.
#
- # The +version+ argument is an integer.
- # The +fingerprint+ and +name+ arguments are required but may be empty strings.
- # The migration's +migrated_at+ attribute is set to the current time,
- # instead of being set explicitly as an argument to the method.
+ # The +info+ hash is optional, and if given is used to define metadata
+ # about the current schema (currently, only the schema's version):
#
- # migration 20121129235959, "4a1eb3965d94406b00002b370854eae8", "add_magic_power_to_unicorns"
- def migration(version, fingerprint, name)
- SchemaMigration.create!(version: version, migrated_at: Time.now, fingerprint: fingerprint, name: name)
+ # ActiveRecord::Schema.define(version: 20380119000001) do
+ # ...
+ # end
+ def self.define(info={}, &block)
+ new.define(info, &block)
end
end
end
View
21 activerecord/lib/active_record/schema_dumper.rb
@@ -24,7 +24,6 @@ def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT)
def dump(stream)
header(stream)
- migrations(stream)
tables(stream)
trailer(stream)
stream
@@ -39,11 +38,13 @@ def initialize(connection)
end
def header(stream)
+ define_params = @version ? "version: #{@version}" : ""
+
if stream.respond_to?(:external_encoding) && stream.external_encoding
stream.puts "# encoding: #{stream.external_encoding.name}"
end
- header_text = <<HEADER_RUBY
+ stream.puts <<HEADER
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
@@ -56,27 +57,15 @@ def header(stream)
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define do
+ActiveRecord::Schema.define(#{define_params}) do
-HEADER_RUBY
- stream.puts header_text
+HEADER
end
def trailer(stream)
stream.puts "end"
end
- def migrations(stream)
- all_migrations = ActiveRecord::SchemaMigration.all.to_a
- if all_migrations.any?
- stream.puts(" migrations do")
- all_migrations.each do |migration|
- stream.puts(migration.schema_line(" "))
- end
- stream.puts(" end\n\n")
- end
- end
-
def tables(stream)
@connection.tables.sort.each do |tbl|
next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
View
39 activerecord/lib/active_record/schema_migration.rb
@@ -14,56 +14,23 @@ def self.index_name
end
def self.create_table
- if connection.table_exists?(table_name)
- cols = connection.columns(table_name).collect { |col| col.name }
- unless cols.include?("migrated_at")
- connection.add_column(table_name, "migrated_at", :datetime)
- q_table_name = connection.quote_table_name(table_name)
- q_timestamp = connection.quoted_date(Time.now)
- connection.update("UPDATE #{q_table_name} SET migrated_at = '#{q_timestamp}' WHERE migrated_at IS NULL")
- connection.change_column(table_name, "migrated_at", :datetime, :null => false)
- end
- unless cols.include?("fingerprint")
- connection.add_column(table_name, "fingerprint", :string, :limit => 32)
- end
- unless cols.include?("name")
- connection.add_column(table_name, "name", :string)
- end
- else
+ unless connection.table_exists?(table_name)
connection.create_table(table_name, :id => false) do |t|
t.column :version, :string, :null => false
- t.column :migrated_at, :datetime, :null => false
- t.column :fingerprint, :string, :limit => 32
- t.column :name, :string
end
- connection.add_index(table_name, "version", :unique => true, :name => index_name)
+ connection.add_index table_name, :version, :unique => true, :name => index_name
end
- reset_column_information
end
def self.drop_table
if connection.table_exists?(table_name)
- if connection.index_exists?(table_name, "version", :unique => true, :name => index_name)
- connection.remove_index(table_name, :name => index_name)
- end
+ connection.remove_index table_name, :name => index_name
connection.drop_table(table_name)
end
end
def version
super.to_i
end
-
- # Construct ruby source to include in schema.rb dump for this migration.
- # Pass a string of spaces as +indent+ to allow calling code to control how deeply indented the line is.
- # The generated line includes the migration version, fingerprint, and name. Either fingerprint or name
- # can be an empty string.
- #
- # Example output:
- #
- # migration 20121129235959, "ee4be703f9e6e2fc0f4baddebe6eb8f7", "add_magic_power_to_unicorns"
- def schema_line(indent)
- %Q(#{indent}migration %s, "%s", "%s") % [version, fingerprint, name]
- end
end
end
View
51 activerecord/test/cases/ar_schema_test.rb
@@ -46,55 +46,4 @@ def test_schema_subclass
end
end
- class ActiveRecordSchemaMigrationsTest < ActiveRecordSchemaTest
- def setup
- super
- ActiveRecord::SchemaMigration.delete_all
- end
-
- def test_migration_adds_row_to_migrations_table
- schema = ActiveRecord::Schema.new
- schema.migration(1001, "", "")
- schema.migration(1002, "123456789012345678901234567890ab", "add_magic_power_to_unicorns")
-
- migrations = ActiveRecord::SchemaMigration.all.to_a
- assert_equal 2, migrations.length
-
- assert_equal 1001, migrations[0].version
- assert_match %r{^2\d\d\d-}, migrations[0].migrated_at.to_s(:db)
- assert_equal "", migrations[0].fingerprint
- assert_equal "", migrations[0].name
-
- assert_equal 1002, migrations[1].version
- assert_match %r{^2\d\d\d-}, migrations[1].migrated_at.to_s(:db)
- assert_equal "123456789012345678901234567890ab", migrations[1].fingerprint
- assert_equal "add_magic_power_to_unicorns", migrations[1].name
- end
-
- def test_define_clears_schema_migrations
- assert_nothing_raised do
- ActiveRecord::Schema.define do
- migrations do
- migration(123001, "", "")
- end
- end
- ActiveRecord::Schema.define do
- migrations do
- migration(123001, "", "")
- end
- end
- end
- end
-
- def test_define_raises_if_both_version_and_explicit_migrations
- assert_raise(ArgumentError) do
- ActiveRecord::Schema.define(version: 123001) do
- migrations do
- migration(123001, "", "")
- end
- end
- end
- end
- end
-
end
View
2 activerecord/test/cases/migration/logger_test.rb
@@ -10,8 +10,6 @@ class LoggerTest < ActiveRecord::TestCase
def migrate direction
# do nothing
end
- def filename; "anon.rb"; end
- def fingerprint; "123456789012345678901234567890ab"; end
end
def setup
View
24 activerecord/test/cases/migration/table_and_index_test.rb
@@ -0,0 +1,24 @@
+require "cases/helper"
+
+module ActiveRecord
+ class Migration
+ class TableAndIndexTest < ActiveRecord::TestCase
+ def test_add_schema_info_respects_prefix_and_suffix
+ conn = ActiveRecord::Base.connection
+
+ conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
+ # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
+ ActiveRecord::Base.table_name_prefix = 'p_'
+ ActiveRecord::Base.table_name_suffix = '_s'
+ conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
+
+ conn.initialize_schema_migrations_table
+
+ assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
+ ensure
+ ActiveRecord::Base.table_name_prefix = ""
+ ActiveRecord::Base.table_name_suffix = ""
+ end
+ end
+ end
+end
View
11 activerecord/test/cases/migration_test.rb
@@ -59,21 +59,12 @@ def teardown
def test_migrator_versions
migrations_path = MIGRATIONS_ROOT + "/valid"
ActiveRecord::Migrator.migrations_paths = migrations_path
- m0_path = File.join(migrations_path, "1_valid_people_have_last_names.rb")
- m0_fingerprint = Digest::MD5.hexdigest(File.read(m0_path))
ActiveRecord::Migrator.up(migrations_path)
assert_equal 3, ActiveRecord::Migrator.current_version
assert_equal 3, ActiveRecord::Migrator.last_version
assert_equal false, ActiveRecord::Migrator.needs_migration?
- rows = connection.select_all("SELECT * FROM #{connection.quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)}")
- assert_equal m0_fingerprint, rows[0]["fingerprint"]
- assert_equal "valid_people_have_last_names", rows[0]["name"]
- rows.each do |row|
- assert_match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/, row["migrated_at"].to_s, "missing migrated_at") # sometimes a String, sometimes a Time
- end
-
ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
assert_equal 0, ActiveRecord::Migrator.current_version
assert_equal 3, ActiveRecord::Migrator.last_version
@@ -346,7 +337,7 @@ def test_create_table_with_binary_column
assert_nothing_raised {
Person.connection.create_table :binary_testings do |t|
- t.column :data, :binary, :null => false
+ t.column "data", :binary, :null => false
end
}
View
9 activerecord/test/cases/migrator_test.rb
@@ -18,9 +18,6 @@ def initialize name = self.class.name, version = nil
def up; @went_up = true; end
def down; @went_down = true; end
- # also used in place of a MigrationProxy
- def filename; "anon.rb"; end
- def fingerprint; "123456789012345678901234567890ab"; end
end
def setup
@@ -105,7 +102,7 @@ def test_relative_migrations
end
def test_finds_pending_migrations
- ActiveRecord::SchemaMigration.create!(:version => '1', :name => "anon", :migrated_at => Time.now)
+ ActiveRecord::SchemaMigration.create!(:version => '1')
migration_list = [ Migration.new('foo', 1), Migration.new('bar', 3) ]
migrations = ActiveRecord::Migrator.new(:up, migration_list).pending_migrations
@@ -155,7 +152,7 @@ def test_down_calls_down
end
def test_current_version
- ActiveRecord::SchemaMigration.create!(:version => '1000', :name => "anon", :migrated_at => Time.now)
+ ActiveRecord::SchemaMigration.create!(:version => '1000')
assert_equal 1000, ActiveRecord::Migrator.current_version
end
@@ -323,7 +320,7 @@ def test_migrator_forward
def test_only_loads_pending_migrations
# migrate up to 1
- ActiveRecord::SchemaMigration.create!(:version => '1', :name => "anon", :migrated_at => Time.now)
+ ActiveRecord::SchemaMigration.create!(:version => '1')
calls, migrator = migrator_class(3)
migrator.migrate("valid", nil)
View
17 activerecord/test/cases/schema_dumper_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
+
class SchemaDumperTest < ActiveRecord::TestCase
def setup
super
@@ -17,15 +18,11 @@ def standard_dump
def test_dump_schema_information_outputs_lexically_ordered_versions
versions = %w{ 20100101010101 20100201010101 20100301010101 }
versions.reverse.each do |v|
- ActiveRecord::SchemaMigration.create!(
- :version => v, :migrated_at => Time.now,
- :fingerprint => "123456789012345678901234567890ab", :name => "anon")
+ ActiveRecord::SchemaMigration.create!(:version => v)
end
schema_info = ActiveRecord::Base.connection.dump_schema_information
assert_match(/20100201010101.*20100301010101/m, schema_info)
- target_line = %q{INSERT INTO schema_migrations (version, migrated_at, fingerprint, name) VALUES ('20100101010101',CURRENT_TIMESTAMP,'123456789012345678901234567890ab','anon');}
- assert_match target_line, schema_info
end
def test_magic_comment
@@ -39,16 +36,6 @@ def test_schema_dump
assert_no_match %r{create_table "schema_migrations"}, output
end
- def test_schema_dump_includes_migrations
- ActiveRecord::SchemaMigration.delete_all
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/always_safe")
-
- output = standard_dump
- assert_match %r{migrations do}, output, "Missing migrations block"
- assert_match %r{migration 1001, "[0-9a-f]{32}", "always_safe"}, output, "Missing migration line"
- assert_match %r{migration 1002, "[0-9a-f]{32}", "still_safe"}, output, "Missing migration line"
- end
-
def test_schema_dump_excludes_sqlite_sequence
output = standard_dump
assert_no_match %r{create_table "sqlite_sequence"}, output
View
54 activerecord/test/cases/schema_migration_test.rb
@@ -1,54 +0,0 @@
-require "cases/helper"
-
-class SchemaMigrationTest < ActiveRecord::TestCase
- def sm_table_name
- ActiveRecord::SchemaMigration.table_name
- end
-
- def connection
- ActiveRecord::Base.connection
- end
-
- def test_add_schema_info_respects_prefix_and_suffix
- connection.drop_table(sm_table_name) if connection.table_exists?(sm_table_name)
- # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
- ActiveRecord::Base.table_name_prefix = 'p_'
- ActiveRecord::Base.table_name_suffix = '_s'
- connection.drop_table(sm_table_name) if connection.table_exists?(sm_table_name)
-
- ActiveRecord::SchemaMigration.create_table
-
- assert_equal "p_unique_schema_migrations_s", connection.indexes(sm_table_name)[0][:name]
- ensure
- ActiveRecord::Base.table_name_prefix = ""
- ActiveRecord::Base.table_name_suffix = ""
- end
-
- def test_add_metadata_columns_to_exisiting_schema_migrations
- # creates the old table schema from pre-Rails4.0, so we can test adding to it below
- if connection.table_exists?(sm_table_name)
- connection.drop_table(sm_table_name)
- end
- connection.create_table(sm_table_name, :id => false) do |schema_migrations_table|
- schema_migrations_table.column("version", :string, :null => false)
- end
-
- connection.insert "INSERT INTO #{connection.quote_table_name(sm_table_name)} (version) VALUES (100)"
- connection.insert "INSERT INTO #{connection.quote_table_name(sm_table_name)} (version) VALUES (200)"
-
- ActiveRecord::SchemaMigration.create_table
-
- rows = connection.select_all("SELECT * FROM #{connection.quote_table_name(sm_table_name)}")
- assert rows[0].has_key?("migrated_at"), "missing column `migrated_at`"
- assert_match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/, rows[0]["migrated_at"].to_s) # sometimes a String, sometimes a Time
- assert rows[0].has_key?("fingerprint"), "missing column `fingerprint`"
- assert rows[0].has_key?("name"), "missing column `name`"
- end
-
- def test_schema_migrations_columns
- ActiveRecord::SchemaMigration.create_table
-
- columns = connection.columns(sm_table_name).collect(&:name)
- %w[version migrated_at fingerprint name].each { |col| assert columns.include?(col), "missing column `#{col}`" }
- end
-end
View
5 activerecord/test/migrations/always_safe/1001_always_safe.rb
@@ -1,5 +0,0 @@
-class AlwaysSafe < ActiveRecord::Migration
- def change
- # do nothing to avoid side-effect conflicts from running multiple times
- end
-end
View
5 activerecord/test/migrations/always_safe/1002_still_safe.rb
@@ -1,5 +0,0 @@
-class StillSafe < ActiveRecord::Migration
- def change
- # do nothing to avoid side-effect conflicts from running multiple times
- end
-end

0 comments on commit cff747d

Please sign in to comment.
Something went wrong with that request. Please try again.