Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
181 / 181 |
|
100.00% |
12 / 12 |
CRAP | |
100.00% |
1 / 1 |
Column | |
100.00% |
181 / 181 |
|
100.00% |
12 / 12 |
109 | |
100.00% |
1 / 1 |
getColumnSchema | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getValidDataType | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
6 | |||
getValidMysqlDataType | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
7 | |||
getValidPgsqlDataType | |
100.00% |
28 / 28 |
|
100.00% |
1 / 1 |
15 | |||
getValidSqliteDataType | |
100.00% |
33 / 33 |
|
100.00% |
1 / 1 |
20 | |||
getValidSqlsrvDataType | |
100.00% |
29 / 29 |
|
100.00% |
1 / 1 |
16 | |||
formatColumn | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
6 | |||
formatMysqlColumn | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
10 | |||
formatPgsqlColumn | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
7 | |||
formatSqliteColumn | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
formatSqlsrvColumn | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
9 | |||
formatCommonParameters | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
8 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Db\Sql\Schema\Formatter; |
15 | |
16 | use Pop\Db\Sql; |
17 | |
18 | /** |
19 | * Schema column formatter class |
20 | * |
21 | * @category Pop |
22 | * @package Pop\Db |
23 | * @author Nick Sagona, III <dev@nolainteractive.com> |
24 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
25 | * @license http://www.popphp.org/license New BSD License |
26 | * @version 6.5.0 |
27 | */ |
28 | class Column extends AbstractFormatter |
29 | { |
30 | |
31 | /** |
32 | * Get column schema |
33 | * |
34 | * @param string $dbType |
35 | * @param string $name |
36 | * @param array $column |
37 | * @param string $table |
38 | * @throws Exception |
39 | * @return string |
40 | */ |
41 | public static function getColumnSchema(string $dbType, string $name, array $column, string $table): string |
42 | { |
43 | if (!isset($column['type'])) { |
44 | throw new Exception('Error: The column type was not set.'); |
45 | } |
46 | |
47 | $dataType = self::getValidDataType($dbType, $column['type']); |
48 | |
49 | return self::formatColumn($dbType, $name, $dataType, $column, $table); |
50 | } |
51 | |
52 | /** |
53 | * Get valid column data type |
54 | * |
55 | * @param string $dbType |
56 | * @param string $type |
57 | * @return string |
58 | */ |
59 | public static function getValidDataType(string $dbType, string $type): string |
60 | { |
61 | switch ($dbType) { |
62 | case Sql::MYSQL: |
63 | return self::getValidMysqlDataType($type); |
64 | break; |
65 | case Sql::PGSQL: |
66 | return self::getValidPgsqlDataType($type); |
67 | break; |
68 | case Sql::SQLITE: |
69 | return self::getValidSqliteDataType($type); |
70 | break; |
71 | case Sql::SQLSRV: |
72 | return self::getValidSqlsrvDataType($type); |
73 | break; |
74 | default: |
75 | return $type; |
76 | } |
77 | } |
78 | |
79 | /** |
80 | * Get valid MySQL data type |
81 | * |
82 | * @param string $type |
83 | * @return string |
84 | */ |
85 | public static function getValidMysqlDataType(string $type): string |
86 | { |
87 | $type = strtoupper($type); |
88 | |
89 | switch ($type) { |
90 | case 'INTEGER': |
91 | $type = 'INT'; |
92 | break; |
93 | case 'SERIAL': |
94 | $type = 'INT'; |
95 | break; |
96 | case 'BIGSERIAL': |
97 | $type = 'BIGINT'; |
98 | break; |
99 | case 'SMALLSERIAL': |
100 | $type = 'SMALLINT'; |
101 | break; |
102 | case 'CHARACTER VARYING': |
103 | $type = 'VARCHAR'; |
104 | break; |
105 | case 'CHARACTER': |
106 | $type = 'CHAR'; |
107 | break; |
108 | } |
109 | |
110 | return $type; |
111 | } |
112 | |
113 | /** |
114 | * Get valid PostgreSQL data type |
115 | * |
116 | * @param string $type |
117 | * @return string |
118 | */ |
119 | public static function getValidPgsqlDataType(string $type): string |
120 | { |
121 | $type = strtoupper($type); |
122 | |
123 | switch ($type) { |
124 | case 'INT': |
125 | case 'MEDIUMINT': |
126 | $type = 'INTEGER'; |
127 | break; |
128 | case 'TINYINT': |
129 | $type = 'SMALLINT'; |
130 | break; |
131 | break; |
132 | case 'DOUBLE': |
133 | $type = 'DOUBLE PRECISION'; |
134 | break; |
135 | case 'BLOB': |
136 | case 'TINYBLOB': |
137 | case 'MEDIUMBLOB': |
138 | case 'LONGBLOB': |
139 | case 'TINYTEXT': |
140 | case 'MEDIUMTEXT': |
141 | case 'LONGTEXT': |
142 | $type = 'TEXT'; |
143 | break; |
144 | case 'BINARY': |
145 | case 'VARBINARY': |
146 | $type = 'BYTEA'; |
147 | break; |
148 | case 'DATETIME': |
149 | $type = 'TIMESTAMP'; |
150 | break; |
151 | } |
152 | |
153 | return $type; |
154 | } |
155 | |
156 | /** |
157 | * Get valid SQLite data type |
158 | * |
159 | * @param string $type |
160 | * @return string |
161 | */ |
162 | public static function getValidSqliteDataType(string $type): string |
163 | { |
164 | $type = strtoupper($type); |
165 | |
166 | switch ($type) { |
167 | case 'INT': |
168 | case 'SMALLINT': |
169 | case 'TINYINT': |
170 | case 'MEDIUMINT': |
171 | case 'BIGINT': |
172 | case 'SERIAL': |
173 | case 'BIGSERIAL': |
174 | case 'SMALLSERIAL': |
175 | $type = 'INTEGER'; |
176 | break; |
177 | case 'FLOAT': |
178 | case 'DOUBLE': |
179 | case 'DOUBLE PRECISION': |
180 | $type = 'REAL'; |
181 | break; |
182 | case 'DECIMAL': |
183 | $type = 'NUMERIC'; |
184 | break; |
185 | case 'TINYBLOB': |
186 | case 'MEDIUMBLOB': |
187 | case 'LONGBLOB': |
188 | $type = 'BLOB'; |
189 | break; |
190 | case 'TINYTEXT': |
191 | case 'MEDIUMTEXT': |
192 | case 'LONGTEXT': |
193 | $type = 'TEXT'; |
194 | break; |
195 | case 'TIMESTAMP': |
196 | $type = 'DATETIME'; |
197 | break; |
198 | } |
199 | |
200 | return $type; |
201 | } |
202 | |
203 | /** |
204 | * Get valid SQL Server data type |
205 | * |
206 | * @param string $type |
207 | * @return string |
208 | */ |
209 | public static function getValidSqlsrvDataType(string $type): string |
210 | { |
211 | $type = strtoupper($type); |
212 | |
213 | switch ($type) { |
214 | case 'INTEGER': |
215 | case 'MEDIUMINT': |
216 | case 'SERIAL': |
217 | $type = 'INT'; |
218 | break; |
219 | case 'BIGSERIAL': |
220 | $type = 'BIGINT'; |
221 | break; |
222 | case 'SMALLSERIAL': |
223 | $type = 'SMALLINT'; |
224 | break; |
225 | case 'DOUBLE': |
226 | case 'DOUBLE PRECISION': |
227 | $type = 'REAL'; |
228 | break; |
229 | case 'BLOB': |
230 | case 'TINYBLOB': |
231 | case 'MEDIUMBLOB': |
232 | case 'LONGBLOB': |
233 | case 'TINYTEXT': |
234 | case 'MEDIUMTEXT': |
235 | case 'LONGTEXT': |
236 | $type = 'TEXT'; |
237 | break; |
238 | case 'TIMESTAMP': |
239 | $type = 'DATETIME'; |
240 | break; |
241 | } |
242 | |
243 | return $type; |
244 | } |
245 | |
246 | /** |
247 | * Format column |
248 | * |
249 | * @param string $dbType |
250 | * @param string $name |
251 | * @param string $dataType |
252 | * @param array $column |
253 | * @param string $table |
254 | * @throws Exception |
255 | * @return string |
256 | */ |
257 | public static function formatColumn(string $dbType, string $name, string $dataType, array $column, string $table): string |
258 | { |
259 | switch ($dbType) { |
260 | case Sql::MYSQL: |
261 | return self::formatMysqlColumn($name, $dataType, $column); |
262 | break; |
263 | case Sql::PGSQL: |
264 | return self::formatPgsqlColumn($name, $dataType, $column, $table); |
265 | break; |
266 | case Sql::SQLITE: |
267 | return self::formatSqliteColumn($name, $dataType, $column); |
268 | break; |
269 | case Sql::SQLSRV: |
270 | return self::formatSqlsrvColumn($name, $dataType, $column); |
271 | break; |
272 | default: |
273 | throw new Exception("Error: The database type '" . $dbType . "' is not supported."); |
274 | } |
275 | } |
276 | |
277 | /** |
278 | * Format MySQL column |
279 | * |
280 | * @param string $name |
281 | * @param string $dataType |
282 | * @param array $column |
283 | * @return string |
284 | */ |
285 | public static function formatMysqlColumn(string $name, string $dataType, array $column): string |
286 | { |
287 | $columnString = $name . ' ' . $dataType; |
288 | $sizeAllowed = ['DECIMAL', 'NUMERIC', 'FLOAT', 'DOUBLE', 'REAL', 'DOUBLE PRECISION']; |
289 | |
290 | if (!empty($column['size']) && |
291 | ((stripos($dataType, 'INT') !== false) || (stripos($dataType, 'CHAR') !== false) || |
292 | (stripos($dataType, 'BINARY') !== false) || in_array($dataType, $sizeAllowed))) { |
293 | $columnString .= '(' . $column['size']; |
294 | $columnString .= (!empty($column['precision']) && in_array($dataType, $sizeAllowed)) ? |
295 | ', ' . $column['precision'] . ')' : ')'; |
296 | } |
297 | |
298 | if ($column['unsigned'] !== false) { |
299 | $columnString .= ' UNSIGNED'; |
300 | } |
301 | |
302 | $columnString = self::formatCommonParameters($columnString, $column); |
303 | |
304 | if ($column['increment'] !== false) { |
305 | $columnString .= ' AUTO_INCREMENT'; |
306 | } |
307 | |
308 | return $columnString; |
309 | } |
310 | |
311 | /** |
312 | * Format PostgreSQL column |
313 | * |
314 | * @param string $name |
315 | * @param string $dataType |
316 | * @param array $column |
317 | * @param string $table |
318 | * @return string |
319 | */ |
320 | public static function formatPgsqlColumn(string $name, string $dataType, array $column, string $table): string |
321 | { |
322 | $columnString = $name . ' ' . $dataType; |
323 | $unquotedName = self::unquoteId($name); |
324 | $sizeAllowed = ['DECIMAL', 'NUMERIC', 'FLOAT', 'REAL']; |
325 | $precisionAllowed = ['DECIMAL', 'NUMERIC']; |
326 | |
327 | if (!empty($column['size']) && |
328 | ((stripos($dataType, 'CHAR') !== false) || in_array($dataType, $sizeAllowed))) { |
329 | $columnString .= '(' . $column['size']; |
330 | $columnString .= (!empty($column['precision']) && in_array($dataType, $precisionAllowed)) ? |
331 | ', ' . $column['precision'] . ')' : ')'; |
332 | } |
333 | |
334 | $columnString = self::formatCommonParameters($columnString, $column); |
335 | |
336 | if ($column['increment'] !== false) { |
337 | $columnString .= ' DEFAULT nextval(\'' . $table . '_' . $unquotedName . '_seq\')'; |
338 | } |
339 | |
340 | return $columnString; |
341 | } |
342 | |
343 | /** |
344 | * Format SQLite column |
345 | * |
346 | * @param string $name |
347 | * @param string $dataType |
348 | * @param array $column |
349 | * @return string |
350 | */ |
351 | public static function formatSqliteColumn(string $name, string $dataType, array $column): string |
352 | { |
353 | $columnString = $name . ' ' . $dataType; |
354 | $columnString = self::formatCommonParameters($columnString, $column); |
355 | |
356 | if ($column['increment'] !== false) { |
357 | $columnString .= (($column['primary'] !== false) ? ' PRIMARY KEY' : null) . ' AUTOINCREMENT'; |
358 | } |
359 | |
360 | return $columnString; |
361 | } |
362 | |
363 | /** |
364 | * Format SQL Server column |
365 | * |
366 | * @param string $name |
367 | * @param string $dataType |
368 | * @param array $column |
369 | * @return string |
370 | */ |
371 | public static function formatSqlsrvColumn(string $name, string $dataType, array $column): string |
372 | { |
373 | $columnString = $name . ' ' . $dataType; |
374 | $sizeAllowed = ['DECIMAL', 'NUMERIC', 'FLOAT', 'REAL']; |
375 | $precisionAllowed = ['DECIMAL', 'NUMERIC']; |
376 | |
377 | if (!empty($column['size']) && |
378 | ((stripos($dataType, 'CHAR') !== false) || (stripos($dataType, 'BINARY') !== false) || |
379 | in_array($dataType, $sizeAllowed))) { |
380 | $columnString .= '(' . $column['size']; |
381 | $columnString .= (!empty($column['precision']) && in_array($dataType, $precisionAllowed)) ? |
382 | ', ' . $column['precision'] . ')' : ')'; |
383 | } |
384 | |
385 | $columnString = self::formatCommonParameters($columnString, $column); |
386 | |
387 | if ($column['increment'] !== false) { |
388 | $columnString .= (($column['primary'] !== false) ? ' PRIMARY KEY' : null) . |
389 | ' IDENTITY(' . (int)$column['increment'] . ', 1)'; |
390 | } |
391 | |
392 | return $columnString; |
393 | } |
394 | |
395 | /** |
396 | * Format common column parameters |
397 | * |
398 | * @param string $columnString |
399 | * @param array $column |
400 | * @return string |
401 | */ |
402 | public static function formatCommonParameters(string $columnString, array $column): string |
403 | { |
404 | if (count($column['attributes']) > 0) { |
405 | $columnString .= ' ' . implode(' ', $column['attributes']); |
406 | } |
407 | |
408 | if (($column['nullable'] === false) || (strtoupper((string)$column['default']) == 'NOT NULL')) { |
409 | $columnString .= ' NOT NULL'; |
410 | } |
411 | |
412 | if (($column['default'] === null) && ($column['nullable'] === true)) { |
413 | $columnString .= ' DEFAULT NULL'; |
414 | } else if (strtoupper((string)$column['default']) == 'NULL') { |
415 | $columnString .= ' DEFAULT NULL'; |
416 | } else if ($column['default'] !== null) { |
417 | $columnString .= " DEFAULT '" . $column['default'] . "'"; |
418 | } |
419 | |
420 | return $columnString; |
421 | } |
422 | |
423 | } |