Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source
Show
Ignore:
Timestamp:
04/09/08 16:20:15 (8 months ago)
Author:
rick
Message:

Add support for interleaving migrations by storing which migrations have run in the new schema_migrations table. Closes #11493 [jordi]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

    r9226 r9244  
    233233      # Should not be called normally, but this operation is non-destructive. 
    234234      # The migrations module handles this automatically. 
    235       def initialize_schema_information(current_version=0) 
    236         begin 
    237           execute "CREATE TABLE #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version #{type_to_sql(:string)})" 
    238           execute "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES(#{current_version})" 
    239         rescue ActiveRecord::StatementInvalid 
    240           # Schema has been initialized, make sure version is a string 
    241           version_column = columns(:schema_info).detect { |c| c.name == "version" } 
    242            
    243           # can't just alter the table, since SQLite can't deal 
    244           unless version_column.type == :string 
    245             version = ActiveRecord::Migrator.current_version 
    246             execute "DROP TABLE #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)}" 
    247             initialize_schema_information(version) 
     235      def initialize_schema_migrations_table 
     236        sm_table = ActiveRecord::Migrator.schema_migrations_table_name 
     237 
     238        unless tables.detect { |t| t == sm_table } 
     239          create_table(sm_table, :id => false) do |schema_migrations_table| 
     240            schema_migrations_table.column :version, :string, :null => false 
    248241          end 
    249         end 
    250       end 
    251  
    252       def dump_schema_information #:nodoc: 
    253         begin 
    254           if (current_schema = ActiveRecord::Migrator.current_version) > 0 
    255             return "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES (#{current_schema})"  
     242          add_index sm_table, :version, :unique => true, 
     243            :name => 'unique_schema_migrations' 
     244 
     245          # Backwards-compatibility: if we find schema_info, assume we've 
     246          # migrated up to that point: 
     247          si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix 
     248 
     249          if tables.detect { |t| t == si_table } 
     250 
     251            old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i 
     252            assume_migrated_upto_version(old_version) 
     253            drop_table(si_table) 
    256254          end 
    257         rescue ActiveRecord::StatementInvalid  
    258           # No Schema Info 
    259         end 
    260       end 
    261  
     255        end 
     256      end 
     257 
     258      def assume_migrated_upto_version(version) 
     259        sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name) 
     260        migrated = select_values("SELECT version FROM #{sm_table}").map(&:to_i) 
     261        versions = Dir['db/migrate/[0-9]*_*.rb'].map do |filename| 
     262          filename.split('/').last.split('_').first.to_i 
     263        end 
     264 
     265        execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" unless migrated.include?(version.to_i) 
     266        (versions - migrated).select { |v| v < version.to_i }.each do |v| 
     267          execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" 
     268        end 
     269      end 
    262270 
    263271      def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: