Do not dynamically call static methods
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / database / editor / MySQLDatabaseEditor.class.php
CommitLineData
11ade432
AE
1<?php
2namespace wcf\system\database\editor;
82a7de7f 3use wcf\system\Regex;
11ade432
AE
4
5/**
a17de04e
MS
6 * Database editor implementation for MySQL4.1 or higher.
7 *
11ade432 8 * @author Marcel Werk
7d739af0 9 * @copyright 2001-2016 WoltLab GmbH
11ade432 10 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
e71525e4 11 * @package WoltLabSuite\Core\System\Database\Editor
11ade432
AE
12 */
13class MySQLDatabaseEditor extends DatabaseEditor {
14 /**
0fcfe5f6 15 * @inheritDoc
11ade432
AE
16 */
17 public function getTableNames() {
058cbd6a 18 $existingTables = [];
11ade432
AE
19 $sql = "SHOW TABLES FROM `".$this->dbObj->getDatabaseName()."`";
20 $statement = $this->dbObj->prepareStatement($sql);
21 $statement->execute();
22 while ($row = $statement->fetchArray(\PDO::FETCH_NUM)) {
23 $existingTables[] = $row[0];
24 }
25 return $existingTables;
26 }
27
28 /**
0fcfe5f6 29 * @inheritDoc
11ade432
AE
30 */
31 public function getColumns($tableName) {
058cbd6a 32 $columns = [];
14d48464 33 $regex = new Regex('([a-z]+)\(([0-9]+)\)', Regex::CASE_INSENSITIVE);
77bb36ca 34
4f2c4eb8 35 $sql = "SHOW COLUMNS FROM `".$tableName."`";
11ade432
AE
36 $statement = $this->dbObj->prepareStatement($sql);
37 $statement->execute();
38 while ($row = $statement->fetchArray()) {
14d48464 39 $regex->match($row['Type']);
40 $typeMatches = $regex->getMatches();
77bb36ca 41
058cbd6a 42 $columns[] = ['name' => $row['Field'], 'data' => [
77bb36ca 43 'type' => ((empty($typeMatches)) ? $row['Type'] : $typeMatches[1]),
44 'length' => ((empty($typeMatches)) ? '' : $typeMatches[2]),
14d48464 45 'notNull' => (($row['Null'] == 'YES') ? false : true),
5fe135db
K
46 'key' => (($row['Key'] == 'PRI') ? 'PRIMARY' : (($row['Key'] == 'UNI') ? 'UNIQUE' : '')),
47 'default' => $row['Default'],
48 'autoIncrement' => ($row['Extra'] == 'auto_increment' ? true : false)
058cbd6a 49 ]];
ebe8e825 50 }
bf27dc91 51
9f959ced 52 return $columns;
11ade432
AE
53 }
54
55 /**
0fcfe5f6 56 * @inheritDoc
11ade432
AE
57 */
58 public function getIndices($tableName) {
058cbd6a 59 $indices = [];
4f2c4eb8 60 $sql = "SHOW INDEX FROM `".$tableName."`";
11ade432
AE
61 $statement = $this->dbObj->prepareStatement($sql);
62 $statement->execute();
63 while ($row = $statement->fetchArray()) {
9f959ced
MS
64 $indices[] = $row['Key_name'];
65 }
66
67 return $indices;
11ade432
AE
68 }
69
70 /**
0fcfe5f6 71 * @inheritDoc
11ade432 72 */
058cbd6a 73 public function createTable($tableName, $columns, $indices = []) {
11ade432
AE
74 $columnDefinition = $indexDefinition = '';
75
76 // build column definition
77 foreach ($columns as $column) {
78 if (!empty($columnDefinition)) $columnDefinition .= ',';
79 $columnDefinition .= $this->buildColumnDefinition($column['name'], $column['data']);
80 }
81
82 // build index definition
83 $hasFulltextIndex = false;
84 foreach ($indices as $index) {
85 if (!empty($indexDefinition)) $indexDefinition .= ',';
86 $indexDefinition .= $this->buildIndexDefinition($index['name'], $index['data']);
87 if ($index['data']['type'] == 'FULLTEXT') $hasFulltextIndex = true;
88 }
89
90 // create table
4f2c4eb8 91 $sql = "CREATE TABLE `".$tableName."` (
11ade432
AE
92 ".$columnDefinition."
93 ".(!empty($indexDefinition) ? ',' : '')."
94 ".$indexDefinition."
ac677ff6 95 ) ENGINE=".($hasFulltextIndex ? 'MyISAM' : 'InnoDB')." DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
11ade432
AE
96 $statement = $this->dbObj->prepareStatement($sql);
97 $statement->execute();
98 }
99
100 /**
0fcfe5f6 101 * @inheritDoc
11ade432
AE
102 */
103 public function dropTable($tableName) {
4f2c4eb8 104 $sql = "DROP TABLE IF EXISTS `".$tableName."`";
11ade432
AE
105 $statement = $this->dbObj->prepareStatement($sql);
106 $statement->execute();
107 }
108
109 /**
0fcfe5f6 110 * @inheritDoc
11ade432
AE
111 */
112 public function addColumn($tableName, $columnName, $columnData) {
4f2c4eb8 113 $sql = "ALTER TABLE `".$tableName."` ADD COLUMN ".$this->buildColumnDefinition($columnName, $columnData);
11ade432
AE
114 $statement = $this->dbObj->prepareStatement($sql);
115 $statement->execute();
116 }
117
118 /**
0fcfe5f6 119 * @inheritDoc
11ade432
AE
120 */
121 public function alterColumn($tableName, $oldColumnName, $newColumnName, $newColumnData) {
4f2c4eb8 122 $sql = "ALTER TABLE `".$tableName."` CHANGE COLUMN `".$oldColumnName."` ".$this->buildColumnDefinition($newColumnName, $newColumnData);
11ade432
AE
123 $statement = $this->dbObj->prepareStatement($sql);
124 $statement->execute();
125 }
126
127 /**
0fcfe5f6 128 * @inheritDoc
11ade432
AE
129 */
130 public function dropColumn($tableName, $columnName) {
4f2c4eb8 131 $sql = "ALTER TABLE `".$tableName."` DROP COLUMN `".$columnName."`";
11ade432
AE
132 $statement = $this->dbObj->prepareStatement($sql);
133 $statement->execute();
134 }
135
136 /**
0fcfe5f6 137 * @inheritDoc
11ade432
AE
138 */
139 public function addIndex($tableName, $indexName, $indexData) {
4f2c4eb8 140 $sql = "ALTER TABLE `".$tableName."` ADD ".$this->buildIndexDefinition($indexName, $indexData);
11ade432
AE
141 $statement = $this->dbObj->prepareStatement($sql);
142 $statement->execute();
143 }
144
145 /**
0fcfe5f6 146 * @inheritDoc
11ade432
AE
147 */
148 public function addForeignKey($tableName, $indexName, $indexData) {
4f2c4eb8 149 $sql = "ALTER TABLE `".$tableName."` ADD";
11ade432
AE
150
151 // add index name
96017679 152 if (!empty($indexName)) $sql .= " CONSTRAINT `".$indexName."`";
11ade432
AE
153
154 // add columns
4f2c4eb8 155 $sql .= " FOREIGN KEY (`".str_replace(',', '`,`', preg_replace('/\s+/', '', $indexData['columns']))."`)";
11ade432
AE
156
157 // add referenced table name
4f2c4eb8 158 $sql .= " REFERENCES `".$indexData['referencedTable']."`";
11ade432
AE
159
160 // add referenced columns
4f2c4eb8 161 $sql .= " (`".str_replace(',', '`,`', preg_replace('/\s+/', '', $indexData['referencedColumns']))."`)";
11ade432
AE
162
163 // add operation and action
164 if (!empty($indexData['operation'])) $sql .= " ON ".$indexData['operation']." ".$indexData['action'];
281ac362
TD
165 if (!empty($indexData['ON DELETE'])) $sql .= " ON DELETE ".$indexData['ON DELETE'];
166 if (!empty($indexData['ON UPDATE'])) $sql .= " ON UPDATE ".$indexData['ON UPDATE'];
11ade432
AE
167
168 $statement = $this->dbObj->prepareStatement($sql);
169 $statement->execute();
170 }
171
172 /**
0fcfe5f6 173 * @inheritDoc
11ade432
AE
174 */
175 public function dropIndex($tableName, $indexName) {
4f2c4eb8 176 $sql = "ALTER TABLE `".$tableName."` DROP INDEX `".$indexName."`";
11ade432
AE
177 $statement = $this->dbObj->prepareStatement($sql);
178 $statement->execute();
179 }
180
42a1e71f 181 /**
6b7d6653 182 * @inheritDoc
42a1e71f 183 */
184 public function dropPrimaryKey($tableName) {
185 $sql = "ALTER TABLE ".$tableName." DROP PRIMARY KEY";
186 $statement = $this->dbObj->prepareStatement($sql);
187 $statement->execute();
188 }
189
b6ae7d04 190 /**
0fcfe5f6 191 * @inheritDoc
b6ae7d04
MW
192 */
193 public function dropForeignKey($tableName, $indexName) {
4f2c4eb8 194 $sql = "ALTER TABLE `".$tableName."` DROP FOREIGN KEY `".$indexName."`";
b6ae7d04
MW
195 $statement = $this->dbObj->prepareStatement($sql);
196 $statement->execute();
197 }
198
11ade432
AE
199 /**
200 * Builds a column definition for execution in a create table or alter table statement.
201 *
202 * @param string $columnName
203 * @param array $columnData
71952a87 204 * @return string
11ade432
AE
205 */
206 protected function buildColumnDefinition($columnName, $columnData) {
207 // column name
4f2c4eb8 208 $definition = "`".$columnName."`";
11ade432
AE
209 // column type
210 $definition .= " ".$columnData['type'];
211 // column length and decimals
212 if (!empty($columnData['length'])) {
213 $definition .= "(".$columnData['length'].(!empty($columnData['decimals']) ? ",".$columnData['decimals'] : "").")";
214 }
215 // enum / set
216 if ($columnData['type'] == 'enum' && !empty($columnData['values'])) {
217 $definition .= "(".$columnData['values'].")";
218 }
219 // not null / null
220 if (!empty($columnData['notNull'])) $definition .= " NOT NULL";
221 // default
222 if (isset($columnData['default']) && $columnData['default'] !== '') $definition .= " DEFAULT ".$columnData['default'];
223 // auto_increment
224 if (!empty($columnData['autoIncrement'])) $definition .= " AUTO_INCREMENT";
225 // key
226 if (!empty($columnData['key'])) $definition .= " ".$columnData['key']." KEY";
227
228 return $definition;
229 }
230
231 /**
232 * Builds a index definition for execution in a create table or alter table statement.
233 *
234 * @param string $indexName
235 * @param array $indexData
71952a87 236 * @return string
11ade432
AE
237 */
238 protected function buildIndexDefinition($indexName, $indexData) {
11ade432
AE
239 // index type
240 if ($indexData['type'] == 'PRIMARY') $definition = "PRIMARY KEY";
241 else if ($indexData['type'] == 'UNIQUE') $definition = "UNIQUE KEY";
242 else if ($indexData['type'] == 'FULLTEXT') $definition = "FULLTEXT KEY";
243 else $definition = "KEY";
244
245 // index name
4f2c4eb8 246 if (!empty($indexName)) $definition .= " `".$indexName."`";
11ade432 247 // columns
4f2c4eb8 248 $definition .= " (`".str_replace(',', '`,`', preg_replace('/\s+/', '', $indexData['columns']))."`)";
11ade432
AE
249
250 return $definition;
251 }
252}