mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 13:30:55 +01:00
Support AUTO_INCREMENT in bin/storage adjust
Summary: Ref T1191. When changing the column type of an AUTO_INCREMENT column, we currently may lose the autoincrement attribute. Instead, support it. This is a bit messy because AUTO_INCREMENT columns interact with PRIMARY KEY columns (tables may only have one AUTO_INCREMENT column, and it must be a primary key). We need to migrate in more phases to avoid this issue. Introduce new `auto` and `auto64` types to represent autoincrement IDs. Test Plan: - Saw autoincrement show up correctly in web UI. - Fixed an autoincrement issue on the XHProf storage table with `bin/storage adjust` safely. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10607
This commit is contained in:
parent
0d7489da79
commit
300172e799
16 changed files with 185 additions and 69 deletions
|
@ -9,7 +9,7 @@ final class PhabricatorCacheSchemaSpec extends PhabricatorConfigSchemaSpec {
|
||||||
'cache',
|
'cache',
|
||||||
id(new PhabricatorKeyValueDatabaseCache())->getTableName(),
|
id(new PhabricatorKeyValueDatabaseCache())->getTableName(),
|
||||||
array(
|
array(
|
||||||
'id' => 'id64',
|
'id' => 'auto64',
|
||||||
'cacheKeyHash' => 'bytes12',
|
'cacheKeyHash' => 'bytes12',
|
||||||
'cacheKey' => 'text128',
|
'cacheKey' => 'text128',
|
||||||
'cacheFormat' => 'text16',
|
'cacheFormat' => 'text16',
|
||||||
|
|
|
@ -13,7 +13,7 @@ final class PhabricatorConduitMethodCallLog
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
'id' => 'id64',
|
'id' => 'auto64',
|
||||||
'connectionID' => 'id64?',
|
'connectionID' => 'id64?',
|
||||||
'method' => 'text64',
|
'method' => 'text64',
|
||||||
'error' => 'text255',
|
'error' => 'text255',
|
||||||
|
|
|
@ -282,6 +282,7 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
$unique_issue = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
|
$unique_issue = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
|
||||||
$columns_issue = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS;
|
$columns_issue = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS;
|
||||||
$longkey_issue = PhabricatorConfigStorageSchema::ISSUE_LONGKEY;
|
$longkey_issue = PhabricatorConfigStorageSchema::ISSUE_LONGKEY;
|
||||||
|
$auto_issue = PhabricatorConfigStorageSchema::ISSUE_AUTOINCREMENT;
|
||||||
|
|
||||||
$database = $comp->getDatabase($database_name);
|
$database = $comp->getDatabase($database_name);
|
||||||
if (!$database) {
|
if (!$database) {
|
||||||
|
@ -339,6 +340,9 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
$this->renderAttr(
|
$this->renderAttr(
|
||||||
$this->renderBoolean($column->getNullable()),
|
$this->renderBoolean($column->getNullable()),
|
||||||
$column->hasIssue($nullable_issue)),
|
$column->hasIssue($nullable_issue)),
|
||||||
|
$this->renderAttr(
|
||||||
|
$this->renderBoolean($column->getAutoIncrement()),
|
||||||
|
$column->hasIssue($auto_issue)),
|
||||||
$this->renderAttr(
|
$this->renderAttr(
|
||||||
$column->getCharacterSet(),
|
$column->getCharacterSet(),
|
||||||
$column->hasIssue($charset_issue)),
|
$column->hasIssue($charset_issue)),
|
||||||
|
@ -356,6 +360,7 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
pht('Data Type'),
|
pht('Data Type'),
|
||||||
pht('Column Type'),
|
pht('Column Type'),
|
||||||
pht('Nullable'),
|
pht('Nullable'),
|
||||||
|
pht('Autoincrement'),
|
||||||
pht('Character Set'),
|
pht('Character Set'),
|
||||||
pht('Collation'),
|
pht('Collation'),
|
||||||
))
|
))
|
||||||
|
@ -366,6 +371,7 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -521,11 +527,13 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
$actual_charset = $actual_column->getCharacterSet();
|
$actual_charset = $actual_column->getCharacterSet();
|
||||||
$actual_collation = $actual_column->getCollation();
|
$actual_collation = $actual_column->getCollation();
|
||||||
$actual_nullable = $actual_column->getNullable();
|
$actual_nullable = $actual_column->getNullable();
|
||||||
|
$actual_auto = $actual_column->getAutoIncrement();
|
||||||
} else {
|
} else {
|
||||||
$actual_coltype = null;
|
$actual_coltype = null;
|
||||||
$actual_charset = null;
|
$actual_charset = null;
|
||||||
$actual_collation = null;
|
$actual_collation = null;
|
||||||
$actual_nullable = null;
|
$actual_nullable = null;
|
||||||
|
$actual_auto = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($expect_column) {
|
if ($expect_column) {
|
||||||
|
@ -534,12 +542,14 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
$expect_charset = $expect_column->getCharacterSet();
|
$expect_charset = $expect_column->getCharacterSet();
|
||||||
$expect_collation = $expect_column->getCollation();
|
$expect_collation = $expect_column->getCollation();
|
||||||
$expect_nullable = $expect_column->getNullable();
|
$expect_nullable = $expect_column->getNullable();
|
||||||
|
$expect_auto = $expect_column->getAutoIncrement();
|
||||||
} else {
|
} else {
|
||||||
$data_type = null;
|
$data_type = null;
|
||||||
$expect_coltype = null;
|
$expect_coltype = null;
|
||||||
$expect_charset = null;
|
$expect_charset = null;
|
||||||
$expect_collation = null;
|
$expect_collation = null;
|
||||||
$expect_nullable = null;
|
$expect_nullable = null;
|
||||||
|
$expect_auto = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -587,6 +597,14 @@ final class PhabricatorConfigDatabaseStatusController
|
||||||
pht('Expected Nullable'),
|
pht('Expected Nullable'),
|
||||||
$this->renderBoolean($expect_nullable),
|
$this->renderBoolean($expect_nullable),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
pht('Autoincrement'),
|
||||||
|
$this->renderBoolean($actual_auto),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
pht('Expected Autoincrement'),
|
||||||
|
$this->renderBoolean($expect_auto),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
$column->getIssues());
|
$column->getIssues());
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,16 @@ final class PhabricatorConfigColumnSchema
|
||||||
private $columnType;
|
private $columnType;
|
||||||
private $dataType;
|
private $dataType;
|
||||||
private $nullable;
|
private $nullable;
|
||||||
|
private $autoIncrement;
|
||||||
|
|
||||||
|
public function setAutoIncrement($auto_increment) {
|
||||||
|
$this->autoIncrement = $auto_increment;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAutoIncrement() {
|
||||||
|
return $this->autoIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
public function setNullable($nullable) {
|
public function setNullable($nullable) {
|
||||||
$this->nullable = $nullable;
|
$this->nullable = $nullable;
|
||||||
|
@ -131,6 +141,10 @@ final class PhabricatorConfigColumnSchema
|
||||||
$issues[] = self::ISSUE_NULLABLE;
|
$issues[] = self::ISSUE_NULLABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->getAutoIncrement() !== $expect->getAutoIncrement()) {
|
||||||
|
$issues[] = self::ISSUE_AUTOINCREMENT;
|
||||||
|
}
|
||||||
|
|
||||||
return $issues;
|
return $issues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ final class PhabricatorConfigSchemaQuery extends Phobject {
|
||||||
$column_info = queryfx_all(
|
$column_info = queryfx_all(
|
||||||
$conn,
|
$conn,
|
||||||
'SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME,
|
'SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME,
|
||||||
COLLATION_NAME, COLUMN_TYPE, IS_NULLABLE
|
COLLATION_NAME, COLUMN_TYPE, IS_NULLABLE, EXTRA
|
||||||
FROM INFORMATION_SCHEMA.COLUMNS
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
WHERE (%Q)',
|
WHERE (%Q)',
|
||||||
'('.implode(') OR (', $sql).')');
|
'('.implode(') OR (', $sql).')');
|
||||||
|
@ -96,12 +96,19 @@ final class PhabricatorConfigSchemaQuery extends Phobject {
|
||||||
|
|
||||||
$columns = idx($database_column_info, $table_name, array());
|
$columns = idx($database_column_info, $table_name, array());
|
||||||
foreach ($columns as $column) {
|
foreach ($columns as $column) {
|
||||||
|
if (strpos($column['EXTRA'], 'auto_increment') === false) {
|
||||||
|
$auto_increment = false;
|
||||||
|
} else {
|
||||||
|
$auto_increment = true;
|
||||||
|
}
|
||||||
|
|
||||||
$column_schema = id(new PhabricatorConfigColumnSchema())
|
$column_schema = id(new PhabricatorConfigColumnSchema())
|
||||||
->setName($column['COLUMN_NAME'])
|
->setName($column['COLUMN_NAME'])
|
||||||
->setCharacterSet($column['CHARACTER_SET_NAME'])
|
->setCharacterSet($column['CHARACTER_SET_NAME'])
|
||||||
->setCollation($column['COLLATION_NAME'])
|
->setCollation($column['COLLATION_NAME'])
|
||||||
->setColumnType($column['COLUMN_TYPE'])
|
->setColumnType($column['COLUMN_TYPE'])
|
||||||
->setNullable($column['IS_NULLABLE'] == 'YES');
|
->setNullable($column['IS_NULLABLE'] == 'YES')
|
||||||
|
->setAutoIncrement($auto_increment);
|
||||||
|
|
||||||
$table_schema->addColumn($column_schema);
|
$table_schema->addColumn($column_schema);
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,14 +102,15 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
$details = $this->getDetailsForDataType($type);
|
$details = $this->getDetailsForDataType($type);
|
||||||
list($column_type, $charset, $collation, $nullable) = $details;
|
list($column_type, $charset, $collation, $nullable, $auto) = $details;
|
||||||
|
|
||||||
$column = $this->newColumn($name)
|
$column = $this->newColumn($name)
|
||||||
->setDataType($type)
|
->setDataType($type)
|
||||||
->setColumnType($column_type)
|
->setColumnType($column_type)
|
||||||
->setCharacterSet($charset)
|
->setCharacterSet($charset)
|
||||||
->setCollation($collation)
|
->setCollation($collation)
|
||||||
->setNullable($nullable);
|
->setNullable($nullable)
|
||||||
|
->setAutoIncrement($auto);
|
||||||
|
|
||||||
$table->addColumn($column);
|
$table->addColumn($column);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +163,7 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
|
||||||
$object->getApplicationName(),
|
$object->getApplicationName(),
|
||||||
PhabricatorEdgeConfig::TABLE_NAME_EDGEDATA,
|
PhabricatorEdgeConfig::TABLE_NAME_EDGEDATA,
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'data' => 'text',
|
'data' => 'text',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
|
@ -233,6 +234,7 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
|
||||||
$column_type = null;
|
$column_type = null;
|
||||||
$charset = null;
|
$charset = null;
|
||||||
$collation = null;
|
$collation = null;
|
||||||
|
$auto = false;
|
||||||
|
|
||||||
// If the type ends with "?", make the column nullable.
|
// If the type ends with "?", make the column nullable.
|
||||||
$nullable = false;
|
$nullable = false;
|
||||||
|
@ -246,6 +248,14 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
|
||||||
// totally disallowed in a MODIFY statement vs a CREATE TABLE statement.
|
// totally disallowed in a MODIFY statement vs a CREATE TABLE statement.
|
||||||
|
|
||||||
switch ($data_type) {
|
switch ($data_type) {
|
||||||
|
case 'auto':
|
||||||
|
$column_type = 'int(10) unsigned';
|
||||||
|
$auto = true;
|
||||||
|
break;
|
||||||
|
case 'auto64':
|
||||||
|
$column_type = 'bigint(20) unsigned';
|
||||||
|
$auto = true;
|
||||||
|
break;
|
||||||
case 'id':
|
case 'id':
|
||||||
case 'epoch':
|
case 'epoch':
|
||||||
case 'uint32':
|
case 'uint32':
|
||||||
|
@ -392,7 +402,7 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($column_type, $charset, $collation, $nullable);
|
return array($column_type, $charset, $collation, $nullable, $auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ abstract class PhabricatorConfigStorageSchema extends Phobject {
|
||||||
const ISSUE_LONGKEY = 'longkey';
|
const ISSUE_LONGKEY = 'longkey';
|
||||||
const ISSUE_SUBWARN = 'subwarn';
|
const ISSUE_SUBWARN = 'subwarn';
|
||||||
const ISSUE_SUBFAIL = 'subfail';
|
const ISSUE_SUBFAIL = 'subfail';
|
||||||
|
const ISSUE_AUTOINCREMENT = 'autoincrement';
|
||||||
|
|
||||||
const STATUS_OKAY = 'okay';
|
const STATUS_OKAY = 'okay';
|
||||||
const STATUS_WARN = 'warn';
|
const STATUS_WARN = 'warn';
|
||||||
|
@ -124,6 +125,8 @@ abstract class PhabricatorConfigStorageSchema extends Phobject {
|
||||||
return pht('Subschemata Have Warnings');
|
return pht('Subschemata Have Warnings');
|
||||||
case self::ISSUE_SUBFAIL:
|
case self::ISSUE_SUBFAIL:
|
||||||
return pht('Subschemata Have Failures');
|
return pht('Subschemata Have Failures');
|
||||||
|
case self::ISSUE_AUTOINCREMENT:
|
||||||
|
return pht('Column has Wrong Autoincrement');
|
||||||
default:
|
default:
|
||||||
throw new Exception(pht('Unknown schema issue "%s"!', $issue));
|
throw new Exception(pht('Unknown schema issue "%s"!', $issue));
|
||||||
}
|
}
|
||||||
|
@ -157,6 +160,8 @@ abstract class PhabricatorConfigStorageSchema extends Phobject {
|
||||||
return pht('Subschemata have setup warnings.');
|
return pht('Subschemata have setup warnings.');
|
||||||
case self::ISSUE_SUBFAIL:
|
case self::ISSUE_SUBFAIL:
|
||||||
return pht('Subschemata have setup failures.');
|
return pht('Subschemata have setup failures.');
|
||||||
|
case self::ISSUE_AUTOINCREMENT:
|
||||||
|
return pht('This column has the wrong autoincrement setting.');
|
||||||
default:
|
default:
|
||||||
throw new Exception(pht('Unknown schema issue "%s"!', $issue));
|
throw new Exception(pht('Unknown schema issue "%s"!', $issue));
|
||||||
}
|
}
|
||||||
|
@ -178,6 +183,7 @@ abstract class PhabricatorConfigStorageSchema extends Phobject {
|
||||||
case self::ISSUE_UNIQUE:
|
case self::ISSUE_UNIQUE:
|
||||||
case self::ISSUE_KEYCOLUMNS:
|
case self::ISSUE_KEYCOLUMNS:
|
||||||
case self::ISSUE_LONGKEY:
|
case self::ISSUE_LONGKEY:
|
||||||
|
case self::ISSUE_AUTOINCREMENT:
|
||||||
return self::STATUS_WARN;
|
return self::STATUS_WARN;
|
||||||
default:
|
default:
|
||||||
throw new Exception(pht('Unknown schema issue "%s"!', $issue));
|
throw new Exception(pht('Unknown schema issue "%s"!', $issue));
|
||||||
|
|
|
@ -9,7 +9,7 @@ final class PhabricatorFactAggregate extends PhabricatorFactDAO {
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
'id' => 'id64',
|
'id' => 'auto64',
|
||||||
'factType' => 'text32',
|
'factType' => 'text32',
|
||||||
'valueX' => 'uint64',
|
'valueX' => 'uint64',
|
||||||
),
|
),
|
||||||
|
|
|
@ -15,7 +15,7 @@ final class PhabricatorFactRaw extends PhabricatorFactDAO {
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
'id' => 'id64',
|
'id' => 'auto64',
|
||||||
'factType' => 'text32',
|
'factType' => 'text32',
|
||||||
'objectA' => 'phid',
|
'objectA' => 'phid',
|
||||||
'valueX' => 'sint64',
|
'valueX' => 'sint64',
|
||||||
|
|
|
@ -24,7 +24,7 @@ final class HarbormasterSchemaSpec extends PhabricatorConfigSchemaSpec {
|
||||||
id(new HarbormasterBuildable())->getApplicationName(),
|
id(new HarbormasterBuildable())->getApplicationName(),
|
||||||
'harbormaster_buildlogchunk',
|
'harbormaster_buildlogchunk',
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'logID' => 'id',
|
'logID' => 'id',
|
||||||
'encoding' => 'text32',
|
'encoding' => 'text32',
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ final class PhabricatorProjectSchemaSpec extends PhabricatorConfigSchemaSpec {
|
||||||
id(new PhabricatorProject())->getApplicationName(),
|
id(new PhabricatorProject())->getApplicationName(),
|
||||||
PhabricatorProject::TABLE_DATASOURCE_TOKEN,
|
PhabricatorProject::TABLE_DATASOURCE_TOKEN,
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'projectID' => 'id',
|
'projectID' => 'id',
|
||||||
'token' => 'text128',
|
'token' => 'text128',
|
||||||
),
|
),
|
||||||
|
|
|
@ -29,7 +29,7 @@ final class PhabricatorRepositorySchemaSpec
|
||||||
id(new PhabricatorRepository())->getApplicationName(),
|
id(new PhabricatorRepository())->getApplicationName(),
|
||||||
PhabricatorRepository::TABLE_COVERAGE,
|
PhabricatorRepository::TABLE_COVERAGE,
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'branchID' => 'id',
|
'branchID' => 'id',
|
||||||
'commitID' => 'id',
|
'commitID' => 'id',
|
||||||
'pathID' => 'id',
|
'pathID' => 'id',
|
||||||
|
@ -70,7 +70,7 @@ final class PhabricatorRepositorySchemaSpec
|
||||||
id(new PhabricatorRepository())->getApplicationName(),
|
id(new PhabricatorRepository())->getApplicationName(),
|
||||||
PhabricatorRepository::TABLE_LINTMESSAGE,
|
PhabricatorRepository::TABLE_LINTMESSAGE,
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'branchID' => 'id',
|
'branchID' => 'id',
|
||||||
'path' => 'text',
|
'path' => 'text',
|
||||||
'line' => 'uint32',
|
'line' => 'uint32',
|
||||||
|
@ -100,7 +100,7 @@ final class PhabricatorRepositorySchemaSpec
|
||||||
id(new PhabricatorRepository())->getApplicationName(),
|
id(new PhabricatorRepository())->getApplicationName(),
|
||||||
PhabricatorRepository::TABLE_PARENTS,
|
PhabricatorRepository::TABLE_PARENTS,
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'childCommitID' => 'id',
|
'childCommitID' => 'id',
|
||||||
'parentCommitID' => 'id',
|
'parentCommitID' => 'id',
|
||||||
),
|
),
|
||||||
|
@ -122,7 +122,7 @@ final class PhabricatorRepositorySchemaSpec
|
||||||
id(new PhabricatorRepository())->getApplicationName(),
|
id(new PhabricatorRepository())->getApplicationName(),
|
||||||
PhabricatorRepository::TABLE_PATH,
|
PhabricatorRepository::TABLE_PATH,
|
||||||
array(
|
array(
|
||||||
'id' => 'id',
|
'id' => 'auto',
|
||||||
'path' => 'text',
|
'path' => 'text',
|
||||||
'pathHash' => 'bytes32',
|
'pathHash' => 'bytes32',
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class PhabricatorTokenCount extends PhabricatorTokenDAO {
|
||||||
self::CONFIG_IDS => self::IDS_MANUAL,
|
self::CONFIG_IDS => self::IDS_MANUAL,
|
||||||
self::CONFIG_TIMESTAMPS => false,
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
|
'id' => 'auto',
|
||||||
'tokenCount' => 'uint32',
|
'tokenCount' => 'uint32',
|
||||||
),
|
),
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
|
|
|
@ -10,7 +10,12 @@ final class PhabricatorWorkerArchiveTask extends PhabricatorWorkerTask {
|
||||||
protected $result;
|
protected $result;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
$config = parent::getConfiguration();
|
$config = array(
|
||||||
|
// We manage the IDs in this table; they are allocated in the ActiveTask
|
||||||
|
// table and moved here without alteration.
|
||||||
|
self::CONFIG_IDS => self::IDS_MANUAL,
|
||||||
|
) + parent::getConfiguration();
|
||||||
|
|
||||||
|
|
||||||
$config[self::CONFIG_COLUMN_SCHEMA] = array(
|
$config[self::CONFIG_COLUMN_SCHEMA] = array(
|
||||||
'result' => 'uint32',
|
'result' => 'uint32',
|
||||||
|
|
|
@ -1744,8 +1744,15 @@ abstract class LiskDAO {
|
||||||
|
|
||||||
$binary_map = $this->getBinaryColumns();
|
$binary_map = $this->getBinaryColumns();
|
||||||
|
|
||||||
|
$id_mechanism = $this->getConfigOption(self::CONFIG_IDS);
|
||||||
|
if ($id_mechanism == self::IDS_AUTOINCREMENT) {
|
||||||
|
$id_type = 'auto';
|
||||||
|
} else {
|
||||||
|
$id_type = 'id';
|
||||||
|
}
|
||||||
|
|
||||||
$builtin = array(
|
$builtin = array(
|
||||||
'id' => 'id',
|
'id' => $id_type,
|
||||||
'phid' => 'phid',
|
'phid' => 'phid',
|
||||||
'viewPolicy' => 'policy',
|
'viewPolicy' => 'policy',
|
||||||
'editPolicy' => 'policy',
|
'editPolicy' => 'policy',
|
||||||
|
|
|
@ -132,68 +132,103 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
|
|
||||||
$failed = array();
|
$failed = array();
|
||||||
|
|
||||||
// We make changes in three phases:
|
// We make changes in several phases.
|
||||||
//
|
$phases = array(
|
||||||
// Phase 0: Drop all keys which we're going to adjust. This prevents them
|
// Drop surplus autoincrements. This allows us to drop primary keys on
|
||||||
// from interfering with column changes.
|
// autoincrement columns.
|
||||||
//
|
'drop_auto',
|
||||||
// Phase 1: Apply all database, table, and column changes.
|
|
||||||
//
|
// Drop all keys we're going to adjust. This prevents them from
|
||||||
// Phase 2: Restore adjusted keys.
|
// interfering with column changes.
|
||||||
$phases = 3;
|
'drop_keys',
|
||||||
|
|
||||||
|
// Apply all database, table, and column changes.
|
||||||
|
'main',
|
||||||
|
|
||||||
|
// Restore adjusted keys.
|
||||||
|
'add_keys',
|
||||||
|
|
||||||
|
// Add missing autoincrements.
|
||||||
|
'add_auto',
|
||||||
|
);
|
||||||
|
|
||||||
$bar = id(new PhutilConsoleProgressBar())
|
$bar = id(new PhutilConsoleProgressBar())
|
||||||
->setTotal(count($adjustments) * $phases);
|
->setTotal(count($adjustments) * count($phases));
|
||||||
|
|
||||||
for ($phase = 0; $phase < $phases; $phase++) {
|
foreach ($phases as $phase) {
|
||||||
foreach ($adjustments as $adjust) {
|
foreach ($adjustments as $adjust) {
|
||||||
try {
|
try {
|
||||||
switch ($adjust['kind']) {
|
switch ($adjust['kind']) {
|
||||||
case 'database':
|
case 'database':
|
||||||
if ($phase != 1) {
|
if ($phase == 'main') {
|
||||||
break;
|
queryfx(
|
||||||
}
|
|
||||||
queryfx(
|
|
||||||
$conn,
|
|
||||||
'ALTER DATABASE %T CHARACTER SET = %s COLLATE = %s',
|
|
||||||
$adjust['database'],
|
|
||||||
$adjust['charset'],
|
|
||||||
$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,
|
$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 == 'main') {
|
||||||
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'ALTER TABLE %T.%T COLLATE = %s',
|
||||||
|
$adjust['database'],
|
||||||
|
$adjust['table'],
|
||||||
|
$adjust['collation']);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'column':
|
||||||
|
$apply = false;
|
||||||
|
$auto = false;
|
||||||
|
$new_auto = idx($adjust, 'auto');
|
||||||
|
if ($phase == 'drop_auto') {
|
||||||
|
if ($new_auto === false) {
|
||||||
|
$apply = true;
|
||||||
|
$auto = false;
|
||||||
|
}
|
||||||
|
} else if ($phase == 'main') {
|
||||||
|
$apply = true;
|
||||||
|
if ($new_auto === false) {
|
||||||
|
$auto = false;
|
||||||
|
} else {
|
||||||
|
$auto = $adjust['is_auto'];
|
||||||
|
}
|
||||||
|
} else if ($phase == 'add_auto') {
|
||||||
|
if ($new_auto === true) {
|
||||||
|
$apply = true;
|
||||||
|
$auto = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
queryfx(
|
if ($apply) {
|
||||||
$conn,
|
$parts = array();
|
||||||
'ALTER TABLE %T.%T MODIFY %T %Q %Q %Q',
|
|
||||||
$adjust['database'],
|
|
||||||
$adjust['table'],
|
|
||||||
$adjust['name'],
|
|
||||||
$adjust['type'],
|
|
||||||
implode(' ', $parts),
|
|
||||||
$adjust['nullable'] ? 'NULL' : 'NOT NULL');
|
|
||||||
|
|
||||||
|
if ($auto) {
|
||||||
|
$parts[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'AUTO_INCREMENT');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($adjust['charset']) {
|
||||||
|
$parts[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'CHARACTER SET %Q COLLATE %Q',
|
||||||
|
$adjust['charset'],
|
||||||
|
$adjust['collation']);
|
||||||
|
}
|
||||||
|
|
||||||
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'ALTER TABLE %T.%T MODIFY %T %Q %Q %Q',
|
||||||
|
$adjust['database'],
|
||||||
|
$adjust['table'],
|
||||||
|
$adjust['name'],
|
||||||
|
$adjust['type'],
|
||||||
|
implode(' ', $parts),
|
||||||
|
$adjust['nullable'] ? 'NULL' : 'NOT NULL');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'key':
|
case 'key':
|
||||||
if (($phase == 0) && $adjust['exists']) {
|
if (($phase == 0) && $adjust['exists']) {
|
||||||
|
@ -298,6 +333,7 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
$issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS;
|
$issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS;
|
||||||
$issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
|
$issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
|
||||||
$issue_longkey = PhabricatorConfigStorageSchema::ISSUE_LONGKEY;
|
$issue_longkey = PhabricatorConfigStorageSchema::ISSUE_LONGKEY;
|
||||||
|
$issue_auto = PhabricatorConfigStorageSchema::ISSUE_AUTOINCREMENT;
|
||||||
|
|
||||||
$adjustments = array();
|
$adjustments = array();
|
||||||
foreach ($comp->getDatabases() as $database_name => $database) {
|
foreach ($comp->getDatabases() as $database_name => $database) {
|
||||||
|
@ -368,6 +404,9 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
if ($column->hasIssue($issue_columntype)) {
|
if ($column->hasIssue($issue_columntype)) {
|
||||||
$issues[] = $issue_columntype;
|
$issues[] = $issue_columntype;
|
||||||
}
|
}
|
||||||
|
if ($column->hasIssue($issue_auto)) {
|
||||||
|
$issues[] = $issue_auto;
|
||||||
|
}
|
||||||
|
|
||||||
if ($issues) {
|
if ($issues) {
|
||||||
if ($expect_column->getCharacterSet() === null) {
|
if ($expect_column->getCharacterSet() === null) {
|
||||||
|
@ -380,8 +419,7 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
$collation = $expect_column->getCollation();
|
$collation = $expect_column->getCollation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$adjustment = array(
|
||||||
$adjustments[] = array(
|
|
||||||
'kind' => 'column',
|
'kind' => 'column',
|
||||||
'database' => $database_name,
|
'database' => $database_name,
|
||||||
'table' => $table_name,
|
'table' => $table_name,
|
||||||
|
@ -394,7 +432,17 @@ final class PhabricatorStorageManagementAdjustWorkflow
|
||||||
// NOTE: We don't adjust column nullability because it is
|
// NOTE: We don't adjust column nullability because it is
|
||||||
// dangerous, so always use the current nullability.
|
// dangerous, so always use the current nullability.
|
||||||
'nullable' => $actual_column->getNullable(),
|
'nullable' => $actual_column->getNullable(),
|
||||||
|
|
||||||
|
// NOTE: This always stores the current value, because we have
|
||||||
|
// to make these updates separately.
|
||||||
|
'is_auto' => $actual_column->getAutoIncrement(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($column->hasIssue($issue_auto)) {
|
||||||
|
$adjustment['auto'] = $expect_column->getAutoIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
$adjustments[] = $adjustment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue