diff --git a/application/config/migration.php b/application/config/migration.php index 667f4bc7..e6f9d5b5 100644 --- a/application/config/migration.php +++ b/application/config/migration.php @@ -21,10 +21,11 @@ | be upgraded / downgraded to. | */ -$config['migration_version'] = 20140228091723; +// Format for migration_type = unmark: (YYYYMMDDXX format where XX is an incremented sequence of changes in selected day) +$config['migration_version'] = 2014022801; // Set migration type to timestamp to avoid conflicts -$config['migration_type'] = 'timestamp'; +$config['migration_type'] = 'unmark'; /* @@ -39,6 +40,16 @@ */ $config['migration_path'] = APPPATH . 'migrations/'; +/* + * Due to switch from timestamp to unmark numbering (to support 32-bit systems), we need to add mappings + * for already created migration files, to port on 64-bit systems properly + * If you've created custom migrations, please add entries to this config in form of + * old number (timestamp) => new number (YYYYMMDDXX format where XX is an incremented sequence of changes in selected day) + */ +$config['migration_mappings'] = array( + '20140228091723' => '2014022801', +); + /* End of file migration.php */ /* Location: ./application/config/migration.php */ \ No newline at end of file diff --git a/application/libraries/Plain_Migration.php b/application/libraries/Plain_Migration.php index e04c7bf7..bd321d86 100644 --- a/application/libraries/Plain_Migration.php +++ b/application/libraries/Plain_Migration.php @@ -21,11 +21,87 @@ public function __construct($config = array()) // Set the latest release if (! empty($config)) { $config['migration_version'] = (isset($custom_config['migration_version']) && $custom_config['migration_version'] > $config['migration_version']) ? $custom_config['migration_version'] : $config['migration_version']; + if(empty($config['migration_mappings'])){ + $config['migration_mappings'] = array(); + } + if(!empty($custom_config['migration_mappings'])){ + $config['migration_mappings'] = $config['migration_mappings'] + $custom_config['migration_mappings']; + } } - // Call home + // Overriden parent constructor to support YYYYMMDDXX format where XX is sequential number in day + if (get_parent_class($this) !== FALSE && get_class($this) !== config_item('subclass_prefix').'Migration' ) + { + return; + } + + foreach ($config as $key => $val) + { + $this->{'_'.$key} = $val; + } + + log_message('debug', 'Migrations class initialized'); + + // Are they trying to use migrations while it is disabled? + if ($this->_migration_enabled !== TRUE) + { + show_error('Migrations has been loaded but is disabled or set up incorrectly.'); + } + + // If not set, set it + $this->_migration_path !== '' OR $this->_migration_path = APPPATH.'migrations/'; + + // Add trailing slash if not set + $this->_migration_path = rtrim($this->_migration_path, '/').'/'; + + // Load migration language + $this->lang->load('migration'); + + // They'll probably be using dbforge + $this->load->dbforge(); + + // Make sure the migration table name was set. + if (empty($this->_migration_table)) + { + show_error('Migrations configuration file (migration.php) must have "migration_table" set.'); + } + + // Migration basename regex + switch($this->_migration_type){ + case 'timestamp': + $this->_migration_regex = '/^\d{14}_(\w+)$/'; + break; + case 'unmark': + $this->_migration_regex = '/^\d{10}_(\w+)$/'; + break; + default: + $this->_migration_regex = '/^\d{3}_(\w+)$/'; + } + + // Make sure a valid migration numbering type was set. + if ( ! in_array($this->_migration_type, array('sequential', 'timestamp', 'unmark'))) + { + show_error('An invalid migration numbering type was specified: '.$this->_migration_type); + } + + // If the migrations table is missing, make it + if ( ! $this->db->table_exists($this->_migration_table)) + { + $this->dbforge->add_field(array( + 'version' => array('type' => 'BIGINT', 'constraint' => 20), + )); + + $this->dbforge->create_table($this->_migration_table, TRUE); + + $this->db->insert($this->_migration_table, array('version' => 0)); + } + + // Do we auto migrate to the latest migration? + if ($this->_migration_auto_latest === TRUE && ! $this->latest()) + { + show_error($this->error_string()); + } // Check that all tables are InnoDB - parent::__construct($config); self::checkForInnoDB(); } @@ -96,6 +172,30 @@ public function version($target_version) } return $migrationsResult; } + + /** + * Retrieves current schema version + * If _migration_type == 'unmark' and previous version matches timestamp - return different version + * + * @return int Current Migration + */ + protected function _get_version() + { + $row = $this->db->select('version')->get($this->_migration_table)->row(); + $finalVersion = $row ? $row->version : 0; + // Check if we're not switching from timestamp to unmark + if($finalVersion != 0 && $this->_migration_type === 'unmark' && strlen((string) $finalVersion) == 14){ + // Switch from timestamp to unmark + if(!empty($this->_migration_mappings) && !empty($this->_migration_mappings[$finalVersion])){ + log_message('debug', sprintf('Returning mapped %s instead of original %s migration version and updating DB', $this->_migration_mappings[$finalVersion] , $finalVersion)); + $finalVersion = $this->_migration_mappings[$finalVersion]; + $this->_update_version($finalVersion); + } else{ + show_error(sprintf(_('Migrations switched from timestamp to unmark, but cannot find mapping for version %s. Please add correct version to migrations_mapping config entry for migrations'), $finalVersion)); + } + } + return $finalVersion; + } /** * Creates database backup and returns a path to a file with this backup diff --git a/application/migrations/20140228091723_label_sort.php b/application/migrations/2014022801_label_sort.php similarity index 100% rename from application/migrations/20140228091723_label_sort.php rename to application/migrations/2014022801_label_sort.php