~ubuntu-branches/ubuntu/vivid/phabricator/vivid-proposed

« back to all changes in this revision

Viewing changes to phabricator/src/applications/config/schema/PhabricatorConfigSchemaSpec.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2014-10-23 20:49:26 UTC
  • Revision ID: package-import@ubuntu.com-20141023204926-ar20vnfjqwxysrce
Tags: upstream-0~git20141023
ImportĀ upstreamĀ versionĀ 0~git20141023

Show diffs side-by-side

added added

removed removed

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