forked from GNUsocial/gnu-social
MySQL schema: fix dropping unique indexes, add support for changing table properties back from old code.
This commit is contained in:
parent
a923ef9719
commit
4aa6c4e49f
@ -245,6 +245,9 @@ class MysqlSchema extends Schema
|
|||||||
* @param string $name
|
* @param string $name
|
||||||
* @param array $def
|
* @param array $def
|
||||||
* @return string;
|
* @return string;
|
||||||
|
*
|
||||||
|
* @fixme ENGINE may need to be set differently in some cases,
|
||||||
|
* such as to support fulltext index.
|
||||||
*/
|
*/
|
||||||
function endCreateTable($name, array $def)
|
function endCreateTable($name, array $def)
|
||||||
{
|
{
|
||||||
@ -267,153 +270,36 @@ class MysqlSchema extends Schema
|
|||||||
return "{$tableName}_{$columnName}_idx";
|
return "{$tableName}_{$columnName}_idx";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that a table exists with the given
|
* MySQL doesn't take 'DROP CONSTRAINT', need to treat unique keys as
|
||||||
* name and the given column definitions.
|
* if they were indexes here.
|
||||||
*
|
*
|
||||||
* If the table does not yet exist, it will
|
* @param array $phrase
|
||||||
* create the table. If it does exist, it will
|
* @param <type> $keyName MySQL
|
||||||
* alter the table to match the column definitions.
|
|
||||||
*
|
|
||||||
* @param string $tableName name of the table
|
|
||||||
* @param array $columns array of ColumnDef
|
|
||||||
* objects for the table
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
*/
|
||||||
|
function appendAlterDropUnique(array &$phrase, $keyName)
|
||||||
public function oldensureTable($tableName, $columns)
|
|
||||||
{
|
{
|
||||||
// XXX: DB engine portability -> toilet
|
$phrase[] = 'DROP INDEX ' . $keyName;
|
||||||
|
|
||||||
try {
|
|
||||||
$td = $this->getTableDef($tableName);
|
|
||||||
} catch (SchemaTableMissingException $e) {
|
|
||||||
return $this->createTable($tableName, $columns);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cur = $this->_names($td->columns);
|
|
||||||
$new = $this->_names($columns);
|
|
||||||
|
|
||||||
$dropIndex = array();
|
|
||||||
$toadd = array_diff($new, $cur);
|
|
||||||
$todrop = array_diff($cur, $new);
|
|
||||||
$same = array_intersect($new, $cur);
|
|
||||||
$tomod = array();
|
|
||||||
$addIndex = array();
|
|
||||||
$tableProps = array();
|
|
||||||
|
|
||||||
foreach ($same as $m) {
|
|
||||||
$curCol = $this->_byName($td->columns, $m);
|
|
||||||
$newCol = $this->_byName($columns, $m);
|
|
||||||
|
|
||||||
if (!$newCol->equals($curCol)) {
|
|
||||||
$tomod[] = $newCol->name;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Earlier versions may have accidentally left tables at default
|
|
||||||
// charsets which might be latin1 or other freakish things.
|
|
||||||
if ($this->_isString($curCol)) {
|
|
||||||
if ($curCol->charset != 'utf8') {
|
|
||||||
$tomod[] = $newCol->name;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find any indices we have to change...
|
|
||||||
$curIdx = $this->_indexList($td->columns);
|
|
||||||
$newIdx = $this->_indexList($columns);
|
|
||||||
|
|
||||||
if ($curIdx['primary'] != $newIdx['primary']) {
|
|
||||||
if ($curIdx['primary']) {
|
|
||||||
$dropIndex[] = 'drop primary key';
|
|
||||||
}
|
|
||||||
if ($newIdx['primary']) {
|
|
||||||
$keys = implode(',', $newIdx['primary']);
|
|
||||||
$addIndex[] = "add constraint primary key ($keys)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$dropUnique = array_diff($curIdx['uniques'], $newIdx['uniques']);
|
|
||||||
$addUnique = array_diff($newIdx['uniques'], $curIdx['uniques']);
|
|
||||||
foreach ($dropUnique as $columnName) {
|
|
||||||
$dropIndex[] = 'drop key ' . $this->_uniqueKey($tableName, $columnName);
|
|
||||||
}
|
|
||||||
foreach ($addUnique as $columnName) {
|
|
||||||
$addIndex[] = 'add constraint unique key ' . $this->_uniqueKey($tableName, $columnName) . " ($columnName)";;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dropMultiple = array_diff($curIdx['indices'], $newIdx['indices']);
|
|
||||||
$addMultiple = array_diff($newIdx['indices'], $curIdx['indices']);
|
|
||||||
foreach ($dropMultiple as $columnName) {
|
|
||||||
$dropIndex[] = 'drop key ' . $this->_key($tableName, $columnName);
|
|
||||||
}
|
|
||||||
foreach ($addMultiple as $columnName) {
|
|
||||||
$addIndex[] = 'add key ' . $this->_key($tableName, $columnName) . " ($columnName)";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw some table metadata onto the ALTER TABLE if we have a mismatch
|
||||||
|
* in expected type, collation.
|
||||||
|
*/
|
||||||
|
function appendAlterExtras(array &$phrase, $tableName)
|
||||||
|
{
|
||||||
// Check for table properties: make sure we're using a sane
|
// Check for table properties: make sure we're using a sane
|
||||||
// engine type and charset/collation.
|
// engine type and charset/collation.
|
||||||
// @fixme make the default engine configurable?
|
// @fixme make the default engine configurable?
|
||||||
$oldProps = $this->getTableProperties($tableName, array('ENGINE', 'TABLE_COLLATION'));
|
$oldProps = $this->getTableProperties($tableName, array('ENGINE', 'TABLE_COLLATION'));
|
||||||
if (strtolower($oldProps['ENGINE']) != 'innodb') {
|
if (strtolower($oldProps['ENGINE']) != 'innodb') {
|
||||||
$tableProps['ENGINE'] = 'InnoDB';
|
$phrase[] = 'ENGINE=InnoDB';
|
||||||
}
|
}
|
||||||
if (strtolower($oldProps['TABLE_COLLATION']) != 'utf8_bin') {
|
if (strtolower($oldProps['TABLE_COLLATION']) != 'utf8_bin') {
|
||||||
$tableProps['DEFAULT CHARSET'] = 'utf8';
|
$phrase[] = 'DEFAULT CHARSET=utf8';
|
||||||
$tableProps['COLLATE'] = 'utf8_bin';
|
$phrase[] = 'COLLATE=utf8_bin';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($dropIndex) + count($toadd) + count($todrop) + count($tomod) + count($addIndex) + count($tableProps) == 0) {
|
|
||||||
// nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For efficiency, we want this all in one
|
|
||||||
// query, instead of using our methods.
|
|
||||||
|
|
||||||
$phrase = array();
|
|
||||||
|
|
||||||
foreach ($dropIndex as $indexSql) {
|
|
||||||
$phrase[] = $indexSql;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($toadd as $columnName) {
|
|
||||||
$cd = $this->_byName($columns, $columnName);
|
|
||||||
|
|
||||||
$phrase[] = 'ADD COLUMN ' . $this->_columnSql($cd);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($todrop as $columnName) {
|
|
||||||
$phrase[] = 'DROP COLUMN ' . $columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($tomod as $columnName) {
|
|
||||||
$cd = $this->_byName($columns, $columnName);
|
|
||||||
|
|
||||||
$phrase[] = 'MODIFY COLUMN ' . $this->_columnSql($cd);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($addIndex as $indexSql) {
|
|
||||||
$phrase[] = $indexSql;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($tableProps as $key => $val) {
|
|
||||||
$phrase[] = "$key=$val";
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql = 'ALTER TABLE ' . $tableName . ' ' . implode(', ', $phrase);
|
|
||||||
|
|
||||||
common_log(LOG_DEBUG, __METHOD__ . ': ' . $sql);
|
|
||||||
$res = $this->conn->query($sql);
|
|
||||||
|
|
||||||
if (PEAR::isError($res)) {
|
|
||||||
throw new Exception($res->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -493,12 +493,6 @@ class Schema
|
|||||||
$uniques = $this->diffArrays($old, $def, 'unique keys');
|
$uniques = $this->diffArrays($old, $def, 'unique keys');
|
||||||
$indexes = $this->diffArrays($old, $def, 'indexes');
|
$indexes = $this->diffArrays($old, $def, 'indexes');
|
||||||
|
|
||||||
$total = $fields['count'] + $uniques['count'] + $indexes['count'];
|
|
||||||
if ($total == 0) {
|
|
||||||
// nothing to do
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// For efficiency, we want this all in one
|
// For efficiency, we want this all in one
|
||||||
// query, instead of using our methods.
|
// query, instead of using our methods.
|
||||||
|
|
||||||
@ -527,6 +521,13 @@ class Schema
|
|||||||
$this->appendAlterAddUnique($phrase, $keyName, $def['unique keys'][$keyName]);
|
$this->appendAlterAddUnique($phrase, $keyName, $def['unique keys'][$keyName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->appendAlterExtras($phrase, $tableName);
|
||||||
|
|
||||||
|
if (count($phrase) == 0) {
|
||||||
|
// nothing to do
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
$sql = 'ALTER TABLE ' . $tableName . ' ' . implode(",\n", $phrase);
|
$sql = 'ALTER TABLE ' . $tableName . ' ' . implode(",\n", $phrase);
|
||||||
|
|
||||||
return array($sql);
|
return array($sql);
|
||||||
@ -625,6 +626,11 @@ class Schema
|
|||||||
$phrase[] = 'DROP CONSTRAINT ' . $keyName;
|
$phrase[] = 'DROP CONSTRAINT ' . $keyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function appendAlterExtras(array &$phrase, $tableName)
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quote a db/table/column identifier if necessary.
|
* Quote a db/table/column identifier if necessary.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user