Page MenuHomePhabricator

D10525.id25295.diff
No OneTemporary

D10525.id25295.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1344,8 +1344,10 @@
'PhabricatorConfigConfigPHIDType' => 'applications/config/phid/PhabricatorConfigConfigPHIDType.php',
'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php',
'PhabricatorConfigDatabaseController' => 'applications/config/controller/PhabricatorConfigDatabaseController.php',
+ 'PhabricatorConfigDatabaseIssueController' => 'applications/config/controller/PhabricatorConfigDatabaseIssueController.php',
'PhabricatorConfigDatabaseSchema' => 'applications/config/schema/PhabricatorConfigDatabaseSchema.php',
'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php',
+ 'PhabricatorConfigDatabaseStatusController' => 'applications/config/controller/PhabricatorConfigDatabaseStatusController.php',
'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php',
'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php',
'PhabricatorConfigEditController' => 'applications/config/controller/PhabricatorConfigEditController.php',
@@ -4261,8 +4263,10 @@
'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType',
'PhabricatorConfigController' => 'PhabricatorController',
'PhabricatorConfigDatabaseController' => 'PhabricatorConfigController',
+ 'PhabricatorConfigDatabaseIssueController' => 'PhabricatorConfigDatabaseController',
'PhabricatorConfigDatabaseSchema' => 'PhabricatorConfigStorageSchema',
'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource',
+ 'PhabricatorConfigDatabaseStatusController' => 'PhabricatorConfigDatabaseController',
'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource',
'PhabricatorConfigEditController' => 'PhabricatorConfigController',
diff --git a/src/applications/config/application/PhabricatorConfigApplication.php b/src/applications/config/application/PhabricatorConfigApplication.php
--- a/src/applications/config/application/PhabricatorConfigApplication.php
+++ b/src/applications/config/application/PhabricatorConfigApplication.php
@@ -46,7 +46,8 @@
'(?:(?P<database>[^/]+)/'.
'(?:(?P<table>[^/]+)/'.
'(?:(?:col/(?P<column>[^/]+)|key/(?P<key>[^/]+))/)?)?)?'
- => 'PhabricatorConfigDatabaseController',
+ => 'PhabricatorConfigDatabaseStatusController',
+ 'dbissue/' => 'PhabricatorConfigDatabaseIssueController',
'(?P<verb>ignore|unignore)/(?P<key>[^/]+)/'
=> 'PhabricatorConfigIgnoreController',
'issue/' => array(
diff --git a/src/applications/config/controller/PhabricatorConfigController.php b/src/applications/config/controller/PhabricatorConfigController.php
--- a/src/applications/config/controller/PhabricatorConfigController.php
+++ b/src/applications/config/controller/PhabricatorConfigController.php
@@ -18,6 +18,7 @@
$nav->addFilter('issue/', pht('Setup Issues'));
$nav->addLabel(pht('Database'));
$nav->addFilter('database/', pht('Database Status'));
+ $nav->addFilter('dbissue/', pht('Database Issues'));
$nav->addLabel(pht('Welcome'));
$nav->addFilter('welcome/', pht('Welcome Screen'));
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseController.php b/src/applications/config/controller/PhabricatorConfigDatabaseController.php
--- a/src/applications/config/controller/PhabricatorConfigDatabaseController.php
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseController.php
@@ -1,26 +1,11 @@
<?php
-final class PhabricatorConfigDatabaseController
+abstract class PhabricatorConfigDatabaseController
extends PhabricatorConfigController {
const MAX_INNODB_KEY_LENGTH = 767;
- private $database;
- private $table;
- private $column;
- private $key;
-
- public function willProcessRequest(array $data) {
- $this->database = idx($data, 'database');
- $this->table = idx($data, 'table');
- $this->column = idx($data, 'column');
- $this->key = idx($data, 'key');
- }
-
- public function processRequest() {
- $request = $this->getRequest();
- $viewer = $request->getUser();
-
+ protected function buildSchemaQuery() {
$conf = PhabricatorEnv::newObjectFromConfig(
'mysql.configuration-provider',
array($dao = null, 'w'));
@@ -35,655 +20,10 @@
$query = id(new PhabricatorConfigSchemaQuery())
->setAPI($api);
- $actual = $query->loadActualSchema();
- $expect = $query->loadExpectedSchema();
- $comp = $query->buildComparisonSchema($expect, $actual);
-
- if ($this->column) {
- return $this->renderColumn(
- $comp,
- $expect,
- $actual,
- $this->database,
- $this->table,
- $this->column);
- } else if ($this->key) {
- return $this->renderKey(
- $comp,
- $expect,
- $actual,
- $this->database,
- $this->table,
- $this->key);
- } else if ($this->table) {
- return $this->renderTable(
- $comp,
- $expect,
- $actual,
- $this->database,
- $this->table);
- } else if ($this->database) {
- return $this->renderDatabase(
- $comp,
- $expect,
- $actual,
- $this->database);
- } else {
- return $this->renderServer(
- $comp,
- $expect,
- $actual);
- }
- }
-
- private function buildResponse($title, $body) {
- $nav = $this->buildSideNavView();
- $nav->selectFilter('database/');
-
- $crumbs = $this->buildApplicationCrumbs();
- if ($this->database) {
- $crumbs->addTextCrumb(
- pht('Database Status'),
- $this->getApplicationURI('database/'));
- if ($this->table) {
- $crumbs->addTextCrumb(
- $this->database,
- $this->getApplicationURI('database/'.$this->database.'/'));
- if ($this->column || $this->key) {
- $crumbs->addTextCrumb(
- $this->table,
- $this->getApplicationURI(
- 'database/'.$this->database.'/'.$this->table.'/'));
- if ($this->column) {
- $crumbs->addTextCrumb($this->column);
- } else {
- $crumbs->addTextCrumb($this->key);
- }
- } else {
- $crumbs->addTextCrumb($this->table);
- }
- } else {
- $crumbs->addTextCrumb($this->database);
- }
- } else {
- $crumbs->addTextCrumb(pht('Database Status'));
- }
-
- $nav->setCrumbs($crumbs);
- $nav->appendChild($body);
-
- return $this->buildApplicationPage(
- $nav,
- array(
- 'title' => $title,
- ));
- }
-
-
- private function renderServer(
- PhabricatorConfigServerSchema $comp,
- PhabricatorConfigServerSchema $expect,
- PhabricatorConfigServerSchema $actual) {
-
- $charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
- $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
-
- $rows = array();
- foreach ($comp->getDatabases() as $database_name => $database) {
- $actual_database = $actual->getDatabase($database_name);
- if ($actual_database) {
- $charset = $actual_database->getCharacterSet();
- $collation = $actual_database->getCollation();
- } else {
- $charset = null;
- $collation = null;
- }
-
- $status = $database->getStatus();
- $issues = $database->getIssues();
-
- $rows[] = array(
- $this->renderIcon($status),
- phutil_tag(
- 'a',
- array(
- 'href' => $this->getApplicationURI(
- '/database/'.$database_name.'/'),
- ),
- $database_name),
- $this->renderAttr($charset, $database->hasIssue($charset_issue)),
- $this->renderAttr($collation, $database->hasIssue($collation_issue)),
- );
- }
-
- $table = id(new AphrontTableView($rows))
- ->setHeaders(
- array(
- null,
- pht('Database'),
- pht('Charset'),
- pht('Collation'),
- ))
- ->setColumnClasses(
- array(
- null,
- 'wide pri',
- null,
- null,
- ));
-
- $title = pht('Database Status');
-
- $properties = $this->buildProperties(
- array(
- ),
- $comp->getIssues());
-
- $box = id(new PHUIObjectBoxView())
- ->setHeaderText($title)
- ->addPropertyList($properties)
- ->appendChild($table);
-
- return $this->buildResponse($title, $box);
- }
-
- private function renderDatabase(
- PhabricatorConfigServerSchema $comp,
- PhabricatorConfigServerSchema $expect,
- PhabricatorConfigServerSchema $actual,
- $database_name) {
-
- $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
-
- $database = $comp->getDatabase($database_name);
- if (!$database) {
- return new Aphront404Response();
- }
-
- $rows = array();
- foreach ($database->getTables() as $table_name => $table) {
- $status = $table->getStatus();
-
- $rows[] = array(
- $this->renderIcon($status),
- phutil_tag(
- 'a',
- array(
- 'href' => $this->getApplicationURI(
- '/database/'.$database_name.'/'.$table_name.'/'),
- ),
- $table_name),
- $this->renderAttr(
- $table->getCollation(),
- $table->hasIssue($collation_issue)),
- );
- }
-
- $table = id(new AphrontTableView($rows))
- ->setHeaders(
- array(
- null,
- pht('Table'),
- pht('Collation'),
- ))
- ->setColumnClasses(
- array(
- null,
- 'wide pri',
- null,
- ));
-
- $title = pht('Database Status: %s', $database_name);
-
- $actual_database = $actual->getDatabase($database_name);
- if ($actual_database) {
- $actual_charset = $actual_database->getCharacterSet();
- $actual_collation = $actual_database->getCollation();
- } else {
- $actual_charset = null;
- $actual_collation = null;
- }
-
- $expect_database = $expect->getDatabase($database_name);
- if ($expect_database) {
- $expect_charset = $expect_database->getCharacterSet();
- $expect_collation = $expect_database->getCollation();
- } else {
- $expect_charset = null;
- $expect_collation = null;
- }
-
- $properties = $this->buildProperties(
- array(
- array(
- pht('Character Set'),
- $actual_charset,
- ),
- array(
- pht('Expected Character Set'),
- $expect_charset,
- ),
- array(
- pht('Collation'),
- $actual_collation,
- ),
- array(
- pht('Expected Collation'),
- $expect_collation,
- ),
- ),
- $database->getIssues());
-
- $box = id(new PHUIObjectBoxView())
- ->setHeaderText($title)
- ->addPropertyList($properties)
- ->appendChild($table);
-
- return $this->buildResponse($title, $box);
- }
-
- private function renderTable(
- PhabricatorConfigServerSchema $comp,
- PhabricatorConfigServerSchema $expect,
- PhabricatorConfigServerSchema $actual,
- $database_name,
- $table_name) {
-
- $type_issue = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE;
- $charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
- $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
- $nullable_issue = PhabricatorConfigStorageSchema::ISSUE_NULLABLE;
-
- $database = $comp->getDatabase($database_name);
- if (!$database) {
- return new Aphront404Response();
- }
-
- $table = $database->getTable($table_name);
- if (!$table) {
- return new Aphront404Response();
- }
-
- $actual_database = $actual->getDatabase($database_name);
- $actual_table = null;
- if ($actual_database) {
- $actual_table = $actual_database->getTable($table_name);
- }
-
- $expect_database = $expect->getDatabase($database_name);
- $expect_table = null;
- if ($expect_database) {
- $expect_table = $expect_database->getTable($table_name);
- }
-
- $rows = array();
- foreach ($table->getColumns() as $column_name => $column) {
- $expect_column = null;
- if ($expect_table) {
- $expect_column = $expect_table->getColumn($column_name);
- }
-
- $status = $column->getStatus();
-
- $data_type = null;
- if ($expect_column) {
- $data_type = $expect_column->getDataType();
- }
-
- $rows[] = array(
- $this->renderIcon($status),
- phutil_tag(
- 'a',
- array(
- 'href' => $this->getApplicationURI(
- 'database/'.
- $database_name.'/'.
- $table_name.'/'.
- 'col/'.
- $column_name.'/'),
- ),
- $column_name),
- $data_type,
- $this->renderAttr(
- $column->getColumnType(),
- $column->hasIssue($type_issue)),
- $this->renderAttr(
- $column->getNullable()
- ? pht('Yes')
- : pht('No'),
- $column->hasIssue($nullable_issue)),
- $this->renderAttr(
- $column->getCharacterSet(),
- $column->hasIssue($charset_issue)),
- $this->renderAttr(
- $column->getCollation(),
- $column->hasIssue($collation_issue)),
- );
- }
-
- $table_view = id(new AphrontTableView($rows))
- ->setHeaders(
- array(
- null,
- pht('Column'),
- pht('Data Type'),
- pht('Column Type'),
- pht('Nullable'),
- pht('Character Set'),
- pht('Collation'),
- ))
- ->setColumnClasses(
- array(
- null,
- 'wide pri',
- null,
- null,
- null,
- null
- ));
-
- $key_rows = array();
- foreach ($table->getKeys() as $key_name => $key) {
- $expect_key = null;
- if ($expect_table) {
- $expect_key = $expect_table->getKey($key_name);
- }
-
- $status = $key->getStatus();
-
- $size = 0;
- foreach ($key->getColumnNames() as $column_name) {
- $column = $table->getColumn($column_name);
- if (!$column) {
- $size = 0;
- break;
- }
- $size += $column->getKeyByteLength();
- }
-
- $size_formatted = null;
- if ($size) {
- $size_formatted = $this->renderAttr(
- $size,
- ($size > self::MAX_INNODB_KEY_LENGTH));
- }
-
- $key_rows[] = array(
- $this->renderIcon($status),
- phutil_tag(
- 'a',
- array(
- 'href' => $this->getApplicationURI(
- 'database/'.
- $database_name.'/'.
- $table_name.'/'.
- 'key/'.
- $key_name.'/'),
- ),
- $key_name),
- implode(', ', $key->getColumnNames()),
- $size_formatted,
- );
- }
-
- $keys_view = id(new AphrontTableView($key_rows))
- ->setHeaders(
- array(
- null,
- pht('Key'),
- pht('Columns'),
- pht('Size'),
- ))
- ->setColumnClasses(
- array(
- null,
- 'wide pri',
- null,
- null,
- ));
-
- $title = pht('Database Status: %s.%s', $database_name, $table_name);
-
- if ($actual_table) {
- $actual_collation = $actual_table->getCollation();
- } else {
- $actual_collation = null;
- }
-
- if ($expect_table) {
- $expect_collation = $expect_table->getCollation();
- } else {
- $expect_collation = null;
- }
-
- $properties = $this->buildProperties(
- array(
- array(
- pht('Collation'),
- $actual_collation,
- ),
- array(
- pht('Expected Collation'),
- $expect_collation,
- ),
- ),
- $table->getIssues());
-
- $box = id(new PHUIObjectBoxView())
- ->setHeaderText($title)
- ->addPropertyList($properties)
- ->appendChild($table_view)
- ->appendChild($keys_view);
-
- return $this->buildResponse($title, $box);
+ return $query;
}
- private function renderColumn(
- PhabricatorConfigServerSchema $comp,
- PhabricatorConfigServerSchema $expect,
- PhabricatorConfigServerSchema $actual,
- $database_name,
- $table_name,
- $column_name) {
-
- $database = $comp->getDatabase($database_name);
- if (!$database) {
- return new Aphront404Response();
- }
-
- $table = $database->getTable($table_name);
- if (!$table) {
- return new Aphront404Response();
- }
-
- $column = $table->getColumn($column_name);
- if (!$column) {
- return new Aphront404Response();
- }
-
- $actual_database = $actual->getDatabase($database_name);
- $actual_table = null;
- $actual_column = null;
- if ($actual_database) {
- $actual_table = $actual_database->getTable($table_name);
- if ($actual_table) {
- $actual_column = $actual_table->getColumn($column_name);
- }
- }
-
- $expect_database = $expect->getDatabase($database_name);
- $expect_table = null;
- $expect_column = null;
- if ($expect_database) {
- $expect_table = $expect_database->getTable($table_name);
- if ($expect_table) {
- $expect_column = $expect_table->getColumn($column_name);
- }
- }
-
- if ($actual_column) {
- $actual_coltype = $actual_column->getColumnType();
- $actual_charset = $actual_column->getCharacterSet();
- $actual_collation = $actual_column->getCollation();
- $actual_nullable = $actual_column->getNullable();
- } else {
- $actual_coltype = null;
- $actual_charset = null;
- $actual_collation = null;
- $actual_nullable = null;
- }
-
- if ($expect_column) {
- $data_type = $expect_column->getDataType();
- $expect_coltype = $expect_column->getColumnType();
- $expect_charset = $expect_column->getCharacterSet();
- $expect_collation = $expect_column->getCollation();
- $expect_nullable = $expect_column->getNullable();
- } else {
- $data_type = null;
- $expect_coltype = null;
- $expect_charset = null;
- $expect_collation = null;
- $expect_nullable = null;
- }
-
-
- $title = pht(
- 'Database Status: %s.%s.%s',
- $database_name,
- $table_name,
- $column_name);
-
- $properties = $this->buildProperties(
- array(
- array(
- pht('Data Type'),
- $data_type,
- ),
- array(
- pht('Column Type'),
- $actual_coltype,
- ),
- array(
- pht('Expected Column Type'),
- $expect_coltype,
- ),
- array(
- pht('Character Set'),
- $actual_charset,
- ),
- array(
- pht('Expected Character Set'),
- $expect_charset,
- ),
- array(
- pht('Collation'),
- $actual_collation,
- ),
- array(
- pht('Expected Collation'),
- $expect_collation,
- ),
- array(
- pht('Nullable'),
- $this->getNullableString($actual_nullable),
- ),
- array(
- pht('Expected Nullable'),
- $this->getNullableString($expect_nullable),
- ),
- ),
- $column->getIssues());
-
- $box = id(new PHUIObjectBoxView())
- ->setHeaderText($title)
- ->addPropertyList($properties);
-
- return $this->buildResponse($title, $box);
- }
-
- private function renderKey(
- PhabricatorConfigServerSchema $comp,
- PhabricatorConfigServerSchema $expect,
- PhabricatorConfigServerSchema $actual,
- $database_name,
- $table_name,
- $key_name) {
-
- $database = $comp->getDatabase($database_name);
- if (!$database) {
- return new Aphront404Response();
- }
-
- $table = $database->getTable($table_name);
- if (!$table) {
- return new Aphront404Response();
- }
-
- $key = $table->getKey($key_name);
- if (!$key) {
- return new Aphront404Response();
- }
-
- $actual_database = $actual->getDatabase($database_name);
- $actual_table = null;
- $actual_key = null;
- if ($actual_database) {
- $actual_table = $actual_database->getTable($table_name);
- if ($actual_table) {
- $actual_key = $actual_table->getKey($key_name);
- }
- }
-
- $expect_database = $expect->getDatabase($database_name);
- $expect_table = null;
- $expect_key = null;
- if ($expect_database) {
- $expect_table = $expect_database->getTable($table_name);
- if ($expect_table) {
- $expect_key = $expect_table->getKey($key_name);
- }
- }
-
- if ($actual_key) {
- $actual_columns = $actual_key->getColumnNames();
- } else {
- $actual_columns = array();
- }
-
- if ($expect_key) {
- $expect_columns = $expect_key->getColumnNames();
- } else {
- $expect_columns = array();
- }
-
- $title = pht(
- 'Database Status: %s.%s (%s)',
- $database_name,
- $table_name,
- $key_name);
-
- $properties = $this->buildProperties(
- array(
- array(
- pht('Columns'),
- implode(', ', $actual_columns),
- ),
- array(
- pht('Expected Columns'),
- implode(', ', $expect_columns),
- ),
- ),
- $key->getIssues());
-
- $box = id(new PHUIObjectBoxView())
- ->setHeaderText($title)
- ->addPropertyList($properties);
-
- return $this->buildResponse($title, $box);
- }
-
- private function renderIcon($status) {
+ protected function renderIcon($status) {
switch ($status) {
case PhabricatorConfigStorageSchema::STATUS_OKAY:
$icon = 'fa-check-circle green';
@@ -704,7 +44,7 @@
->setIconFont($icon);
}
- private function renderAttr($attr, $issue) {
+ protected function renderAttr($attr, $issue) {
if ($issue) {
return phutil_tag(
'span',
@@ -717,56 +57,7 @@
}
}
- private function buildProperties(array $properties, array $issues) {
- $view = id(new PHUIPropertyListView())
- ->setUser($this->getRequest()->getUser());
-
- foreach ($properties as $property) {
- list($key, $value) = $property;
- $view->addProperty($key, $value);
- }
-
- $status_view = new PHUIStatusListView();
- if (!$issues) {
- $status_view->addItem(
- id(new PHUIStatusItemView())
- ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
- ->setTarget(pht('No Schema Issues')));
- } else {
- foreach ($issues as $issue) {
- $note = PhabricatorConfigStorageSchema::getIssueDescription($issue);
-
- $status = PhabricatorConfigStorageSchema::getIssueStatus($issue);
- switch ($status) {
- case PhabricatorConfigStorageSchema::STATUS_NOTE:
- $icon = PHUIStatusItemView::ICON_INFO;
- $color = 'blue';
- break;
- case PhabricatorConfigStorageSchema::STATUS_WARN:
- $icon = PHUIStatusItemView::ICON_WARNING;
- $color = 'yellow';
- break;
- case PhabricatorConfigStorageSchema::STATUS_FAIL:
- default:
- $icon = PHUIStatusItemView::ICON_REJECT;
- $color = 'red';
- break;
- }
-
- $item = id(new PHUIStatusItemView())
- ->setTarget(PhabricatorConfigStorageSchema::getIssueName($issue))
- ->setIcon($icon, $color)
- ->setNote($note);
-
- $status_view->addItem($item);
- }
- }
- $view->addProperty(pht('Schema Status'), $status_view);
-
- return $view;
- }
-
- private function getNullableString($value) {
+ protected function renderBoolean($value) {
if ($value === null) {
return '';
} else if ($value === true) {
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php b/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php
@@ -0,0 +1,167 @@
+<?php
+
+final class PhabricatorConfigDatabaseIssueController
+ extends PhabricatorConfigDatabaseController {
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $query = $this->buildSchemaQuery();
+
+ $actual = $query->loadActualSchema();
+ $expect = $query->loadExpectedSchema();
+ $comp = $query->buildComparisonSchema($expect, $actual);
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(pht('Database Issues'));
+
+ // Collect all open issues.
+ $issues = array();
+ foreach ($comp->getDatabases() as $database_name => $database) {
+ foreach ($database->getLocalIssues() as $issue) {
+ $issues[] = array(
+ $database_name,
+ null,
+ null,
+ null,
+ $issue);
+ }
+ foreach ($database->getTables() as $table_name => $table) {
+ foreach ($table->getLocalIssues() as $issue) {
+ $issues[] = array(
+ $database_name,
+ $table_name,
+ null,
+ null,
+ $issue);
+ }
+ foreach ($table->getColumns() as $column_name => $column) {
+ foreach ($column->getLocalIssues() as $issue) {
+ $issues[] = array(
+ $database_name,
+ $table_name,
+ 'column',
+ $column_name,
+ $issue);
+ }
+ }
+ foreach ($table->getKeys() as $key_name => $key) {
+ foreach ($key->getLocalIssues() as $issue) {
+ $issues[] = array(
+ $database_name,
+ $table_name,
+ 'key',
+ $key_name,
+ $issue);
+ }
+ }
+ }
+ }
+
+
+ // Sort all open issues so that the most severe issues appear first.
+ $order = array();
+ $counts = array();
+ foreach ($issues as $key => $issue) {
+ $const = $issue[4];
+ $status = PhabricatorConfigStorageSchema::getIssueStatus($const);
+ $severity = PhabricatorConfigStorageSchema::getStatusSeverity($status);
+ $order[$key] = sprintf(
+ '~%d~%s%s%s',
+ 9 - $severity,
+ $issue[0],
+ $issue[1],
+ $issue[3]);
+
+ if (empty($counts[$status])) {
+ $counts[$status] = 0;
+ }
+
+ $counts[$status]++;
+ }
+ asort($order);
+ $issues = array_select_keys($issues, array_keys($order));
+
+
+ // Render the issues.
+ $rows = array();
+ foreach ($issues as $issue) {
+ $const = $issue[4];
+
+ $rows[] = array(
+ $this->renderIcon(
+ PhabricatorConfigStorageSchema::getIssueStatus($const)),
+ $issue[0],
+ $issue[1],
+ $issue[2],
+ $issue[3],
+ PhabricatorConfigStorageSchema::getIssueDescription($const),
+ );
+ }
+
+ $table = id(new AphrontTableView($rows))
+ ->setHeaders(
+ array(
+ null,
+ pht('Database'),
+ pht('Table'),
+ pht('Type'),
+ pht('Column/Key'),
+ pht('Issue'),
+ ))
+ ->setColumnClasses(
+ array(
+ null,
+ null,
+ null,
+ null,
+ null,
+ 'wide',
+ ));
+
+ $errors = array();
+
+ $errors[] = pht(
+ 'IMPORTANT: This feature is in development and the information below '.
+ 'is not accurate! Ignore it for now. See T1191.');
+
+ if (isset($counts[PhabricatorConfigStorageSchema::STATUS_FAIL])) {
+ $errors[] = pht(
+ 'Detected %s serious issue(s) with the schemata.',
+ new PhutilNumber($counts[PhabricatorConfigStorageSchema::STATUS_FAIL]));
+ }
+
+ if (isset($counts[PhabricatorConfigStorageSchema::STATUS_WARN])) {
+ $errors[] = pht(
+ 'Detected %s warning(s) with the schemata.',
+ new PhutilNumber($counts[PhabricatorConfigStorageSchema::STATUS_WARN]));
+ }
+
+ if (isset($counts[PhabricatorConfigStorageSchema::STATUS_NOTE])) {
+ $errors[] = pht(
+ 'Detected %s minor issue(s) with the scheamata.',
+ new PhutilNumber($counts[PhabricatorConfigStorageSchema::STATUS_NOTE]));
+ }
+
+ $table_box = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Database Issues'))
+ ->setFormErrors($errors)
+ ->appendChild($table);
+
+ $nav = $this->buildSideNavView();
+ $nav->selectFilter('dbissue/');
+ $nav->appendChild(
+ array(
+ $crumbs,
+ $table_box,
+ ));
+
+ return $this->buildApplicationPage(
+ $nav,
+ array(
+ 'title' => 'all',
+ ));
+ }
+
+}
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseController.php b/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php
copy from src/applications/config/controller/PhabricatorConfigDatabaseController.php
copy to src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php
--- a/src/applications/config/controller/PhabricatorConfigDatabaseController.php
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php
@@ -1,9 +1,7 @@
<?php
-final class PhabricatorConfigDatabaseController
- extends PhabricatorConfigController {
-
- const MAX_INNODB_KEY_LENGTH = 767;
+final class PhabricatorConfigDatabaseStatusController
+ extends PhabricatorConfigDatabaseController {
private $database;
private $table;
@@ -21,19 +19,7 @@
$request = $this->getRequest();
$viewer = $request->getUser();
- $conf = PhabricatorEnv::newObjectFromConfig(
- 'mysql.configuration-provider',
- array($dao = null, 'w'));
-
- $api = id(new PhabricatorStorageManagementAPI())
- ->setUser($conf->getUser())
- ->setHost($conf->getHost())
- ->setPort($conf->getPort())
- ->setNamespace(PhabricatorLiskDAO::getDefaultStorageNamespace())
- ->setPassword($conf->getPassword());
-
- $query = id(new PhabricatorConfigSchemaQuery())
- ->setAPI($api);
+ $query = $this->buildSchemaQuery();
$actual = $query->loadActualSchema();
$expect = $query->loadExpectedSchema();
@@ -293,6 +279,7 @@
$charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
$collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
$nullable_issue = PhabricatorConfigStorageSchema::ISSUE_NULLABLE;
+ $unique_issue = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
$database = $comp->getDatabase($database_name);
if (!$database) {
@@ -348,9 +335,7 @@
$column->getColumnType(),
$column->hasIssue($type_issue)),
$this->renderAttr(
- $column->getNullable()
- ? pht('Yes')
- : pht('No'),
+ $this->renderBoolean($column->getNullable()),
$column->hasIssue($nullable_issue)),
$this->renderAttr(
$column->getCharacterSet(),
@@ -422,6 +407,9 @@
),
$key_name),
implode(', ', $key->getColumnNames()),
+ $this->renderAttr(
+ $this->renderBoolean($key->getUnique()),
+ $key->hasIssue($unique_issue)),
$size_formatted,
);
}
@@ -432,6 +420,7 @@
null,
pht('Key'),
pht('Columns'),
+ pht('Unique'),
pht('Size'),
))
->setColumnClasses(
@@ -440,6 +429,7 @@
'wide pri',
null,
null,
+ null,
));
$title = pht('Database Status: %s.%s', $database_name, $table_name);
@@ -586,11 +576,11 @@
),
array(
pht('Nullable'),
- $this->getNullableString($actual_nullable),
+ $this->renderBoolean($actual_nullable),
),
array(
pht('Expected Nullable'),
- $this->getNullableString($expect_nullable),
+ $this->renderBoolean($expect_nullable),
),
),
$column->getIssues());
@@ -647,14 +637,18 @@
if ($actual_key) {
$actual_columns = $actual_key->getColumnNames();
+ $actual_unique = $actual_key->getUnique();
} else {
$actual_columns = array();
+ $actual_unique = null;
}
if ($expect_key) {
$expect_columns = $expect_key->getColumnNames();
+ $expect_unique = $expect_key->getUnique();
} else {
$expect_columns = array();
+ $expect_unique = null;
}
$title = pht(
@@ -666,6 +660,14 @@
$properties = $this->buildProperties(
array(
array(
+ pht('Unique'),
+ $this->renderBoolean($actual_unique),
+ ),
+ array(
+ pht('Expected Unique'),
+ $this->renderBoolean($expect_unique),
+ ),
+ array(
pht('Columns'),
implode(', ', $actual_columns),
),
@@ -683,40 +685,6 @@
return $this->buildResponse($title, $box);
}
- private function renderIcon($status) {
- switch ($status) {
- case PhabricatorConfigStorageSchema::STATUS_OKAY:
- $icon = 'fa-check-circle green';
- break;
- case PhabricatorConfigStorageSchema::STATUS_NOTE:
- $icon = 'fa-info-circle blue';
- break;
- case PhabricatorConfigStorageSchema::STATUS_WARN:
- $icon = 'fa-exclamation-circle yellow';
- break;
- case PhabricatorConfigStorageSchema::STATUS_FAIL:
- default:
- $icon = 'fa-times-circle red';
- break;
- }
-
- return id(new PHUIIconView())
- ->setIconFont($icon);
- }
-
- private function renderAttr($attr, $issue) {
- if ($issue) {
- return phutil_tag(
- 'span',
- array(
- 'style' => 'color: #aa0000;',
- ),
- $attr);
- } else {
- return $attr;
- }
- }
-
private function buildProperties(array $properties, array $issues) {
$view = id(new PHUIPropertyListView())
->setUser($this->getRequest()->getUser());
@@ -766,14 +734,4 @@
return $view;
}
- private function getNullableString($value) {
- if ($value === null) {
- return '';
- } else if ($value === true) {
- return pht('Yes');
- } else {
- return pht('No');
- }
- }
-
}
diff --git a/src/applications/config/schema/PhabricatorConfigKeySchema.php b/src/applications/config/schema/PhabricatorConfigKeySchema.php
--- a/src/applications/config/schema/PhabricatorConfigKeySchema.php
+++ b/src/applications/config/schema/PhabricatorConfigKeySchema.php
@@ -4,6 +4,16 @@
extends PhabricatorConfigStorageSchema {
private $columnNames;
+ private $unique;
+
+ public function setUnique($unique) {
+ $this->unique = $unique;
+ return $this;
+ }
+
+ public function getUnique() {
+ return $this->unique;
+ }
public function setColumnNames(array $column_names) {
$this->columnNames = array_values($column_names);
@@ -26,6 +36,10 @@
$issues[] = self::ISSUE_KEYCOLUMNS;
}
+ if ($this->getUnique() !== $expect->getUnique()) {
+ $issues[] = self::ISSUE_UNIQUE;
+ }
+
return $issues;
}
diff --git a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
--- a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
+++ b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
@@ -69,18 +69,9 @@
$column_info = array();
}
- if ($sql) {
- $key_info = queryfx_all(
- $conn,
- 'SELECT CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME,
- ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT
- FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
- WHERE (%Q)',
- '('.implode(') OR (', $sql).')');
- $key_info = igroup($key_info, 'TABLE_SCHEMA');
- } else {
- $key_info = array();
- }
+ // NOTE: Tables like KEY_COLUMN_USAGE and TABLE_CONSTRAINTS only contain
+ // primary, unique, and foreign keys, so we can't use them here. We pull
+ // indexes later on using SHOW INDEXES.
$server_schema = new PhabricatorConfigServerSchema();
@@ -95,8 +86,6 @@
$database_column_info = idx($column_info, $database_name, array());
$database_column_info = igroup($database_column_info, 'TABLE_NAME');
- $database_key_info = idx($key_info, $database_name, array());
- $database_key_info = igroup($database_key_info, 'TABLE_NAME');
foreach ($database_tables as $table) {
$table_name = $table['TABLE_NAME'];
@@ -117,13 +106,19 @@
$table_schema->addColumn($column_schema);
}
- $key_parts = idx($database_key_info, $table_name, array());
- $keys = igroup($key_parts, 'CONSTRAINT_NAME');
+ $key_parts = queryfx_all(
+ $conn,
+ 'SHOW INDEXES FROM %T.%T',
+ $database_name,
+ $table_name);
+ $keys = igroup($key_parts, 'Key_name');
foreach ($keys as $key_name => $key_pieces) {
- $key_pieces = isort($key_pieces, 'ORDINAL_POSITION');
+ $key_pieces = isort($key_pieces, 'Seq_in_index');
+ $head = head($key_pieces);
$key_schema = id(new PhabricatorConfigKeySchema())
->setName($key_name)
- ->setColumnNames(ipull($key_pieces, 'COLUMN_NAME'));
+ ->setColumnNames(ipull($key_pieces, 'Column_name'))
+ ->setUnique(!$head['Non_unique']);
$table_schema->addKey($key_schema);
}
diff --git a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php
--- a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php
+++ b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php
@@ -100,6 +100,8 @@
$key = $this->newKey($key_name)
->setColumnNames(idx($key_spec, 'columns', array()));
+ $key->setUnique((bool)idx($key_spec, 'unique'));
+
$table->addKey($key);
}
diff --git a/src/applications/config/schema/PhabricatorConfigStorageSchema.php b/src/applications/config/schema/PhabricatorConfigStorageSchema.php
--- a/src/applications/config/schema/PhabricatorConfigStorageSchema.php
+++ b/src/applications/config/schema/PhabricatorConfigStorageSchema.php
@@ -9,6 +9,7 @@
const ISSUE_COLUMNTYPE = 'columntype';
const ISSUE_NULLABLE = 'nullable';
const ISSUE_KEYCOLUMNS = 'keycolumns';
+ const ISSUE_UNIQUE = 'unique';
const ISSUE_SUBNOTE = 'subnote';
const ISSUE_SUBWARN = 'subwarn';
const ISSUE_SUBFAIL = 'subfail';
@@ -72,6 +73,10 @@
return $issues;
}
+ public function getLocalIssues() {
+ return $this->issues;
+ }
+
public function hasIssue($issue) {
return (bool)idx($this->getIssues(), $issue);
}
@@ -109,6 +114,8 @@
return pht('Wrong Nullable Setting');
case self::ISSUE_KEYCOLUMNS:
return pht('Key on Wrong Columns');
+ case self::ISSUE_UNIQUE:
+ return pht('Key has Wrong Uniqueness');
case self::ISSUE_SUBNOTE:
return pht('Subschemata Have Notices');
case self::ISSUE_SUBWARN:
@@ -136,6 +143,8 @@
return pht('This schema has the wrong nullable setting.');
case self::ISSUE_KEYCOLUMNS:
return pht('This schema is on the wrong columns.');
+ case self::ISSUE_UNIQUE:
+ return pht('This key has the wrong uniqueness setting.');
case self::ISSUE_SUBNOTE:
return pht('Subschemata have setup notices.');
case self::ISSUE_SUBWARN:
@@ -157,6 +166,7 @@
case self::ISSUE_SUBWARN:
case self::ISSUE_KEYCOLUMNS:
case self::ISSUE_NULLABLE:
+ case self::ISSUE_UNIQUE:
return self::STATUS_WARN;
case self::ISSUE_SUBNOTE:
case self::ISSUE_CHARSET:
diff --git a/src/infrastructure/storage/lisk/LiskDAO.php b/src/infrastructure/storage/lisk/LiskDAO.php
--- a/src/infrastructure/storage/lisk/LiskDAO.php
+++ b/src/infrastructure/storage/lisk/LiskDAO.php
@@ -1810,11 +1810,13 @@
case 'id':
$default_map['PRIMARY'] = array(
'columns' => array('id'),
+ 'unique' => true,
);
break;
case 'phid':
$default_map['key_phid'] = array(
'columns' => array('phid'),
+ 'unique' => true,
);
break;
}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 9, 3:17 AM (3 d, 1 h ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/tc/gb/b2yoy7e5ywzecfc5
Default Alt Text
D10525.id25295.diff (39 KB)

Event Timeline