mirror of
https://github.com/phpbb/phpbb.git
synced 2025-07-31 14:00:31 +02:00
Merge pull request #1995 from EXreaction/ticket/11880
Schema changes can take too long and cause a timeout
This commit is contained in:
82
phpBB/phpbb/db/migration/helper.php
Normal file
82
phpBB/phpbb/db/migration/helper.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @package db
|
||||
* @copyright (c) 2014 phpBB Group
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\migration;
|
||||
|
||||
/**
|
||||
* The migrator is responsible for applying new migrations in the correct order.
|
||||
*
|
||||
* @package db
|
||||
*/
|
||||
class helper
|
||||
{
|
||||
/**
|
||||
* Get the schema steps from an array of schema changes
|
||||
*
|
||||
* This splits up $schema_changes into individual changes so that the
|
||||
* changes can be chunked
|
||||
*
|
||||
* @param array $schema_changes from migration
|
||||
* @return array
|
||||
*/
|
||||
public function get_schema_steps($schema_changes)
|
||||
{
|
||||
$steps = array();
|
||||
|
||||
// Nested level of data (only supports 1/2 currently)
|
||||
$nested_level = array(
|
||||
'drop_tables' => 1,
|
||||
'add_tables' => 1,
|
||||
'change_columns' => 2,
|
||||
'add_columns' => 2,
|
||||
'drop_keys' => 2,
|
||||
'drop_columns' => 2,
|
||||
'add_primary_keys' => 2, // perform_schema_changes only uses one level, but second is in the function
|
||||
'add_unique_index' => 2,
|
||||
'add_index' => 2,
|
||||
);
|
||||
|
||||
foreach ($nested_level as $change_type => $data_depth)
|
||||
{
|
||||
if (!empty($schema_changes[$change_type]))
|
||||
{
|
||||
foreach ($schema_changes[$change_type] as $key => $value)
|
||||
{
|
||||
if ($data_depth === 1)
|
||||
{
|
||||
$steps[] = array(
|
||||
'dbtools.perform_schema_changes', array(array(
|
||||
$change_type => array(
|
||||
$value,
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
else if ($data_depth === 2)
|
||||
{
|
||||
foreach ($value as $key2 => $value2)
|
||||
{
|
||||
$steps[] = array(
|
||||
'dbtools.perform_schema_changes', array(array(
|
||||
$change_type => array(
|
||||
$key => array(
|
||||
$key2 => $value2,
|
||||
),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $steps;
|
||||
}
|
||||
}
|
@@ -25,6 +25,9 @@ class migrator
|
||||
/** @var \phpbb\db\tools */
|
||||
protected $db_tools;
|
||||
|
||||
/** @var \phpbb\db\migration\helper */
|
||||
protected $helper;
|
||||
|
||||
/** @var string */
|
||||
protected $table_prefix;
|
||||
|
||||
@@ -65,11 +68,12 @@ class migrator
|
||||
/**
|
||||
* Constructor of the database migrator
|
||||
*/
|
||||
public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools)
|
||||
public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->db = $db;
|
||||
$this->db_tools = $db_tools;
|
||||
$this->helper = $helper;
|
||||
|
||||
$this->migrations_table = $migrations_table;
|
||||
|
||||
@@ -83,6 +87,8 @@ class migrator
|
||||
$this->tools[$tool->get_name()] = $tool;
|
||||
}
|
||||
|
||||
$this->tools['dbtools'] = $this->db_tools;
|
||||
|
||||
$this->load_migration_state();
|
||||
}
|
||||
|
||||
@@ -229,9 +235,12 @@ class migrator
|
||||
|
||||
if (!$state['migration_schema_done'])
|
||||
{
|
||||
$this->last_run_migration['task'] = 'apply_schema_changes';
|
||||
$this->apply_schema_changes($migration->update_schema());
|
||||
$state['migration_schema_done'] = true;
|
||||
$this->last_run_migration['task'] = 'process_schema_step';
|
||||
$steps = $this->helper->get_schema_steps($migration->update_schema());
|
||||
$result = $this->process_data_step($steps, $state['migration_data_state']);
|
||||
|
||||
$state['migration_data_state'] = ($result === true) ? '' : $result;
|
||||
$state['migration_schema_done'] = ($result === true);
|
||||
}
|
||||
else if (!$state['migration_data_done'])
|
||||
{
|
||||
@@ -329,32 +338,27 @@ class migrator
|
||||
|
||||
$this->set_migration_state($name, $state);
|
||||
}
|
||||
else
|
||||
else if ($state['migration_schema_done'])
|
||||
{
|
||||
$this->apply_schema_changes($migration->revert_schema());
|
||||
$steps = $this->helper->get_schema_steps($migration->revert_schema());
|
||||
$result = $this->process_data_step($steps, $state['migration_data_state']);
|
||||
|
||||
$sql = 'DELETE FROM ' . $this->migrations_table . "
|
||||
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
|
||||
$this->db->sql_query($sql);
|
||||
$state['migration_data_state'] = ($result === true) ? '' : $result;
|
||||
$state['migration_schema_done'] = ($result === true) ? false : true;
|
||||
|
||||
unset($this->migration_state[$name]);
|
||||
if (!$state['migration_schema_done'])
|
||||
{
|
||||
$sql = 'DELETE FROM ' . $this->migrations_table . "
|
||||
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
unset($this->migration_state[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply schema changes from a migration
|
||||
*
|
||||
* Just calls db_tools->perform_schema_changes
|
||||
*
|
||||
* @param array $schema_changes from migration
|
||||
*/
|
||||
protected function apply_schema_changes($schema_changes)
|
||||
{
|
||||
$this->db_tools->perform_schema_changes($schema_changes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the data step of the migration
|
||||
*
|
||||
@@ -498,6 +502,7 @@ class migrator
|
||||
|
||||
return $this->get_callable_from_step($step);
|
||||
break;
|
||||
|
||||
case 'custom':
|
||||
if (!is_callable($parameters[0]))
|
||||
{
|
||||
|
Reference in New Issue
Block a user