class Sequel::TimestampMigrator
you to make sure the migrations don’t conflict. Part of the migration extension.
after later migrations.  If you plan to do that, the responsibility is on
have not been applied and apply them, even if earlier migrations are added
Stores filenames of migration files, and can figure out which migrations
The migrator used if any migration file version is greater than 20000101.
def convert_from_schema_info
Convert the schema_info table to the new schema_migrations table format,
def convert_from_schema_info v = db[:schema_info].get(:version) ds = db.from(table) files.each do |path| f = File.basename(path) if migration_version_from_file(f) <= v ds.insert(column=>f) end end end
def default_schema_column
def default_schema_column :filename end
def default_schema_table
def default_schema_table :schema_migrations end
def get_applied_migrations
def get_applied_migrations am = ds.select_order_map(column) missing_migration_files = am - files.map{|f| File.basename(f).downcase} raise(Error, "Applied migration files not in file system: #{missing_migration_files.join(', ')}") if missing_migration_files.length > 0 && !@allow_missing_migration_files am end
def get_migration_files
def get_migration_files files = [] Dir.new(directory).each do |file| next unless MIGRATION_FILE_PATTERN.match(file) files << File.join(directory, file) end files.sort_by{|f| MIGRATION_FILE_PATTERN.match(File.basename(f))[1].to_i} end
def get_migration_tuples
def get_migration_tuples up_mts = [] down_mts = [] files.each do |path| f = File.basename(path) fi = f.downcase if target if migration_version_from_file(f) > target if applied_migrations.include?(fi) down_mts << [load_migration_file(path), f, :down] end elsif !applied_migrations.include?(fi) up_mts << [load_migration_file(path), f, :up] end elsif !applied_migrations.include?(fi) up_mts << [load_migration_file(path), f, :up] end end up_mts + down_mts.reverse end
def initialize(db, directory, opts=OPTS)
def initialize(db, directory, opts=OPTS) super @target = opts[:target] @applied_migrations = get_applied_migrations @migration_tuples = get_migration_tuples end
def is_current?
The timestamp migrator is current if there are no migrations to apply
def is_current? migration_tuples.empty? end
def run
def run migration_tuples.each do |m, f, direction| t = Time.now db.log_info("Begin applying migration #{f}, direction: #{direction}") checked_transaction(m) do m.apply(db, direction) fi = f.downcase direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete end db.log_info("Finished applying migration #{f}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds") end nil end
def schema_dataset
Returns the dataset for the schema_migrations table. If no such table
def schema_dataset c = column ds = db.from(table) if !db.table_exists?(table) begin db.create_table(table){String c, :primary_key=>true} rescue Sequel::DatabaseError => e if db.database_type == :mysql && e.message =~ /max key length/ # Handle case where MySQL is used with utf8mb4 charset default, which # only allows a maximum length of about 190 characters for string # primary keys due to InnoDB limitations. db.create_table(table){String c, :primary_key=>true, :size=>190} else raise e end end if db.table_exists?(:schema_info) and vha = db[:schema_info].all and vha.length == 1 and vha.first.keys == [:version] and vha.first.values.first.is_a?(Integer) convert_from_schema_info end elsif !ds.columns.include?(c) raise(Error, "Migrator table #{table} does not contain column #{c}") end ds end