Normally this doesn't cause much of a problem, but wrong update hook numbering just hurts my soul.
The documentation states: "Never renumber update hooks". Well ... screw that :-). Let's try and do it anyway, in a sensible and hopefully elegant manner.
The old and wrong hook_update_N numbering could look like this:
/**
* Do stuff ...
*/
function mymodule_update_7000(&$sandbox) {
// Do stuff ...
}
/**
* Do stuff ...
*/
function mymodule_update_7001(&$sandbox) {
// Do stuff ...
}
/**
* Do stuff ...
*/
function mymodule_update_7100(&$sandbox) {
// Do stuff ...
}
7000 and 7001 are wrong in this case. Someone has then skipped to 7100 in an attempt to fix the numbering. But has obviously failed. What we really want is:
/**
* Do stuff ...
*/
function mymodule_update_7101(&$sandbox) {
// Do stuff ...
}
/**
* Do stuff ...
*/
function mymodule_update_7102(&$sandbox) {
// Do stuff ...
}
/**
* Do stuff ...
*/
function mymodule_update_7103(&$sandbox) {
// Do stuff ...
}
How do we get from the old to the new?
/**
* Mapping of schema versions (old => new).
*
* @return array
*/
function _mymodule_get_mapping() {
return array(
7000 => 7101,
7001 => 7102,
7100 => 7103,
);
}
/**
* Implements hook_requirements().
*
* Check and fix schema version before updating.
*/
function mymodule_requirements($phase) {
switch ($phase) {
case 'update':
_mymodule_renumber_schema_version();
break;
}
}
/**
* Drush does not invoke hook_requirements('update') for modules other
* than 'system'.
*
* Attempt to intercept the command updatedb (updb), and fix the schema
* version if applicable.
*/
if (drupal_is_cli() && function_exists('drush_get_command')) {
$command = drush_get_command();
if (isset($command['command']) && $command['command'] == 'updatedb') {
_mymodule_renumber_schema_version();
}
}
/**
* Renumber current schema version according to mapping.
*/
function _mymodule_renumber_schema_version() {
$schema_version = _mymodule_get_current_schema_version();
$mapping = _mymodule_get_mapping();
if (!empty($mapping[$schema_version])) {
$new_version = $mapping[$schema_version];
drupal_set_installed_schema_version('mymodule', $new_version);
}
}
/**
* Helper function for getting the current schema version.
*/
function _mymodule_get_current_schema_version() {
return db_select('system', 's')
->fields('s', array('schema_version'))
->condition('name', 'mymodule')
->execute()
->fetchField();
}
/**
* Do stuff ...
*/
function mymodule_update_7101(&$sandbox) {
// Do stuff ...
}
/**
* Do stuff ...
*/
function mymodule_update_7102(&$sandbox) {
// Do stuff ...
}
/**
* Do stuff ...
*/
function mymodule_update_7103(&$sandbox) {
// Do stuff ...
}
Caveat: The might very well be some slight problems regarding hook_update_dependencies(), if other modules implement this towards your module.