@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorConfigColumnSchema
4 extends PhabricatorConfigStorageSchema {
5
6 private $characterSet;
7 private $collation;
8 private $columnType;
9 private $dataType;
10 private $nullable;
11 private $autoIncrement;
12
13 public function setAutoIncrement($auto_increment) {
14 $this->autoIncrement = $auto_increment;
15 return $this;
16 }
17
18 public function getAutoIncrement() {
19 return $this->autoIncrement;
20 }
21
22 public function setNullable($nullable) {
23 $this->nullable = $nullable;
24 return $this;
25 }
26
27 public function getNullable() {
28 return $this->nullable;
29 }
30
31 public function setColumnType($column_type) {
32 $this->columnType = $column_type;
33 return $this;
34 }
35
36 public function getColumnType() {
37 return $this->columnType;
38 }
39
40 protected function getSubschemata() {
41 return array();
42 }
43
44 public function setDataType($data_type) {
45 $this->dataType = $data_type;
46 return $this;
47 }
48
49 public function getDataType() {
50 return $this->dataType;
51 }
52
53 public function setCollation($collation) {
54 $this->collation = $collation;
55 return $this;
56 }
57
58 public function getCollation() {
59 return $this->collation;
60 }
61
62 public function setCharacterSet($character_set) {
63 $this->characterSet = $character_set;
64 return $this;
65 }
66
67 public function getCharacterSet() {
68 return $this->characterSet;
69 }
70
71 public function hasSameColumnTypeAs(PhabricatorConfigColumnSchema $other) {
72 $u_type = $this->getColumnType();
73 $v_type = $other->getColumnType();
74
75 if ($u_type === $v_type) {
76 return true;
77 }
78
79 // See T13536. Display widths for integers were deprecated in MySQL 8.0.17
80 // and removed from some display contexts in or around 8.0.19. Older
81 // MySQL versions will report "int(10)"; newer versions will report "int".
82 // Accept these as equivalent.
83
84 static $map = array(
85 'int(10) unsigned' => 'int unsigned',
86 'int(10)' => 'int',
87 'bigint(20) unsigned' => 'bigint unsigned',
88 'bigint(20)' => 'bigint',
89 );
90
91 if (isset($map[$u_type])) {
92 $u_type = $map[$u_type];
93 }
94
95 if (isset($map[$v_type])) {
96 $v_type = $map[$v_type];
97 }
98
99 return ($u_type === $v_type);
100 }
101
102 public function getKeyByteLength($prefix = null) {
103 $type = $this->getColumnType();
104
105 $matches = null;
106 if (preg_match('/^(?:var)?char\((\d+)\)$/', $type, $matches)) {
107 // For utf8mb4, each character requires 4 bytes.
108 $size = (int)$matches[1];
109 if ($prefix && $prefix < $size) {
110 $size = $prefix;
111 }
112 return $size * 4;
113 }
114
115 $matches = null;
116 if (preg_match('/^(?:var)?binary\((\d+)\)$/', $type, $matches)) {
117 // binary()/varbinary() store fixed-length binary data, so their size
118 // is always the column size.
119 $size = (int)$matches[1];
120 if ($prefix && $prefix < $size) {
121 $size = $prefix;
122 }
123 return $size;
124 }
125
126 // The "long..." types are arbitrarily long, so just use a big number to
127 // get the point across. In practice, these should always index only a
128 // prefix.
129 if ($type == 'longtext') {
130 $size = (1 << 16);
131 if ($prefix && $prefix < $size) {
132 $size = $prefix;
133 }
134 return $size * 4;
135 }
136
137 if ($type == 'longblob') {
138 $size = (1 << 16);
139 if ($prefix && $prefix < $size) {
140 $size = $prefix;
141 }
142 return $size * 1;
143 }
144
145 switch ($type) {
146 case 'int(10) unsigned':
147 return 4;
148 }
149
150 // TODO: Build this out to catch overlong indexes.
151
152 return 0;
153 }
154
155 protected function compareToSimilarSchema(
156 PhabricatorConfigStorageSchema $expect) {
157
158 $issues = array();
159
160 $type_unknown = PhabricatorConfigSchemaSpec::DATATYPE_UNKNOWN;
161 if ($expect->getColumnType() == $type_unknown) {
162 $issues[] = self::ISSUE_UNKNOWN;
163 } else {
164 if ($this->getCharacterSet() != $expect->getCharacterSet()) {
165 $issues[] = self::ISSUE_CHARSET;
166 }
167
168 if ($this->getCollation() != $expect->getCollation()) {
169 $issues[] = self::ISSUE_COLLATION;
170 }
171
172 if (!$this->hasSameColumnTypeAs($expect)) {
173 $issues[] = self::ISSUE_COLUMNTYPE;
174 }
175
176 if ($this->getNullable() !== $expect->getNullable()) {
177 $issues[] = self::ISSUE_NULLABLE;
178 }
179
180 if ($this->getAutoIncrement() !== $expect->getAutoIncrement()) {
181 $issues[] = self::ISSUE_AUTOINCREMENT;
182 }
183 }
184
185 return $issues;
186 }
187
188 public function newEmptyClone() {
189 $clone = clone $this;
190 return $clone;
191 }
192
193}