mirror of
https://we.phorge.it/source/phorge.git
synced 2025-04-10 19:38:34 +02:00
Allow bin/storage adjust
to make key changes
Summary: Ref T1191. These are a bit tricky because keys can interact with column changes, so basically we do three phases: 1. Nuke all bad keys. 2. Make all column (and database/table) changes. 3. Fix all nuked keys. Test Plan: Ran migration locally. See note for remaining issues. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10599
This commit is contained in:
parent
22ee8432d2
commit
a5ce56aa76
1 changed files with 135 additions and 42 deletions
|
@ -129,56 +129,99 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
|
|
||||||
$failed = array();
|
$failed = array();
|
||||||
|
|
||||||
|
// We make changes in three phases:
|
||||||
|
//
|
||||||
|
// Phase 0: Drop all keys which we're going to adjust. This prevents them
|
||||||
|
// from interfering with column changes.
|
||||||
|
//
|
||||||
|
// Phase 1: Apply all database, table, and column changes.
|
||||||
|
//
|
||||||
|
// Phase 2: Restore adjusted keys.
|
||||||
|
$phases = 3;
|
||||||
|
|
||||||
$bar = id(new PhutilConsoleProgressBar())
|
$bar = id(new PhutilConsoleProgressBar())
|
||||||
->setTotal(count($adjustments));
|
->setTotal(count($adjustments) * $phases);
|
||||||
foreach ($adjustments as $adjust) {
|
|
||||||
try {
|
for ($phase = 0; $phase < $phases; $phase++) {
|
||||||
switch ($adjust['kind']) {
|
foreach ($adjustments as $adjust) {
|
||||||
case 'database':
|
try {
|
||||||
queryfx(
|
switch ($adjust['kind']) {
|
||||||
$conn,
|
case 'database':
|
||||||
'ALTER DATABASE %T CHARACTER SET = %s COLLATE = %s',
|
if ($phase != 1) {
|
||||||
$adjust['database'],
|
break;
|
||||||
$adjust['charset'],
|
}
|
||||||
$adjust['collation']);
|
queryfx(
|
||||||
break;
|
|
||||||
case 'table':
|
|
||||||
queryfx(
|
|
||||||
$conn,
|
|
||||||
'ALTER TABLE %T.%T COLLATE = %s',
|
|
||||||
$adjust['database'],
|
|
||||||
$adjust['table'],
|
|
||||||
$adjust['collation']);
|
|
||||||
break;
|
|
||||||
case 'column':
|
|
||||||
$parts = array();
|
|
||||||
if ($adjust['charset']) {
|
|
||||||
$parts[] = qsprintf(
|
|
||||||
$conn,
|
$conn,
|
||||||
'CHARACTER SET %Q COLLATE %Q',
|
'ALTER DATABASE %T CHARACTER SET = %s COLLATE = %s',
|
||||||
|
$adjust['database'],
|
||||||
$adjust['charset'],
|
$adjust['charset'],
|
||||||
$adjust['collation']);
|
$adjust['collation']);
|
||||||
}
|
break;
|
||||||
|
case 'table':
|
||||||
|
if ($phase != 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'ALTER TABLE %T.%T COLLATE = %s',
|
||||||
|
$adjust['database'],
|
||||||
|
$adjust['table'],
|
||||||
|
$adjust['collation']);
|
||||||
|
break;
|
||||||
|
case 'column':
|
||||||
|
if ($phase != 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$parts = array();
|
||||||
|
if ($adjust['charset']) {
|
||||||
|
$parts[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'CHARACTER SET %Q COLLATE %Q',
|
||||||
|
$adjust['charset'],
|
||||||
|
$adjust['collation']);
|
||||||
|
}
|
||||||
|
|
||||||
queryfx(
|
queryfx(
|
||||||
$conn,
|
$conn,
|
||||||
'ALTER TABLE %T.%T MODIFY %T %Q %Q %Q',
|
'ALTER TABLE %T.%T MODIFY %T %Q %Q %Q',
|
||||||
$adjust['database'],
|
$adjust['database'],
|
||||||
$adjust['table'],
|
$adjust['table'],
|
||||||
$adjust['name'],
|
$adjust['name'],
|
||||||
$adjust['type'],
|
$adjust['type'],
|
||||||
implode(' ', $parts),
|
implode(' ', $parts),
|
||||||
$adjust['nullable'] ? 'NULL' : 'NOT NULL');
|
$adjust['nullable'] ? 'NULL' : 'NOT NULL');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
case 'key':
|
||||||
throw new Exception(
|
if (($phase == 0) && $adjust['exists']) {
|
||||||
pht('Unknown schema adjustment kind "%s"!', $adjust['kind']));
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'ALTER TABLE %T.%T DROP KEY %T',
|
||||||
|
$adjust['database'],
|
||||||
|
$adjust['table'],
|
||||||
|
$adjust['name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($phase == 2) && $adjust['keep']) {
|
||||||
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'ALTER TABLE %T.%T ADD %Q KEY %T (%Q)',
|
||||||
|
$adjust['database'],
|
||||||
|
$adjust['table'],
|
||||||
|
$adjust['unique'] ? 'UNIQUE' : '/* NONUNIQUE */',
|
||||||
|
$adjust['name'],
|
||||||
|
implode(', ', $adjust['columns']));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception(
|
||||||
|
pht('Unknown schema adjustment kind "%s"!', $adjust['kind']));
|
||||||
|
}
|
||||||
|
} catch (AphrontQueryException $ex) {
|
||||||
|
$failed[] = array($adjust, $ex);
|
||||||
}
|
}
|
||||||
} catch (AphrontQueryException $ex) {
|
$bar->update(1);
|
||||||
$failed[] = array($adjust, $ex);
|
|
||||||
}
|
}
|
||||||
$bar->update(1);
|
|
||||||
}
|
}
|
||||||
$bar->done();
|
$bar->done();
|
||||||
|
|
||||||
|
@ -222,6 +265,11 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
$issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
|
$issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
|
||||||
$issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
|
$issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
|
||||||
$issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE;
|
$issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE;
|
||||||
|
$issue_surpluskey = PhabricatorConfigStorageSchema::ISSUE_SURPLUSKEY;
|
||||||
|
$issue_missingkey = PhabricatorConfigStorageSchema::ISSUE_MISSINGKEY;
|
||||||
|
$issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS;
|
||||||
|
$issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
|
||||||
|
|
||||||
|
|
||||||
$adjustments = array();
|
$adjustments = array();
|
||||||
foreach ($comp->getDatabases() as $database_name => $database) {
|
foreach ($comp->getDatabases() as $database_name => $database) {
|
||||||
|
@ -321,6 +369,51 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($table->getKeys() as $key_name => $key) {
|
||||||
|
$expect_key = $expect_table->getKey($key_name);
|
||||||
|
$actual_key = $actual_table->getKey($key_name);
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
$keep_key = true;
|
||||||
|
if ($key->hasIssue($issue_surpluskey)) {
|
||||||
|
$issues[] = $issue_surpluskey;
|
||||||
|
$keep_key = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($key->hasIssue($issue_missingkey)) {
|
||||||
|
$issues[] = $issue_missingkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($key->hasIssue($issue_columns)) {
|
||||||
|
$issues[] = $issue_columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($key->hasIssue($issue_unique)) {
|
||||||
|
$issues[] = $issue_unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($issues) {
|
||||||
|
$adjustment = array(
|
||||||
|
'kind' => 'key',
|
||||||
|
'database' => $database_name,
|
||||||
|
'table' => $table_name,
|
||||||
|
'name' => $key_name,
|
||||||
|
'issues' => $issues,
|
||||||
|
'exists' => (bool)$actual_key,
|
||||||
|
'keep' => $keep_key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($keep_key) {
|
||||||
|
$adjustment += array(
|
||||||
|
'columns' => $expect_key->getColumnNames(),
|
||||||
|
'unique' => $expect_key->getUnique(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$adjustments[] = $adjustment;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue