[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/config/schema/ -> PhabricatorConfigSchemaSpec.php (source)

   1  <?php
   2  
   3  abstract class PhabricatorConfigSchemaSpec extends Phobject {
   4  
   5    private $server;
   6    private $utf8Charset;
   7    private $utf8BinaryCollation;
   8    private $utf8SortingCollation;
   9  
  10    const DATATYPE_UNKNOWN = '<unknown>';
  11  
  12    public function setUTF8SortingCollation($utf8_sorting_collation) {
  13      $this->utf8SortingCollation = $utf8_sorting_collation;
  14      return $this;
  15    }
  16  
  17    public function getUTF8SortingCollation() {
  18      return $this->utf8SortingCollation;
  19    }
  20  
  21    public function setUTF8BinaryCollation($utf8_binary_collation) {
  22      $this->utf8BinaryCollation = $utf8_binary_collation;
  23      return $this;
  24    }
  25  
  26    public function getUTF8BinaryCollation() {
  27      return $this->utf8BinaryCollation;
  28    }
  29  
  30    public function setUTF8Charset($utf8_charset) {
  31      $this->utf8Charset = $utf8_charset;
  32      return $this;
  33    }
  34  
  35    public function getUTF8Charset() {
  36      return $this->utf8Charset;
  37    }
  38  
  39    public function setServer(PhabricatorConfigServerSchema $server) {
  40      $this->server = $server;
  41      return $this;
  42    }
  43  
  44    public function getServer() {
  45      return $this->server;
  46    }
  47  
  48    abstract public function buildSchemata();
  49  
  50    protected function buildLiskObjectSchema(PhabricatorLiskDAO $object) {
  51      $this->buildRawSchema(
  52        $object->getApplicationName(),
  53        $object->getTableName(),
  54        $object->getSchemaColumns(),
  55        $object->getSchemaKeys());
  56    }
  57  
  58    protected function buildRawSchema(
  59      $database_name,
  60      $table_name,
  61      array $columns,
  62      array $keys) {
  63      $database = $this->getDatabase($database_name);
  64  
  65      $table = $this->newTable($table_name);
  66  
  67      foreach ($columns as $name => $type) {
  68        if ($type === null) {
  69          continue;
  70        }
  71  
  72        $details = $this->getDetailsForDataType($type);
  73        list($column_type, $charset, $collation, $nullable, $auto) = $details;
  74  
  75        $column = $this->newColumn($name)
  76          ->setDataType($type)
  77          ->setColumnType($column_type)
  78          ->setCharacterSet($charset)
  79          ->setCollation($collation)
  80          ->setNullable($nullable)
  81          ->setAutoIncrement($auto);
  82  
  83        $table->addColumn($column);
  84      }
  85  
  86      foreach ($keys as $key_name => $key_spec) {
  87        if ($key_spec === null) {
  88          // This is a subclass removing a key which Lisk expects.
  89          continue;
  90        }
  91  
  92        $key = $this->newKey($key_name)
  93          ->setColumnNames(idx($key_spec, 'columns', array()));
  94  
  95        $key->setUnique((bool)idx($key_spec, 'unique'));
  96        $key->setIndexType(idx($key_spec, 'type', 'BTREE'));
  97  
  98        $table->addKey($key);
  99      }
 100  
 101      $database->addTable($table);
 102    }
 103  
 104    protected function buildEdgeSchemata(PhabricatorLiskDAO $object) {
 105      $this->buildRawSchema(
 106        $object->getApplicationName(),
 107        PhabricatorEdgeConfig::TABLE_NAME_EDGE,
 108        array(
 109          'src' => 'phid',
 110          'type' => 'uint32',
 111          'dst' => 'phid',
 112          'dateCreated' => 'epoch',
 113          'seq' => 'uint32',
 114          'dataID' => 'id?',
 115        ),
 116        array(
 117          'PRIMARY' => array(
 118            'columns' => array('src', 'type', 'dst'),
 119            'unique' => true,
 120          ),
 121          'src' => array(
 122            'columns' => array('src', 'type', 'dateCreated', 'seq'),
 123          ),
 124          'key_dst' => array(
 125            'columns' => array('dst', 'type', 'src'),
 126            'unique' => true,
 127          ),
 128        ));
 129  
 130      $this->buildRawSchema(
 131        $object->getApplicationName(),
 132        PhabricatorEdgeConfig::TABLE_NAME_EDGEDATA,
 133        array(
 134          'id' => 'auto',
 135          'data' => 'text',
 136        ),
 137        array(
 138          'PRIMARY' => array(
 139            'columns' => array('id'),
 140            'unique' => true,
 141          ),
 142        ));
 143    }
 144  
 145    protected function getDatabase($name) {
 146      $server = $this->getServer();
 147  
 148      $database = $server->getDatabase($this->getNamespacedDatabase($name));
 149      if (!$database) {
 150        $database = $this->newDatabase($name);
 151        $server->addDatabase($database);
 152      }
 153  
 154      return $database;
 155    }
 156  
 157    protected function newDatabase($name) {
 158      return id(new PhabricatorConfigDatabaseSchema())
 159        ->setName($this->getNamespacedDatabase($name))
 160        ->setCharacterSet($this->getUTF8Charset())
 161        ->setCollation($this->getUTF8BinaryCollation());
 162    }
 163  
 164    protected function getNamespacedDatabase($name) {
 165      $namespace = PhabricatorLiskDAO::getStorageNamespace();
 166      return $namespace.'_'.$name;
 167    }
 168  
 169    protected function newTable($name) {
 170      return id(new PhabricatorConfigTableSchema())
 171        ->setName($name)
 172        ->setCollation($this->getUTF8BinaryCollation());
 173    }
 174  
 175    protected function newColumn($name) {
 176      return id(new PhabricatorConfigColumnSchema())
 177        ->setName($name);
 178    }
 179  
 180    protected function newKey($name) {
 181      return id(new PhabricatorConfigKeySchema())
 182        ->setName($name);
 183    }
 184  
 185    private function getDetailsForDataType($data_type) {
 186      $column_type = null;
 187      $charset = null;
 188      $collation = null;
 189      $auto = false;
 190  
 191      // If the type ends with "?", make the column nullable.
 192      $nullable = false;
 193      if (preg_match('/\?$/', $data_type)) {
 194        $nullable = true;
 195        $data_type = substr($data_type, 0, -1);
 196      }
 197  
 198      // NOTE: MySQL allows fragments like "VARCHAR(32) CHARACTER SET binary",
 199      // but just interprets that to mean "VARBINARY(32)". The fragment is
 200      // totally disallowed in a MODIFY statement vs a CREATE TABLE statement.
 201  
 202      $is_binary = ($this->getUTF8Charset() == 'binary');
 203      $matches = null;
 204      if (preg_match('/^(fulltext|sort|text)(\d+)?\z/', $data_type, $matches)) {
 205  
 206        // Limit the permitted column lengths under the theory that it would
 207        // be nice to eventually reduce this to a small set of standard lengths.
 208  
 209        static $valid_types = array(
 210          'text255' => true,
 211          'text160' => true,
 212          'text128' => true,
 213          'text80' => true,
 214          'text64' => true,
 215          'text40' => true,
 216          'text32' => true,
 217          'text20' => true,
 218          'text16' => true,
 219          'text12' => true,
 220          'text8' => true,
 221          'text4' => true,
 222          'text' => true,
 223          'sort255' => true,
 224          'sort128' => true,
 225          'sort64' => true,
 226          'sort32' => true,
 227          'sort' => true,
 228          'fulltext' => true,
 229        );
 230  
 231        if (empty($valid_types[$data_type])) {
 232          throw new Exception(pht('Unknown column type "%s"!', $data_type));
 233        }
 234  
 235        $type = $matches[1];
 236        $size = idx($matches, 2);
 237  
 238        if ($is_binary) {
 239          if ($size) {
 240            $column_type = 'varbinary('.$size.')';
 241          } else {
 242            $column_type = 'longblob';
 243          }
 244  
 245          // MySQL (at least, under MyISAM) refuses to create a FULLTEXT index
 246          // on a LONGBLOB column. We'd also lose case insensitivity in search.
 247          // Force this column to utf8 collation. This will truncate results with
 248          // 4-byte UTF characters in their text, but work reasonably in the
 249          // majority of cases.
 250  
 251          if ($type == 'fulltext') {
 252            $column_type = 'longtext';
 253            $charset = 'utf8';
 254            $collation = 'utf8_general_ci';
 255          }
 256        } else {
 257          if ($size) {
 258            $column_type = 'varchar('.$size.')';
 259          } else {
 260            $column_type = 'longtext';
 261          }
 262          $charset = $this->getUTF8Charset();
 263          if ($type == 'sort' || $type == 'fulltext') {
 264            $collation = $this->getUTF8SortingCollation();
 265          } else {
 266            $collation = $this->getUTF8BinaryCollation();
 267          }
 268        }
 269      } else {
 270        switch ($data_type) {
 271          case 'auto':
 272            $column_type = 'int(10) unsigned';
 273            $auto = true;
 274            break;
 275          case 'auto64':
 276            $column_type = 'bigint(20) unsigned';
 277            $auto = true;
 278            break;
 279          case 'id':
 280          case 'epoch':
 281          case 'uint32':
 282            $column_type = 'int(10) unsigned';
 283            break;
 284          case 'sint32':
 285            $column_type = 'int(10)';
 286            break;
 287          case 'id64':
 288          case 'uint64':
 289            $column_type = 'bigint(20) unsigned';
 290            break;
 291          case 'sint64':
 292            $column_type = 'bigint(20)';
 293            break;
 294          case 'phid':
 295          case 'policy';
 296            $column_type = 'varbinary(64)';
 297            break;
 298          case 'bytes64':
 299            $column_type = 'binary(64)';
 300            break;
 301          case 'bytes40':
 302            $column_type = 'binary(40)';
 303            break;
 304          case 'bytes32':
 305            $column_type = 'binary(32)';
 306            break;
 307          case 'bytes20':
 308            $column_type = 'binary(20)';
 309            break;
 310          case 'bytes12':
 311            $column_type = 'binary(12)';
 312            break;
 313          case 'bytes4':
 314            $column_type = 'binary(4)';
 315            break;
 316          case 'bytes':
 317            $column_type = 'longblob';
 318            break;
 319          case 'bool':
 320            $column_type = 'tinyint(1)';
 321            break;
 322          case 'double':
 323            $column_type = 'double';
 324            break;
 325          case 'date':
 326            $column_type = 'date';
 327            break;
 328          default:
 329            $column_type = self::DATATYPE_UNKNOWN;
 330            $charset = self::DATATYPE_UNKNOWN;
 331            $collation = self::DATATYPE_UNKNOWN;
 332            break;
 333        }
 334      }
 335  
 336      return array($column_type, $charset, $collation, $nullable, $auto);
 337    }
 338  
 339  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1