1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 19:40:55 +01:00

Correct column mutations for old versions of MySQL

Summary:
Ref T1191. Although I fixed some of the mutations earlier (in D10598), I missed the column mutations under old versions of MySQL. In particular, this isn't valid:

  - `ALTER TABLE ... MODIFY columnName VARCHAR(64) COLLATE binary`

Issue the permitted version of this instead, which is:

  - `ALTER TABLE ... MODIFY columnName VARBINARY(64)`

Also fixed an issue where a clean schema had the wrong nullability for a column in the draft table. Force it to the expected nullability.

The other trick here is around the one column with a FULLTEXT index on it, which needs a little massaging.

Test Plan:
  - Forced my local install to return `false` for utf8mb4 support.
  - Did a clean adjust into `binary` columns.
  - Poked around, added emoji to things.
  - Reverted the fake check and did a clean adjust into `utf8mb4` columns.
  - Emoji survived.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: fabe, epriestley

Maniphest Tasks: T1191

Differential Revision: https://secure.phabricator.com/D10627
This commit is contained in:
epriestley 2014-10-02 14:44:22 -07:00
parent e333017c3e
commit d67b7f0f47
3 changed files with 134 additions and 153 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_draft.draft
MODIFY metadata LONGTEXT NOT NULL;

View file

@ -197,159 +197,138 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
// but just interprets that to mean "VARBINARY(32)". The fragment is // but just interprets that to mean "VARBINARY(32)". The fragment is
// 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) { $is_binary = ($this->getUTF8Charset() == 'binary');
case 'auto': $matches = null;
$column_type = 'int(10) unsigned'; if (preg_match('/^(fulltext|sort|text)(\d+)?\z/', $data_type, $matches)) {
$auto = true;
break; // Limit the permitted column lengths under the theory that it would
case 'auto64': // be nice to eventually reduce this to a small set of standard lengths.
$column_type = 'bigint(20) unsigned';
$auto = true; static $valid_types = array(
break; 'text255' => true,
case 'id': 'text160' => true,
case 'epoch': 'text128' => true,
case 'uint32': 'text80' => true,
$column_type = 'int(10) unsigned'; 'text64' => true,
break; 'text40' => true,
case 'sint32': 'text32' => true,
$column_type = 'int(10)'; 'text20' => true,
break; 'text16' => true,
case 'id64': 'text12' => true,
case 'uint64': 'text8' => true,
$column_type = 'bigint(20) unsigned'; 'text4' => true,
break; 'text' => true,
case 'sint64': 'sort255' => true,
$column_type = 'bigint(20)'; 'sort128' => true,
break; 'sort64' => true,
case 'phid': 'sort32' => true,
case 'policy'; 'sort' => true,
$column_type = 'varbinary(64)'; 'fulltext' => true,
break; );
case 'bytes64':
$column_type = 'binary(64)'; if (empty($valid_types[$data_type])) {
break; throw new Exception(pht('Unknown column type "%s"!', $data_type));
case 'bytes40': }
$column_type = 'binary(40)';
break; $type = $matches[1];
case 'bytes32': $size = idx($matches, 2);
$column_type = 'binary(32)';
break; if ($is_binary) {
case 'bytes20': if ($size) {
$column_type = 'binary(20)'; $column_type = 'varbinary('.$size.')';
break; } else {
case 'bytes12': $column_type = 'longblob';
$column_type = 'binary(12)'; }
break;
case 'bytes4': // MySQL (at least, under MyISAM) refuses to create a FULLTEXT index
$column_type = 'binary(4)'; // on a LONGBLOB column. We'd also lose case insensitivity in search.
break; // Force this column to utf8 collation. This will truncate results with
case 'bytes': // 4-byte UTF characters in their text, but work reasonably in the
$column_type = 'longblob'; // majority of cases.
break;
case 'sort255': if ($type == 'fulltext') {
$column_type = 'varchar(255)'; $column_type = 'longtext';
$charset = 'utf8';
$collation = 'utf8_general_ci';
}
} else {
if ($size) {
$column_type = 'varchar('.$size.')';
} else {
$column_type = 'longtext';
}
$charset = $this->getUTF8Charset(); $charset = $this->getUTF8Charset();
$collation = $this->getUTF8SortingCollation(); if ($type == 'sort' || $type == 'fulltext') {
break; $collation = $this->getUTF8SortingCollation();
case 'sort128': } else {
$column_type = 'varchar(128)'; $collation = $this->getUTF8BinaryCollation();
$charset = $this->getUTF8Charset(); }
$collation = $this->getUTF8SortingCollation(); }
break; } else {
case 'sort64': switch ($data_type) {
$column_type = 'varchar(64)'; case 'auto':
$charset = $this->getUTF8Charset(); $column_type = 'int(10) unsigned';
$collation = $this->getUTF8SortingCollation(); $auto = true;
break; break;
case 'sort32': case 'auto64':
$column_type = 'varchar(32)'; $column_type = 'bigint(20) unsigned';
$charset = $this->getUTF8Charset(); $auto = true;
$collation = $this->getUTF8SortingCollation(); break;
break; case 'id':
case 'sort': case 'epoch':
$column_type = 'longtext'; case 'uint32':
$charset = $this->getUTF8Charset(); $column_type = 'int(10) unsigned';
$collation = $this->getUTF8SortingCollation(); break;
break; case 'sint32':
case 'text255': $column_type = 'int(10)';
$column_type = 'varchar(255)'; break;
$charset = $this->getUTF8Charset(); case 'id64':
$collation = $this->getUTF8BinaryCollation(); case 'uint64':
break; $column_type = 'bigint(20) unsigned';
case 'text160': break;
$column_type = 'varchar(160)'; case 'sint64':
$charset = $this->getUTF8Charset(); $column_type = 'bigint(20)';
$collation = $this->getUTF8BinaryCollation(); break;
break; case 'phid':
case 'text128': case 'policy';
$column_type = 'varchar(128)'; $column_type = 'varbinary(64)';
$charset = $this->getUTF8Charset(); break;
$collation = $this->getUTF8BinaryCollation(); case 'bytes64':
break; $column_type = 'binary(64)';
case 'text80': break;
$column_type = 'varchar(80)'; case 'bytes40':
$charset = $this->getUTF8Charset(); $column_type = 'binary(40)';
$collation = $this->getUTF8BinaryCollation(); break;
break; case 'bytes32':
case 'text64': $column_type = 'binary(32)';
$column_type = 'varchar(64)'; break;
$charset = $this->getUTF8Charset(); case 'bytes20':
$collation = $this->getUTF8BinaryCollation(); $column_type = 'binary(20)';
break; break;
case 'text40': case 'bytes12':
$column_type = 'varchar(40)'; $column_type = 'binary(12)';
$charset = $this->getUTF8Charset(); break;
$collation = $this->getUTF8BinaryCollation(); case 'bytes4':
break; $column_type = 'binary(4)';
case 'text32': break;
$column_type = 'varchar(32)'; case 'bytes':
$charset = $this->getUTF8Charset(); $column_type = 'longblob';
$collation = $this->getUTF8BinaryCollation(); break;
break; case 'bool':
case 'text20': $column_type = 'tinyint(1)';
$column_type = 'varchar(20)'; break;
$charset = $this->getUTF8Charset(); case 'double':
$collation = $this->getUTF8BinaryCollation(); $column_type = 'double';
break; break;
case 'text16': case 'date':
$column_type = 'varchar(16)'; $column_type = 'date';
$charset = $this->getUTF8Charset(); break;
$collation = $this->getUTF8BinaryCollation(); default:
break; $column_type = pht('<unknown>');
case 'text12': $charset = pht('<unknown>');
$column_type = 'varchar(12)'; $collation = pht('<unknown>');
$charset = $this->getUTF8Charset(); break;
$collation = $this->getUTF8BinaryCollation(); }
break;
case 'text8':
$column_type = 'varchar(8)';
$charset = $this->getUTF8Charset();
$collation = $this->getUTF8BinaryCollation();
break;
case 'text4':
$column_type = 'varchar(4)';
$charset = $this->getUTF8Charset();
$collation = $this->getUTF8BinaryCollation();
break;
case 'text':
$column_type = 'longtext';
$charset = $this->getUTF8Charset();
$collation = $this->getUTF8BinaryCollation();
break;
case 'bool':
$column_type = 'tinyint(1)';
break;
case 'double':
$column_type = 'double';
break;
case 'date':
$column_type = 'date';
break;
default:
$column_type = pht('<unknown>');
$charset = pht('<unknown>');
$collation = pht('<unknown>');
break;
} }
return array($column_type, $charset, $collation, $nullable, $auto); return array($column_type, $charset, $collation, $nullable, $auto);

View file

@ -15,7 +15,7 @@ final class PhabricatorSearchDocumentField extends PhabricatorSearchDAO {
'phidType' => 'text4', 'phidType' => 'text4',
'field' => 'text4', 'field' => 'text4',
'auxPHID' => 'phid?', 'auxPHID' => 'phid?',
'corpus' => 'sort?', 'corpus' => 'fulltext?',
), ),
self::CONFIG_KEY_SCHEMA => array( self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null, 'key_phid' => null,