Total Complexity | 207 |
Total Lines | 1092 |
Duplicated Lines | 14.38 % |
Coverage | 92.49% |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like SqlitePlatform often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use SqlitePlatform, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
42 | class SqlitePlatform extends AbstractPlatform |
||
43 | { |
||
44 | /** |
||
45 | * {@inheritDoc} |
||
46 | */ |
||
47 | 1 | public function getRegexpExpression() |
|
48 | { |
||
49 | 1 | return 'REGEXP'; |
|
50 | } |
||
51 | |||
52 | /** |
||
53 | * {@inheritDoc} |
||
54 | */ |
||
55 | 2 | public function getGuidExpression() |
|
56 | { |
||
57 | return "HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-4' || " |
||
58 | . "SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || " |
||
59 | . "SUBSTR('89AB', 1 + (ABS(RANDOM()) % 4), 1) || " |
||
60 | 2 | . "SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))"; |
|
61 | } |
||
62 | |||
63 | /** |
||
64 | * {@inheritDoc} |
||
65 | */ |
||
66 | public function getNowExpression($type = 'timestamp') |
||
67 | { |
||
68 | switch ($type) { |
||
69 | case 'time': |
||
70 | return 'time(\'now\')'; |
||
71 | case 'date': |
||
72 | return 'date(\'now\')'; |
||
73 | case 'timestamp': |
||
74 | default: |
||
75 | return 'datetime(\'now\')'; |
||
76 | } |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * {@inheritDoc} |
||
81 | */ |
||
82 | 36 | public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) |
|
83 | { |
||
84 | 36 | $trimChar = ($char != false) ? (', ' . $char) : ''; |
|
85 | |||
86 | View Code Duplication | switch ($pos) { |
|
|
|||
87 | 36 | case self::TRIM_LEADING: |
|
88 | 9 | $trimFn = 'LTRIM'; |
|
89 | 9 | break; |
|
90 | |||
91 | 27 | case self::TRIM_TRAILING: |
|
92 | 9 | $trimFn = 'RTRIM'; |
|
93 | 9 | break; |
|
94 | |||
95 | default: |
||
96 | 18 | $trimFn = 'TRIM'; |
|
97 | } |
||
98 | |||
99 | 36 | return $trimFn . '(' . $str . $trimChar . ')'; |
|
100 | } |
||
101 | |||
102 | /** |
||
103 | * {@inheritDoc} |
||
104 | * |
||
105 | * SQLite only supports the 2 parameter variant of this function |
||
106 | */ |
||
107 | 1 | View Code Duplication | public function getSubstringExpression($value, $position, $length = null) |
108 | { |
||
109 | 1 | if ($length !== null) { |
|
110 | 1 | return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')'; |
|
111 | } |
||
112 | |||
113 | 1 | return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))'; |
|
114 | } |
||
115 | |||
116 | /** |
||
117 | * {@inheritDoc} |
||
118 | */ |
||
119 | 1 | View Code Duplication | public function getLocateExpression($str, $substr, $startPos = false) |
120 | { |
||
121 | 1 | if ($startPos == false) { |
|
122 | 1 | return 'LOCATE('.$str.', '.$substr.')'; |
|
123 | } |
||
124 | |||
125 | 1 | return 'LOCATE('.$str.', '.$substr.', '.$startPos.')'; |
|
126 | } |
||
127 | |||
128 | /** |
||
129 | * {@inheritdoc} |
||
130 | */ |
||
131 | 1 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
|
132 | { |
||
133 | switch ($unit) { |
||
134 | 1 | case self::DATE_INTERVAL_UNIT_SECOND: |
|
135 | 1 | case self::DATE_INTERVAL_UNIT_MINUTE: |
|
136 | 1 | case self::DATE_INTERVAL_UNIT_HOUR: |
|
137 | 1 | return "DATETIME(" . $date . ",'" . $operator . $interval . " " . $unit . "')"; |
|
138 | |||
139 | default: |
||
140 | View Code Duplication | switch ($unit) { |
|
141 | 1 | case self::DATE_INTERVAL_UNIT_WEEK: |
|
142 | 1 | $interval *= 7; |
|
143 | 1 | $unit = self::DATE_INTERVAL_UNIT_DAY; |
|
144 | 1 | break; |
|
145 | |||
146 | 1 | case self::DATE_INTERVAL_UNIT_QUARTER: |
|
147 | 1 | $interval *= 3; |
|
148 | 1 | $unit = self::DATE_INTERVAL_UNIT_MONTH; |
|
149 | 1 | break; |
|
150 | } |
||
151 | |||
152 | 1 | return "DATE(" . $date . ",'" . $operator . $interval . " " . $unit . "')"; |
|
153 | } |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * {@inheritDoc} |
||
158 | */ |
||
159 | 1 | public function getDateDiffExpression($date1, $date2) |
|
160 | { |
||
161 | 1 | return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; |
|
162 | } |
||
163 | |||
164 | /** |
||
165 | * {@inheritDoc} |
||
166 | */ |
||
167 | 1 | View Code Duplication | protected function _getTransactionIsolationLevelSQL($level) |
168 | { |
||
169 | switch ($level) { |
||
170 | 1 | case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED: |
|
171 | 1 | return 0; |
|
172 | 1 | case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED: |
|
173 | 1 | case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ: |
|
174 | 1 | case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE: |
|
175 | 1 | return 1; |
|
176 | default: |
||
177 | return parent::_getTransactionIsolationLevelSQL($level); |
||
178 | } |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * {@inheritDoc} |
||
183 | */ |
||
184 | 1 | public function getSetTransactionIsolationSQL($level) |
|
185 | { |
||
186 | 1 | return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSQL($level); |
|
187 | } |
||
188 | |||
189 | /** |
||
190 | * {@inheritDoc} |
||
191 | */ |
||
192 | 2 | public function prefersIdentityColumns() |
|
193 | { |
||
194 | 2 | return true; |
|
195 | } |
||
196 | |||
197 | /** |
||
198 | * {@inheritDoc} |
||
199 | */ |
||
200 | 16 | public function getBooleanTypeDeclarationSQL(array $field) |
|
201 | { |
||
202 | 16 | return 'BOOLEAN'; |
|
203 | } |
||
204 | |||
205 | /** |
||
206 | * {@inheritDoc} |
||
207 | */ |
||
208 | 144 | public function getIntegerTypeDeclarationSQL(array $field) |
|
209 | { |
||
210 | 144 | return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
|
211 | } |
||
212 | |||
213 | /** |
||
214 | * {@inheritDoc} |
||
215 | */ |
||
216 | 18 | View Code Duplication | public function getBigIntTypeDeclarationSQL(array $field) |
217 | { |
||
218 | // SQLite autoincrement is implicit for INTEGER PKs, but not for BIGINT fields. |
||
219 | 18 | if ( ! empty($field['autoincrement'])) { |
|
220 | 3 | return $this->getIntegerTypeDeclarationSQL($field); |
|
221 | } |
||
222 | |||
223 | 16 | return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
|
224 | } |
||
225 | |||
226 | /** |
||
227 | * {@inheritDoc} |
||
228 | */ |
||
229 | 2 | View Code Duplication | public function getTinyIntTypeDeclarationSql(array $field) |
230 | { |
||
231 | // SQLite autoincrement is implicit for INTEGER PKs, but not for TINYINT fields. |
||
232 | 2 | if ( ! empty($field['autoincrement'])) { |
|
233 | 2 | return $this->getIntegerTypeDeclarationSQL($field); |
|
234 | } |
||
235 | |||
236 | 1 | return 'TINYINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
|
237 | } |
||
238 | |||
239 | /** |
||
240 | * {@inheritDoc} |
||
241 | */ |
||
242 | 4 | View Code Duplication | public function getSmallIntTypeDeclarationSQL(array $field) |
243 | { |
||
244 | // SQLite autoincrement is implicit for INTEGER PKs, but not for SMALLINT fields. |
||
245 | 4 | if ( ! empty($field['autoincrement'])) { |
|
246 | 3 | return $this->getIntegerTypeDeclarationSQL($field); |
|
247 | } |
||
248 | |||
249 | 2 | return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
|
250 | } |
||
251 | |||
252 | /** |
||
253 | * {@inheritDoc} |
||
254 | */ |
||
255 | 1 | View Code Duplication | public function getMediumIntTypeDeclarationSql(array $field) |
256 | { |
||
257 | // SQLite autoincrement is implicit for INTEGER PKs, but not for MEDIUMINT fields. |
||
258 | 1 | if ( ! empty($field['autoincrement'])) { |
|
259 | 1 | return $this->getIntegerTypeDeclarationSQL($field); |
|
260 | } |
||
261 | |||
262 | 1 | return 'MEDIUMINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
|
263 | } |
||
264 | |||
265 | /** |
||
266 | * {@inheritDoc} |
||
267 | */ |
||
268 | 19 | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
269 | { |
||
270 | 19 | return 'DATETIME'; |
|
271 | } |
||
272 | |||
273 | /** |
||
274 | * {@inheritDoc} |
||
275 | */ |
||
276 | 18 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
|
277 | { |
||
278 | 18 | return 'DATE'; |
|
279 | } |
||
280 | |||
281 | /** |
||
282 | * {@inheritDoc} |
||
283 | */ |
||
284 | 18 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
285 | { |
||
286 | 18 | return 'TIME'; |
|
287 | } |
||
288 | |||
289 | /** |
||
290 | * {@inheritDoc} |
||
291 | */ |
||
292 | 144 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
|
293 | { |
||
294 | // sqlite autoincrement is implicit for integer PKs, but not when the field is unsigned |
||
295 | 144 | if ( ! empty($columnDef['autoincrement'])) { |
|
296 | 39 | return ''; |
|
297 | } |
||
298 | |||
299 | 131 | return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; |
|
300 | } |
||
301 | |||
302 | /** |
||
303 | * {@inheritDoc} |
||
304 | */ |
||
305 | 6 | public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) |
|
306 | { |
||
307 | 6 | return parent::getForeignKeyDeclarationSQL(new ForeignKeyConstraint( |
|
308 | 6 | $foreignKey->getQuotedLocalColumns($this), |
|
309 | 6 | str_replace('.', '__', $foreignKey->getQuotedForeignTableName($this)), |
|
310 | 6 | $foreignKey->getQuotedForeignColumns($this), |
|
311 | 6 | $foreignKey->getName(), |
|
312 | 6 | $foreignKey->getOptions() |
|
313 | )); |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * {@inheritDoc} |
||
318 | */ |
||
319 | 149 | protected function _getCreateTableSQL($name, array $columns, array $options = []) |
|
320 | { |
||
321 | 149 | $name = str_replace('.', '__', $name); |
|
322 | 149 | $queryFields = $this->getColumnDeclarationListSQL($columns); |
|
323 | |||
324 | 149 | if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { |
|
325 | foreach ($options['uniqueConstraints'] as $name => $definition) { |
||
326 | $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); |
||
327 | } |
||
328 | } |
||
329 | |||
330 | 149 | View Code Duplication | if (isset($options['primary']) && ! empty($options['primary'])) { |
331 | 97 | $keyColumns = array_unique(array_values($options['primary'])); |
|
332 | 97 | $queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')'; |
|
333 | } |
||
334 | |||
335 | 149 | if (isset($options['foreignKeys'])) { |
|
336 | 148 | foreach ($options['foreignKeys'] as $foreignKey) { |
|
337 | 6 | $queryFields.= ', '.$this->getForeignKeyDeclarationSQL($foreignKey); |
|
338 | } |
||
339 | } |
||
340 | |||
341 | 149 | $query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')'; |
|
342 | |||
343 | 149 | if (isset($options['alter']) && true === $options['alter']) { |
|
344 | 25 | return $query; |
|
345 | } |
||
346 | |||
347 | 137 | View Code Duplication | if (isset($options['indexes']) && ! empty($options['indexes'])) { |
348 | 8 | foreach ($options['indexes'] as $indexDef) { |
|
349 | 8 | $query[] = $this->getCreateIndexSQL($indexDef, $name); |
|
350 | } |
||
351 | } |
||
352 | |||
353 | 137 | View Code Duplication | if (isset($options['unique']) && ! empty($options['unique'])) { |
354 | foreach ($options['unique'] as $indexDef) { |
||
355 | $query[] = $this->getCreateIndexSQL($indexDef, $name); |
||
356 | } |
||
357 | } |
||
358 | |||
359 | 137 | return $query; |
|
360 | } |
||
361 | |||
362 | /** |
||
363 | * {@inheritDoc} |
||
364 | */ |
||
365 | 80 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
|
366 | { |
||
367 | 80 | return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') |
|
368 | 80 | : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); |
|
369 | } |
||
370 | |||
371 | /** |
||
372 | * {@inheritdoc} |
||
373 | */ |
||
374 | 2 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
|
375 | { |
||
376 | 2 | return 'BLOB'; |
|
377 | } |
||
378 | |||
379 | /** |
||
380 | * {@inheritdoc} |
||
381 | */ |
||
382 | 6 | public function getBinaryMaxLength() |
|
383 | { |
||
384 | 6 | return 0; |
|
385 | } |
||
386 | |||
387 | /** |
||
388 | * {@inheritdoc} |
||
389 | */ |
||
390 | 3 | public function getBinaryDefaultLength() |
|
391 | { |
||
392 | 3 | return 0; |
|
393 | } |
||
394 | |||
395 | /** |
||
396 | * {@inheritDoc} |
||
397 | */ |
||
398 | 45 | public function getClobTypeDeclarationSQL(array $field) |
|
399 | { |
||
400 | 45 | return 'CLOB'; |
|
401 | } |
||
402 | |||
403 | /** |
||
404 | * {@inheritDoc} |
||
405 | */ |
||
406 | 1 | public function getListTableConstraintsSQL($table) |
|
407 | { |
||
408 | 1 | $table = str_replace('.', '__', $table); |
|
409 | 1 | $table = $this->quoteStringLiteral($table); |
|
410 | |||
411 | 1 | return "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = $table AND sql NOT NULL ORDER BY name"; |
|
412 | } |
||
413 | |||
414 | /** |
||
415 | * {@inheritDoc} |
||
416 | */ |
||
417 | 41 | View Code Duplication | public function getListTableColumnsSQL($table, $currentDatabase = null) |
418 | { |
||
419 | 41 | $table = str_replace('.', '__', $table); |
|
420 | 41 | $table = $this->quoteStringLiteral($table); |
|
421 | |||
422 | 41 | return "PRAGMA table_info($table)"; |
|
423 | } |
||
424 | |||
425 | /** |
||
426 | * {@inheritDoc} |
||
427 | */ |
||
428 | 34 | View Code Duplication | public function getListTableIndexesSQL($table, $currentDatabase = null) |
429 | { |
||
430 | 34 | $table = str_replace('.', '__', $table); |
|
431 | 34 | $table = $this->quoteStringLiteral($table); |
|
432 | |||
433 | 34 | return "PRAGMA index_list($table)"; |
|
434 | } |
||
435 | |||
436 | /** |
||
437 | * {@inheritDoc} |
||
438 | */ |
||
439 | 64 | public function getListTablesSQL() |
|
440 | { |
||
441 | return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' AND name != 'geometry_columns' AND name != 'spatial_ref_sys' " |
||
442 | . "UNION ALL SELECT name FROM sqlite_temp_master " |
||
443 | 64 | . "WHERE type = 'table' ORDER BY name"; |
|
444 | } |
||
445 | |||
446 | /** |
||
447 | * {@inheritDoc} |
||
448 | */ |
||
449 | 1 | public function getListViewsSQL($database) |
|
452 | } |
||
453 | |||
454 | /** |
||
455 | * {@inheritDoc} |
||
456 | */ |
||
457 | 1 | public function getCreateViewSQL($name, $sql) |
|
458 | { |
||
459 | 1 | return 'CREATE VIEW ' . $name . ' AS ' . $sql; |
|
460 | } |
||
461 | |||
462 | /** |
||
463 | * {@inheritDoc} |
||
464 | */ |
||
465 | 1 | public function getDropViewSQL($name) |
|
466 | { |
||
467 | 1 | return 'DROP VIEW '. $name; |
|
468 | } |
||
469 | |||
470 | /** |
||
471 | * {@inheritDoc} |
||
472 | */ |
||
473 | 6 | public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) |
|
474 | { |
||
475 | 6 | $query = parent::getAdvancedForeignKeyOptionsSQL($foreignKey); |
|
476 | |||
477 | 6 | $query .= (($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false) ? ' ' : ' NOT ') . 'DEFERRABLE'; |
|
478 | 6 | $query .= ' INITIALLY ' . (($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false) ? 'DEFERRED' : 'IMMEDIATE'); |
|
479 | |||
480 | 6 | return $query; |
|
481 | } |
||
482 | |||
483 | /** |
||
484 | * {@inheritDoc} |
||
485 | */ |
||
486 | 3 | public function supportsIdentityColumns() |
|
487 | { |
||
488 | 3 | return true; |
|
489 | } |
||
490 | |||
491 | /** |
||
492 | * {@inheritDoc} |
||
493 | */ |
||
494 | 1 | public function supportsColumnCollation() |
|
495 | { |
||
496 | 1 | return true; |
|
497 | } |
||
498 | |||
499 | /** |
||
500 | * {@inheritDoc} |
||
501 | */ |
||
502 | 153 | public function supportsInlineColumnComments() |
|
503 | { |
||
504 | 153 | return true; |
|
505 | } |
||
506 | |||
507 | /** |
||
508 | * {@inheritDoc} |
||
509 | */ |
||
510 | 70 | public function getName() |
|
513 | } |
||
514 | |||
515 | /** |
||
516 | * {@inheritDoc} |
||
517 | */ |
||
518 | 12 | public function getTruncateTableSQL($tableName, $cascade = false) |
|
519 | { |
||
520 | 12 | $tableIdentifier = new Identifier($tableName); |
|
521 | 12 | $tableName = str_replace('.', '__', $tableIdentifier->getQuotedName($this)); |
|
522 | |||
523 | 12 | return 'DELETE FROM ' . $tableName; |
|
524 | } |
||
525 | |||
526 | /** |
||
527 | * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction(). |
||
528 | * |
||
529 | * @param integer|float $value |
||
530 | * |
||
531 | * @return float |
||
532 | */ |
||
533 | public static function udfSqrt($value) |
||
536 | } |
||
537 | |||
538 | /** |
||
539 | * User-defined function for Sqlite that implements MOD(a, b). |
||
540 | * |
||
541 | * @param integer $a |
||
542 | * @param integer $b |
||
543 | * |
||
544 | * @return integer |
||
545 | */ |
||
546 | public static function udfMod($a, $b) |
||
547 | { |
||
548 | return ($a % $b); |
||
549 | } |
||
550 | |||
551 | /** |
||
552 | * @param string $str |
||
553 | * @param string $substr |
||
554 | * @param integer $offset |
||
555 | * |
||
556 | * @return integer |
||
557 | */ |
||
558 | 1 | public static function udfLocate($str, $substr, $offset = 0) |
|
559 | { |
||
560 | // SQL's LOCATE function works on 1-based positions, while PHP's strpos works on 0-based positions. |
||
561 | // So we have to make them compatible if an offset is given. |
||
562 | 1 | if ($offset > 0) { |
|
563 | 1 | $offset -= 1; |
|
564 | } |
||
565 | |||
566 | 1 | $pos = strpos($str, $substr, $offset); |
|
567 | |||
568 | 1 | if ($pos !== false) { |
|
569 | 1 | return $pos + 1; |
|
570 | } |
||
571 | |||
572 | 1 | return 0; |
|
573 | } |
||
574 | |||
575 | /** |
||
576 | * {@inheritDoc} |
||
577 | */ |
||
578 | public function getForUpdateSql() |
||
579 | { |
||
580 | return ''; |
||
581 | } |
||
582 | |||
583 | /** |
||
584 | * {@inheritDoc} |
||
585 | */ |
||
586 | 38 | public function getInlineColumnCommentSQL($comment) |
|
587 | { |
||
588 | 38 | return '--' . str_replace("\n", "\n--", $comment) . "\n"; |
|
589 | } |
||
590 | |||
591 | /** |
||
592 | * {@inheritDoc} |
||
593 | */ |
||
594 | 7 | protected function initializeDoctrineTypeMappings() |
|
595 | { |
||
596 | 7 | $this->doctrineTypeMapping = [ |
|
597 | 'boolean' => 'boolean', |
||
598 | 'tinyint' => 'boolean', |
||
599 | 'smallint' => 'smallint', |
||
600 | 'mediumint' => 'integer', |
||
601 | 'int' => 'integer', |
||
602 | 'integer' => 'integer', |
||
603 | 'serial' => 'integer', |
||
604 | 'bigint' => 'bigint', |
||
605 | 'bigserial' => 'bigint', |
||
606 | 'clob' => 'text', |
||
607 | 'tinytext' => 'text', |
||
608 | 'mediumtext' => 'text', |
||
609 | 'longtext' => 'text', |
||
610 | 'text' => 'text', |
||
611 | 'varchar' => 'string', |
||
612 | 'longvarchar' => 'string', |
||
613 | 'varchar2' => 'string', |
||
614 | 'nvarchar' => 'string', |
||
615 | 'image' => 'string', |
||
616 | 'ntext' => 'string', |
||
617 | 'char' => 'string', |
||
618 | 'date' => 'date', |
||
619 | 'datetime' => 'datetime', |
||
620 | 'timestamp' => 'datetime', |
||
621 | 'time' => 'time', |
||
622 | 'float' => 'float', |
||
623 | 'double' => 'float', |
||
624 | 'double precision' => 'float', |
||
625 | 'real' => 'float', |
||
626 | 'decimal' => 'decimal', |
||
627 | 'numeric' => 'decimal', |
||
628 | 'blob' => 'blob', |
||
629 | ]; |
||
630 | 7 | } |
|
631 | |||
632 | /** |
||
633 | * {@inheritDoc} |
||
634 | */ |
||
635 | 49 | protected function getReservedKeywordsClass() |
|
636 | { |
||
637 | 49 | return Keywords\SQLiteKeywords::class; |
|
638 | } |
||
639 | |||
640 | /** |
||
641 | * {@inheritDoc} |
||
642 | */ |
||
643 | 25 | protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) |
|
644 | { |
||
645 | 25 | if ( ! $diff->fromTable instanceof Table) { |
|
646 | throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); |
||
647 | } |
||
648 | |||
649 | 25 | $sql = []; |
|
650 | 25 | foreach ($diff->fromTable->getIndexes() as $index) { |
|
651 | 9 | if ( ! $index->isPrimary()) { |
|
652 | 9 | $sql[] = $this->getDropIndexSQL($index, $diff->name); |
|
653 | } |
||
654 | } |
||
655 | |||
656 | 25 | return $sql; |
|
657 | } |
||
658 | |||
659 | /** |
||
660 | * {@inheritDoc} |
||
661 | */ |
||
662 | 25 | protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) |
|
663 | { |
||
664 | 25 | if ( ! $diff->fromTable instanceof Table) { |
|
665 | throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); |
||
666 | } |
||
667 | |||
668 | 25 | $sql = []; |
|
669 | 25 | $tableName = $diff->newName ? $diff->getNewName(): $diff->getName($this); |
|
670 | 25 | foreach ($this->getIndexesInAlteredTable($diff) as $index) { |
|
671 | 9 | if ($index->isPrimary()) { |
|
672 | 7 | continue; |
|
673 | } |
||
674 | |||
675 | 6 | $sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this)); |
|
676 | } |
||
677 | |||
678 | 25 | return $sql; |
|
679 | } |
||
680 | |||
681 | /** |
||
682 | * {@inheritDoc} |
||
683 | */ |
||
684 | 11 | protected function doModifyLimitQuery($query, $limit, $offset) |
|
685 | { |
||
686 | 11 | if (null === $limit && null !== $offset) { |
|
687 | 3 | return $query . ' LIMIT -1 OFFSET ' . $offset; |
|
688 | } |
||
689 | |||
690 | 9 | return parent::doModifyLimitQuery($query, $limit, $offset); |
|
691 | } |
||
692 | |||
693 | /** |
||
694 | * {@inheritDoc} |
||
695 | */ |
||
696 | 6 | public function getBlobTypeDeclarationSQL(array $field) |
|
697 | { |
||
698 | 6 | return 'BLOB'; |
|
699 | } |
||
700 | |||
701 | /** |
||
702 | * {@inheritDoc} |
||
703 | */ |
||
704 | 2 | public function getTemporaryTableName($tableName) |
|
705 | { |
||
706 | 2 | $tableName = str_replace('.', '__', $tableName); |
|
707 | |||
708 | 2 | return $tableName; |
|
709 | } |
||
710 | |||
711 | /** |
||
712 | * {@inheritDoc} |
||
713 | * |
||
714 | * Sqlite Platform emulates schema by underscoring each dot and generating tables |
||
715 | * into the default database. |
||
716 | * |
||
717 | * This hack is implemented to be able to use SQLite as testdriver when |
||
718 | * using schema supporting databases. |
||
719 | */ |
||
720 | public function canEmulateSchemas() |
||
721 | { |
||
722 | return true; |
||
723 | } |
||
724 | |||
725 | /** |
||
726 | * {@inheritDoc} |
||
727 | */ |
||
728 | 36 | public function supportsForeignKeyConstraints() |
|
729 | { |
||
730 | 36 | return false; |
|
731 | } |
||
732 | |||
733 | /** |
||
734 | * {@inheritDoc} |
||
735 | */ |
||
736 | public function getCreatePrimaryKeySQL(Index $index, $table) |
||
737 | { |
||
738 | throw new DBALException('Sqlite platform does not support alter primary key.'); |
||
739 | } |
||
740 | |||
741 | /** |
||
742 | * {@inheritdoc} |
||
743 | */ |
||
744 | 2 | public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) |
|
745 | { |
||
746 | 2 | throw new DBALException('Sqlite platform does not support alter foreign key.'); |
|
747 | } |
||
748 | |||
749 | /** |
||
750 | * {@inheritdoc} |
||
751 | */ |
||
752 | public function getDropForeignKeySQL($foreignKey, $table) |
||
753 | { |
||
754 | throw new DBALException('Sqlite platform does not support alter foreign key.'); |
||
755 | } |
||
756 | |||
757 | /** |
||
758 | * {@inheritDoc} |
||
759 | */ |
||
760 | 1 | public function getCreateConstraintSQL(Constraint $constraint, $table) |
|
761 | { |
||
762 | 1 | throw new DBALException('Sqlite platform does not support alter constraint.'); |
|
763 | } |
||
764 | |||
765 | /** |
||
766 | * {@inheritDoc} |
||
767 | */ |
||
768 | 150 | public function getCreateTableSQL(Table $table, $createFlags = null) |
|
773 | } |
||
774 | |||
775 | /** |
||
776 | * {@inheritDoc} |
||
777 | */ |
||
778 | 2 | View Code Duplication | public function getListTableForeignKeysSQL($table, $database = null) |
779 | { |
||
780 | 2 | $table = str_replace('.', '__', $table); |
|
781 | 2 | $table = $this->quoteStringLiteral($table); |
|
782 | |||
783 | 2 | return "PRAGMA foreign_key_list($table)"; |
|
784 | } |
||
785 | |||
786 | /** |
||
787 | * {@inheritDoc} |
||
788 | */ |
||
789 | 34 | public function getAlterTableSQL(TableDiff $diff) |
|
790 | { |
||
791 | 34 | $sql = $this->getSimpleAlterTableSQL($diff); |
|
792 | 34 | if (false !== $sql) { |
|
793 | 7 | return $sql; |
|
794 | } |
||
795 | |||
796 | 27 | $fromTable = $diff->fromTable; |
|
797 | 27 | if ( ! $fromTable instanceof Table) { |
|
798 | 2 | throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); |
|
799 | } |
||
800 | |||
801 | 25 | $table = clone $fromTable; |
|
802 | |||
803 | 25 | $columns = []; |
|
804 | 25 | $oldColumnNames = []; |
|
805 | 25 | $newColumnNames = []; |
|
806 | 25 | $columnSql = []; |
|
807 | |||
808 | 25 | foreach ($table->getColumns() as $columnName => $column) { |
|
809 | 24 | $columnName = strtolower($columnName); |
|
810 | 24 | $columns[$columnName] = $column; |
|
811 | 24 | $oldColumnNames[$columnName] = $newColumnNames[$columnName] = $column->getQuotedName($this); |
|
812 | } |
||
813 | |||
814 | 25 | foreach ($diff->removedColumns as $columnName => $column) { |
|
815 | 5 | if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { |
|
816 | continue; |
||
817 | } |
||
818 | |||
819 | 5 | $columnName = strtolower($columnName); |
|
820 | 5 | if (isset($columns[$columnName])) { |
|
821 | 5 | unset($columns[$columnName]); |
|
822 | 5 | unset($oldColumnNames[$columnName]); |
|
823 | 5 | unset($newColumnNames[$columnName]); |
|
824 | } |
||
825 | } |
||
826 | |||
827 | 25 | foreach ($diff->renamedColumns as $oldColumnName => $column) { |
|
828 | 5 | if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { |
|
829 | continue; |
||
830 | } |
||
831 | |||
832 | 5 | $oldColumnName = strtolower($oldColumnName); |
|
833 | 5 | if (isset($columns[$oldColumnName])) { |
|
834 | 5 | unset($columns[$oldColumnName]); |
|
835 | } |
||
836 | |||
837 | 5 | $columns[strtolower($column->getName())] = $column; |
|
838 | |||
839 | 5 | if (isset($newColumnNames[$oldColumnName])) { |
|
840 | 5 | $newColumnNames[$oldColumnName] = $column->getQuotedName($this); |
|
841 | } |
||
842 | } |
||
843 | |||
844 | 25 | foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { |
|
845 | 18 | if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { |
|
846 | continue; |
||
847 | } |
||
848 | |||
849 | 18 | if (isset($columns[$oldColumnName])) { |
|
850 | 17 | unset($columns[$oldColumnName]); |
|
851 | } |
||
852 | |||
853 | 18 | $columns[strtolower($columnDiff->column->getName())] = $columnDiff->column; |
|
854 | |||
855 | 18 | if (isset($newColumnNames[$oldColumnName])) { |
|
856 | 18 | $newColumnNames[$oldColumnName] = $columnDiff->column->getQuotedName($this); |
|
857 | } |
||
858 | } |
||
859 | |||
860 | 25 | foreach ($diff->addedColumns as $columnName => $column) { |
|
861 | 4 | if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { |
|
862 | continue; |
||
863 | } |
||
864 | |||
865 | 4 | $columns[strtolower($columnName)] = $column; |
|
866 | } |
||
867 | |||
868 | 25 | $sql = []; |
|
869 | 25 | $tableSql = []; |
|
870 | 25 | if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { |
|
871 | 25 | $dataTable = new Table('__temp__'.$table->getName()); |
|
872 | |||
873 | 25 | $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); |
|
874 | 25 | $newTable->addOption('alter', true); |
|
875 | |||
876 | 25 | $sql = $this->getPreAlterTableIndexForeignKeySQL($diff); |
|
877 | //$sql = array_merge($sql, $this->getCreateTableSQL($dataTable, 0)); |
||
878 | 25 | $sql[] = sprintf('CREATE TEMPORARY TABLE %s AS SELECT %s FROM %s', $dataTable->getQuotedName($this), implode(', ', $oldColumnNames), $table->getQuotedName($this)); |
|
879 | 25 | $sql[] = $this->getDropTableSQL($fromTable); |
|
880 | |||
881 | 25 | $sql = array_merge($sql, $this->getCreateTableSQL($newTable)); |
|
882 | 25 | $sql[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $newTable->getQuotedName($this), implode(', ', $newColumnNames), implode(', ', $oldColumnNames), $dataTable->getQuotedName($this)); |
|
883 | 25 | $sql[] = $this->getDropTableSQL($dataTable); |
|
884 | |||
885 | 25 | if ($diff->newName && $diff->newName != $diff->name) { |
|
886 | 3 | $renamedTable = $diff->getNewName(); |
|
887 | 3 | $sql[] = 'ALTER TABLE '.$newTable->getQuotedName($this).' RENAME TO '.$renamedTable->getQuotedName($this); |
|
888 | } |
||
889 | |||
890 | 25 | $sql = array_merge($sql, $this->getPostAlterTableIndexForeignKeySQL($diff)); |
|
891 | } |
||
892 | |||
893 | 25 | return array_merge($sql, $tableSql, $columnSql); |
|
894 | } |
||
895 | |||
896 | /** |
||
897 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
898 | * |
||
899 | * @return array|bool |
||
900 | */ |
||
901 | 34 | private function getSimpleAlterTableSQL(TableDiff $diff) |
|
902 | { |
||
903 | // Suppress changes on integer type autoincrement columns. |
||
904 | 34 | foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { |
|
905 | 23 | if ( ! $columnDiff->fromColumn instanceof Column || |
|
906 | 19 | ! $columnDiff->column instanceof Column || |
|
907 | 19 | ! $columnDiff->column->getAutoincrement() || |
|
908 | 23 | ! $columnDiff->column->getType() instanceof Types\IntegerType |
|
909 | ) { |
||
910 | 18 | continue; |
|
911 | } |
||
912 | |||
913 | 5 | if ( ! $columnDiff->hasChanged('type') && $columnDiff->hasChanged('unsigned')) { |
|
914 | 1 | unset($diff->changedColumns[$oldColumnName]); |
|
915 | |||
916 | 1 | continue; |
|
917 | } |
||
918 | |||
919 | 4 | $fromColumnType = $columnDiff->fromColumn->getType(); |
|
920 | |||
921 | 4 | if ($fromColumnType instanceof Types\SmallIntType || $fromColumnType instanceof Types\BigIntType) { |
|
922 | 4 | unset($diff->changedColumns[$oldColumnName]); |
|
923 | } |
||
924 | } |
||
925 | |||
926 | 34 | if ( ! empty($diff->renamedColumns) || ! empty($diff->addedForeignKeys) || ! empty($diff->addedIndexes) |
|
927 | 29 | || ! empty($diff->changedColumns) || ! empty($diff->changedForeignKeys) || ! empty($diff->changedIndexes) |
|
928 | 13 | || ! empty($diff->removedColumns) || ! empty($diff->removedForeignKeys) || ! empty($diff->removedIndexes) |
|
929 | 34 | || ! empty($diff->renamedIndexes) |
|
930 | ) { |
||
931 | 25 | return false; |
|
932 | } |
||
933 | |||
934 | 9 | $table = new Table($diff->name); |
|
935 | |||
936 | 9 | $sql = []; |
|
937 | 9 | $tableSql = []; |
|
938 | 9 | $columnSql = []; |
|
939 | |||
940 | 9 | foreach ($diff->addedColumns as $column) { |
|
941 | 3 | if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { |
|
942 | continue; |
||
943 | } |
||
944 | |||
945 | 3 | $field = array_merge(['unique' => null, 'autoincrement' => null, 'default' => null], $column->toArray()); |
|
946 | 3 | $type = $field['type']; |
|
947 | switch (true) { |
||
948 | 3 | case isset($field['columnDefinition']) || $field['autoincrement'] || $field['unique']: |
|
949 | 2 | case $type instanceof Types\DateTimeType && $field['default'] == $this->getCurrentTimestampSQL(): |
|
950 | 2 | case $type instanceof Types\DateType && $field['default'] == $this->getCurrentDateSQL(): |
|
951 | 1 | case $type instanceof Types\TimeType && $field['default'] == $this->getCurrentTimeSQL(): |
|
952 | 2 | return false; |
|
953 | } |
||
954 | |||
955 | 1 | $field['name'] = $column->getQuotedName($this); |
|
956 | 1 | if ($type instanceof Types\StringType && $field['length'] === null) { |
|
957 | 1 | $field['length'] = 255; |
|
958 | } |
||
959 | |||
960 | 1 | $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' ADD COLUMN '.$this->getColumnDeclarationSQL($field['name'], $field); |
|
961 | } |
||
962 | |||
963 | 7 | if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { |
|
964 | 7 | if ($diff->newName !== false) { |
|
965 | 1 | $newTable = new Identifier($diff->newName); |
|
966 | 1 | $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' RENAME TO '.$newTable->getQuotedName($this); |
|
967 | } |
||
968 | } |
||
969 | |||
970 | 7 | return array_merge($sql, $tableSql, $columnSql); |
|
971 | } |
||
972 | |||
973 | /** |
||
974 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
975 | * |
||
976 | * @return array |
||
977 | */ |
||
978 | 25 | private function getColumnNamesInAlteredTable(TableDiff $diff) |
|
1010 | } |
||
1011 | |||
1012 | /** |
||
1013 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
1014 | * |
||
1015 | * @return \Doctrine\DBAL\Schema\Index[] |
||
1016 | */ |
||
1017 | 25 | private function getIndexesInAlteredTable(TableDiff $diff) |
|
1018 | { |
||
1019 | 25 | $indexes = $diff->fromTable->getIndexes(); |
|
1020 | 25 | $columnNames = $this->getColumnNamesInAlteredTable($diff); |
|
1021 | |||
1022 | 25 | foreach ($indexes as $key => $index) { |
|
1023 | 9 | foreach ($diff->renamedIndexes as $oldIndexName => $renamedIndex) { |
|
1024 | 4 | if (strtolower($key) === strtolower($oldIndexName)) { |
|
1025 | 4 | unset($indexes[$key]); |
|
1026 | } |
||
1027 | } |
||
1028 | |||
1029 | 9 | $changed = false; |
|
1030 | 9 | $indexColumns = []; |
|
1031 | 9 | View Code Duplication | foreach ($index->getColumns() as $columnName) { |
1032 | 9 | $normalizedColumnName = strtolower($columnName); |
|
1033 | 9 | if ( ! isset($columnNames[$normalizedColumnName])) { |
|
1034 | 1 | unset($indexes[$key]); |
|
1035 | 1 | continue 2; |
|
1036 | } else { |
||
1037 | 9 | $indexColumns[] = $columnNames[$normalizedColumnName]; |
|
1038 | 9 | if ($columnName !== $columnNames[$normalizedColumnName]) { |
|
1039 | 9 | $changed = true; |
|
1040 | } |
||
1041 | } |
||
1042 | } |
||
1043 | |||
1044 | 9 | if ($changed) { |
|
1045 | 9 | $indexes[$key] = new Index($index->getName(), $indexColumns, $index->isUnique(), $index->isPrimary(), $index->getFlags()); |
|
1046 | } |
||
1047 | } |
||
1048 | |||
1049 | 25 | foreach ($diff->removedIndexes as $index) { |
|
1050 | 2 | $indexName = strtolower($index->getName()); |
|
1051 | 2 | if (strlen($indexName) && isset($indexes[$indexName])) { |
|
1052 | 2 | unset($indexes[$indexName]); |
|
1053 | } |
||
1054 | } |
||
1055 | |||
1056 | 25 | foreach (array_merge($diff->changedIndexes, $diff->addedIndexes, $diff->renamedIndexes) as $index) { |
|
1057 | 4 | $indexName = strtolower($index->getName()); |
|
1058 | 4 | if (strlen($indexName)) { |
|
1059 | 4 | $indexes[$indexName] = $index; |
|
1060 | } else { |
||
1061 | 4 | $indexes[] = $index; |
|
1062 | } |
||
1063 | } |
||
1064 | |||
1065 | 25 | return $indexes; |
|
1066 | } |
||
1067 | |||
1068 | /** |
||
1069 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
1070 | * |
||
1071 | * @return array |
||
1072 | */ |
||
1073 | 25 | private function getForeignKeysInAlteredTable(TableDiff $diff) |
|
1074 | { |
||
1075 | 25 | $foreignKeys = $diff->fromTable->getForeignKeys(); |
|
1076 | 25 | $columnNames = $this->getColumnNamesInAlteredTable($diff); |
|
1077 | |||
1078 | 25 | foreach ($foreignKeys as $key => $constraint) { |
|
1079 | 3 | $changed = false; |
|
1080 | 3 | $localColumns = []; |
|
1081 | 3 | View Code Duplication | foreach ($constraint->getLocalColumns() as $columnName) { |
1082 | 3 | $normalizedColumnName = strtolower($columnName); |
|
1083 | 3 | if ( ! isset($columnNames[$normalizedColumnName])) { |
|
1084 | 1 | unset($foreignKeys[$key]); |
|
1085 | 1 | continue 2; |
|
1086 | } else { |
||
1087 | 3 | $localColumns[] = $columnNames[$normalizedColumnName]; |
|
1088 | 3 | if ($columnName !== $columnNames[$normalizedColumnName]) { |
|
1089 | 3 | $changed = true; |
|
1090 | } |
||
1091 | } |
||
1092 | } |
||
1093 | |||
1094 | 3 | if ($changed) { |
|
1095 | 3 | $foreignKeys[$key] = new ForeignKeyConstraint($localColumns, $constraint->getForeignTableName(), $constraint->getForeignColumns(), $constraint->getName(), $constraint->getOptions()); |
|
1096 | } |
||
1097 | } |
||
1098 | |||
1099 | 25 | foreach ($diff->removedForeignKeys as $constraint) { |
|
1100 | 1 | $constraintName = strtolower($constraint->getName()); |
|
1101 | 1 | if (strlen($constraintName) && isset($foreignKeys[$constraintName])) { |
|
1102 | 1 | unset($foreignKeys[$constraintName]); |
|
1103 | } |
||
1104 | } |
||
1105 | |||
1106 | 25 | foreach (array_merge($diff->changedForeignKeys, $diff->addedForeignKeys) as $constraint) { |
|
1107 | 2 | $constraintName = strtolower($constraint->getName()); |
|
1108 | 2 | if (strlen($constraintName)) { |
|
1109 | 1 | $foreignKeys[$constraintName] = $constraint; |
|
1110 | } else { |
||
1111 | 2 | $foreignKeys[] = $constraint; |
|
1112 | } |
||
1113 | } |
||
1114 | |||
1115 | 25 | return $foreignKeys; |
|
1116 | } |
||
1117 | |||
1118 | /** |
||
1119 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
1120 | * |
||
1121 | * @return array |
||
1122 | */ |
||
1123 | 25 | private function getPrimaryIndexInAlteredTable(TableDiff $diff) |
|
1134 | } |
||
1135 | } |
||
1136 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.