1 | <?php |
||
2 | /* |
||
3 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
4 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
5 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
6 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
7 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
8 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
9 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
10 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
11 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
12 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
13 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
14 | * |
||
15 | * This software consists of voluntary contributions made by many individuals |
||
16 | * and is licensed under the MIT license. For more information, see |
||
17 | * <http://www.doctrine-project.org>. |
||
18 | */ |
||
19 | |||
20 | namespace Doctrine\DBAL\Platforms; |
||
21 | |||
22 | use Doctrine\DBAL\DBALException; |
||
23 | use Doctrine\DBAL\Schema\ColumnDiff; |
||
24 | use Doctrine\DBAL\Schema\Identifier; |
||
25 | use Doctrine\DBAL\Schema\Index; |
||
26 | use Doctrine\DBAL\Schema\Table; |
||
27 | use Doctrine\DBAL\Schema\TableDiff; |
||
28 | use Doctrine\DBAL\Types\Type; |
||
29 | |||
30 | class DB2Platform extends AbstractPlatform |
||
31 | { |
||
32 | /** |
||
33 | * {@inheritdoc} |
||
34 | */ |
||
35 | 2 | public function getBinaryMaxLength() |
|
36 | { |
||
37 | 2 | return 32704; |
|
38 | } |
||
39 | |||
40 | /** |
||
41 | * {@inheritdoc} |
||
42 | */ |
||
43 | 2 | public function getBinaryDefaultLength() |
|
44 | { |
||
45 | 2 | return 1; |
|
46 | } |
||
47 | |||
48 | /** |
||
49 | * {@inheritDoc} |
||
50 | */ |
||
51 | 2 | public function getBlobTypeDeclarationSQL(array $field) |
|
52 | { |
||
53 | // todo blob(n) with $field['length']; |
||
0 ignored issues
–
show
|
|||
54 | 2 | return 'BLOB(1M)'; |
|
55 | } |
||
56 | |||
57 | /** |
||
58 | * {@inheritDoc} |
||
59 | */ |
||
60 | 5 | public function initializeDoctrineTypeMappings() |
|
61 | { |
||
62 | 5 | $this->doctrineTypeMapping = [ |
|
63 | 'smallint' => 'smallint', |
||
64 | 'bigint' => 'bigint', |
||
65 | 'integer' => 'integer', |
||
66 | 'time' => 'time', |
||
67 | 'date' => 'date', |
||
68 | 'varchar' => 'string', |
||
69 | 'character' => 'string', |
||
70 | 'varbinary' => 'binary', |
||
71 | 'binary' => 'binary', |
||
72 | 'clob' => 'text', |
||
73 | 'blob' => 'blob', |
||
74 | 'decimal' => 'decimal', |
||
75 | 'double' => 'float', |
||
76 | 'real' => 'float', |
||
77 | 'timestamp' => 'datetime', |
||
78 | ]; |
||
79 | 5 | } |
|
80 | |||
81 | /** |
||
82 | * {@inheritdoc} |
||
83 | */ |
||
84 | 42 | public function isCommentedDoctrineType(Type $doctrineType) |
|
85 | { |
||
86 | 42 | if ($doctrineType->getName() === Type::BOOLEAN) { |
|
87 | // We require a commented boolean type in order to distinguish between boolean and smallint |
||
88 | // as both (have to) map to the same native type. |
||
89 | 1 | return true; |
|
90 | } |
||
91 | |||
92 | 41 | return parent::isCommentedDoctrineType($doctrineType); |
|
93 | } |
||
94 | |||
95 | /** |
||
96 | * {@inheritDoc} |
||
97 | */ |
||
98 | 15 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
|
99 | { |
||
100 | 15 | return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') |
|
101 | 15 | : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); |
|
102 | } |
||
103 | |||
104 | /** |
||
105 | * {@inheritdoc} |
||
106 | */ |
||
107 | 1 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
|
108 | { |
||
109 | 1 | return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; |
|
110 | } |
||
111 | |||
112 | /** |
||
113 | * {@inheritDoc} |
||
114 | */ |
||
115 | 3 | public function getClobTypeDeclarationSQL(array $field) |
|
116 | { |
||
117 | // todo clob(n) with $field['length']; |
||
118 | 3 | return 'CLOB(1M)'; |
|
119 | } |
||
120 | |||
121 | /** |
||
122 | * {@inheritDoc} |
||
123 | */ |
||
124 | 3 | public function getName() |
|
125 | { |
||
126 | 3 | return 'db2'; |
|
127 | } |
||
128 | |||
129 | /** |
||
130 | * {@inheritDoc} |
||
131 | */ |
||
132 | 2 | public function getBooleanTypeDeclarationSQL(array $columnDef) |
|
133 | { |
||
134 | 2 | return 'SMALLINT'; |
|
135 | } |
||
136 | |||
137 | /** |
||
138 | * {@inheritDoc} |
||
139 | */ |
||
140 | 12 | public function getIntegerTypeDeclarationSQL(array $columnDef) |
|
141 | { |
||
142 | 12 | return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); |
|
143 | } |
||
144 | |||
145 | /** |
||
146 | * {@inheritDoc} |
||
147 | */ |
||
148 | 1 | public function getBigIntTypeDeclarationSQL(array $columnDef) |
|
149 | { |
||
150 | 1 | return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * {@inheritDoc} |
||
155 | */ |
||
156 | 1 | public function getSmallIntTypeDeclarationSQL(array $columnDef) |
|
157 | { |
||
158 | 1 | return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); |
|
159 | } |
||
160 | |||
161 | /** |
||
162 | * {@inheritDoc} |
||
163 | */ |
||
164 | 12 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
|
165 | { |
||
166 | 12 | $autoinc = ''; |
|
167 | 12 | if ( ! empty($columnDef['autoincrement'])) { |
|
168 | 2 | $autoinc = ' GENERATED BY DEFAULT AS IDENTITY'; |
|
169 | } |
||
170 | |||
171 | 12 | return $autoinc; |
|
172 | } |
||
173 | |||
174 | /** |
||
175 | * {@inheritdoc} |
||
176 | */ |
||
177 | 1 | public function getBitAndComparisonExpression($value1, $value2) |
|
178 | { |
||
179 | 1 | return 'BITAND(' . $value1 . ', ' . $value2 . ')'; |
|
180 | } |
||
181 | |||
182 | /** |
||
183 | * {@inheritdoc} |
||
184 | */ |
||
185 | 1 | public function getBitOrComparisonExpression($value1, $value2) |
|
186 | { |
||
187 | 1 | return 'BITOR(' . $value1 . ', ' . $value2 . ')'; |
|
188 | } |
||
189 | |||
190 | /** |
||
191 | * {@inheritdoc} |
||
192 | */ |
||
193 | 1 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
|
194 | { |
||
195 | View Code Duplication | switch ($unit) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
196 | 1 | case self::DATE_INTERVAL_UNIT_WEEK: |
|
197 | 1 | $interval *= 7; |
|
198 | 1 | $unit = self::DATE_INTERVAL_UNIT_DAY; |
|
199 | 1 | break; |
|
200 | |||
201 | 1 | case self::DATE_INTERVAL_UNIT_QUARTER: |
|
202 | 1 | $interval *= 3; |
|
203 | 1 | $unit = self::DATE_INTERVAL_UNIT_MONTH; |
|
204 | 1 | break; |
|
205 | } |
||
206 | |||
207 | 1 | return $date . ' ' . $operator . ' ' . $interval . ' ' . $unit; |
|
208 | } |
||
209 | |||
210 | /** |
||
211 | * {@inheritdoc} |
||
212 | */ |
||
213 | 1 | public function getDateDiffExpression($date1, $date2) |
|
214 | { |
||
215 | 1 | return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; |
|
216 | } |
||
217 | |||
218 | /** |
||
219 | * {@inheritDoc} |
||
220 | */ |
||
221 | 1 | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
222 | { |
||
223 | 1 | if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { |
|
224 | 1 | return "TIMESTAMP(0) WITH DEFAULT"; |
|
225 | } |
||
226 | |||
227 | 1 | return 'TIMESTAMP(0)'; |
|
228 | } |
||
229 | |||
230 | /** |
||
231 | * {@inheritDoc} |
||
232 | */ |
||
233 | 1 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
|
234 | { |
||
235 | 1 | return 'DATE'; |
|
236 | } |
||
237 | |||
238 | /** |
||
239 | * {@inheritDoc} |
||
240 | */ |
||
241 | 1 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
242 | { |
||
243 | 1 | return 'TIME'; |
|
244 | } |
||
245 | |||
246 | /** |
||
247 | * {@inheritdoc} |
||
248 | */ |
||
249 | 2 | public function getTruncateTableSQL($tableName, $cascade = false) |
|
250 | { |
||
251 | 2 | $tableIdentifier = new Identifier($tableName); |
|
252 | |||
253 | 2 | return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this) . ' IMMEDIATE'; |
|
254 | } |
||
255 | |||
256 | /** |
||
257 | * This code fragment is originally from the Zend_Db_Adapter_Db2 class, but has been edited. |
||
258 | * |
||
259 | * @license New BSD License |
||
260 | * |
||
261 | * @param string $table |
||
262 | * @param string $database |
||
263 | * |
||
264 | * @return string |
||
265 | */ |
||
266 | 1 | public function getListTableColumnsSQL($table, $database = null) |
|
267 | { |
||
268 | 1 | $table = $this->quoteStringLiteral($table); |
|
269 | |||
270 | // We do the funky subquery and join syscat.columns.default this crazy way because |
||
271 | // as of db2 v10, the column is CLOB(64k) and the distinct operator won't allow a CLOB, |
||
272 | // it wants shorter stuff like a varchar. |
||
273 | return " |
||
274 | SELECT |
||
275 | cols.default, |
||
276 | subq.* |
||
277 | FROM ( |
||
278 | SELECT DISTINCT |
||
279 | c.tabschema, |
||
280 | c.tabname, |
||
281 | c.colname, |
||
282 | c.colno, |
||
283 | c.typename, |
||
284 | c.nulls, |
||
285 | c.length, |
||
286 | c.scale, |
||
287 | c.identity, |
||
288 | tc.type AS tabconsttype, |
||
289 | c.remarks AS comment, |
||
290 | k.colseq, |
||
291 | CASE |
||
292 | WHEN c.generated = 'D' THEN 1 |
||
293 | ELSE 0 |
||
294 | END AS autoincrement |
||
295 | FROM syscat.columns c |
||
296 | LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc |
||
297 | ON (k.tabschema = tc.tabschema |
||
298 | AND k.tabname = tc.tabname |
||
299 | AND tc.type = 'P')) |
||
300 | ON (c.tabschema = k.tabschema |
||
301 | AND c.tabname = k.tabname |
||
302 | AND c.colname = k.colname) |
||
303 | 1 | WHERE UPPER(c.tabname) = UPPER(" . $table . ") |
|
304 | ORDER BY c.colno |
||
305 | ) subq |
||
306 | JOIN syscat.columns cols |
||
307 | ON subq.tabschema = cols.tabschema |
||
308 | AND subq.tabname = cols.tabname |
||
309 | AND subq.colno = cols.colno |
||
310 | ORDER BY subq.colno |
||
311 | "; |
||
312 | } |
||
313 | |||
314 | /** |
||
315 | * {@inheritDoc} |
||
316 | */ |
||
317 | public function getListTablesSQL() |
||
318 | { |
||
319 | return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; |
||
320 | } |
||
321 | |||
322 | /** |
||
323 | * {@inheritDoc} |
||
324 | */ |
||
325 | public function getListViewsSQL($database) |
||
326 | { |
||
327 | return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS"; |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * {@inheritDoc} |
||
332 | */ |
||
333 | 1 | public function getListTableIndexesSQL($table, $currentDatabase = null) |
|
334 | { |
||
335 | 1 | $table = $this->quoteStringLiteral($table); |
|
336 | |||
337 | return "SELECT idx.INDNAME AS key_name, |
||
338 | idxcol.COLNAME AS column_name, |
||
339 | CASE |
||
340 | WHEN idx.UNIQUERULE = 'P' THEN 1 |
||
341 | ELSE 0 |
||
342 | END AS primary, |
||
343 | CASE |
||
344 | WHEN idx.UNIQUERULE = 'D' THEN 1 |
||
345 | ELSE 0 |
||
346 | END AS non_unique |
||
347 | FROM SYSCAT.INDEXES AS idx |
||
348 | JOIN SYSCAT.INDEXCOLUSE AS idxcol |
||
349 | ON idx.INDSCHEMA = idxcol.INDSCHEMA AND idx.INDNAME = idxcol.INDNAME |
||
350 | 1 | WHERE idx.TABNAME = UPPER(" . $table . ") |
|
351 | ORDER BY idxcol.COLSEQ ASC"; |
||
352 | } |
||
353 | |||
354 | /** |
||
355 | * {@inheritDoc} |
||
356 | */ |
||
357 | 1 | public function getListTableForeignKeysSQL($table) |
|
358 | { |
||
359 | 1 | $table = $this->quoteStringLiteral($table); |
|
360 | |||
361 | return "SELECT fkcol.COLNAME AS local_column, |
||
362 | fk.REFTABNAME AS foreign_table, |
||
363 | pkcol.COLNAME AS foreign_column, |
||
364 | fk.CONSTNAME AS index_name, |
||
365 | CASE |
||
366 | WHEN fk.UPDATERULE = 'R' THEN 'RESTRICT' |
||
367 | ELSE NULL |
||
368 | END AS on_update, |
||
369 | CASE |
||
370 | WHEN fk.DELETERULE = 'C' THEN 'CASCADE' |
||
371 | WHEN fk.DELETERULE = 'N' THEN 'SET NULL' |
||
372 | WHEN fk.DELETERULE = 'R' THEN 'RESTRICT' |
||
373 | ELSE NULL |
||
374 | END AS on_delete |
||
375 | FROM SYSCAT.REFERENCES AS fk |
||
376 | JOIN SYSCAT.KEYCOLUSE AS fkcol |
||
377 | ON fk.CONSTNAME = fkcol.CONSTNAME |
||
378 | AND fk.TABSCHEMA = fkcol.TABSCHEMA |
||
379 | AND fk.TABNAME = fkcol.TABNAME |
||
380 | JOIN SYSCAT.KEYCOLUSE AS pkcol |
||
381 | ON fk.REFKEYNAME = pkcol.CONSTNAME |
||
382 | AND fk.REFTABSCHEMA = pkcol.TABSCHEMA |
||
383 | AND fk.REFTABNAME = pkcol.TABNAME |
||
384 | 1 | WHERE fk.TABNAME = UPPER(" . $table . ") |
|
385 | ORDER BY fkcol.COLSEQ ASC"; |
||
386 | } |
||
387 | |||
388 | /** |
||
389 | * {@inheritDoc} |
||
390 | */ |
||
391 | 1 | public function getCreateViewSQL($name, $sql) |
|
392 | { |
||
393 | 1 | return "CREATE VIEW ".$name." AS ".$sql; |
|
394 | } |
||
395 | |||
396 | /** |
||
397 | * {@inheritDoc} |
||
398 | */ |
||
399 | 1 | public function getDropViewSQL($name) |
|
400 | { |
||
401 | 1 | return "DROP VIEW ".$name; |
|
402 | } |
||
403 | |||
404 | /** |
||
405 | * {@inheritDoc} |
||
406 | */ |
||
407 | 1 | public function getCreateDatabaseSQL($database) |
|
408 | { |
||
409 | 1 | return "CREATE DATABASE ".$database; |
|
410 | } |
||
411 | |||
412 | /** |
||
413 | * {@inheritDoc} |
||
414 | */ |
||
415 | 1 | public function getDropDatabaseSQL($database) |
|
416 | { |
||
417 | 1 | return "DROP DATABASE " . $database; |
|
418 | } |
||
419 | |||
420 | /** |
||
421 | * {@inheritDoc} |
||
422 | */ |
||
423 | 1 | public function supportsCreateDropDatabase() |
|
424 | { |
||
425 | 1 | return false; |
|
426 | } |
||
427 | |||
428 | /** |
||
429 | * {@inheritDoc} |
||
430 | */ |
||
431 | 1 | public function supportsReleaseSavepoints() |
|
432 | { |
||
433 | 1 | return false; |
|
434 | } |
||
435 | |||
436 | /** |
||
437 | * {@inheritdoc} |
||
438 | */ |
||
439 | 13 | public function supportsCommentOnStatement() |
|
440 | { |
||
441 | 13 | return true; |
|
442 | } |
||
443 | |||
444 | /** |
||
445 | * {@inheritDoc} |
||
446 | */ |
||
447 | 2 | public function getCurrentDateSQL() |
|
448 | { |
||
449 | 2 | return 'CURRENT DATE'; |
|
450 | } |
||
451 | |||
452 | /** |
||
453 | * {@inheritDoc} |
||
454 | */ |
||
455 | 1 | public function getCurrentTimeSQL() |
|
456 | { |
||
457 | 1 | return 'CURRENT TIME'; |
|
458 | } |
||
459 | |||
460 | /** |
||
461 | * {@inheritDoc} |
||
462 | */ |
||
463 | 2 | public function getCurrentTimestampSQL() |
|
464 | { |
||
465 | 2 | return "CURRENT TIMESTAMP"; |
|
466 | } |
||
467 | |||
468 | /** |
||
469 | * {@inheritDoc} |
||
470 | */ |
||
471 | 1 | public function getIndexDeclarationSQL($name, Index $index) |
|
472 | { |
||
473 | // Index declaration in statements like CREATE TABLE is not supported. |
||
474 | 1 | throw DBALException::notSupported(__METHOD__); |
|
475 | } |
||
476 | |||
477 | /** |
||
478 | * {@inheritDoc} |
||
479 | */ |
||
480 | 12 | protected function _getCreateTableSQL($tableName, array $columns, array $options = []) |
|
481 | { |
||
482 | 12 | $indexes = []; |
|
483 | 12 | if (isset($options['indexes'])) { |
|
484 | 12 | $indexes = $options['indexes']; |
|
485 | } |
||
486 | 12 | $options['indexes'] = []; |
|
487 | |||
488 | 12 | $sqls = parent::_getCreateTableSQL($tableName, $columns, $options); |
|
489 | |||
490 | 12 | foreach ($indexes as $definition) { |
|
491 | 4 | $sqls[] = $this->getCreateIndexSQL($definition, $tableName); |
|
492 | } |
||
493 | 12 | return $sqls; |
|
494 | } |
||
495 | |||
496 | /** |
||
497 | * {@inheritDoc} |
||
498 | */ |
||
499 | 24 | public function getAlterTableSQL(TableDiff $diff) |
|
500 | { |
||
501 | 24 | $sql = []; |
|
502 | 24 | $columnSql = []; |
|
503 | 24 | $commentsSQL = []; |
|
504 | |||
505 | 24 | $queryParts = []; |
|
506 | 24 | foreach ($diff->addedColumns as $column) { |
|
507 | 4 | if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { |
|
508 | continue; |
||
509 | } |
||
510 | |||
511 | 4 | $columnDef = $column->toArray(); |
|
512 | 4 | $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); |
|
513 | |||
514 | // Adding non-nullable columns to a table requires a default value to be specified. |
||
515 | 4 | if ( ! empty($columnDef['notnull']) && |
|
516 | 4 | ! isset($columnDef['default']) && |
|
517 | 4 | empty($columnDef['autoincrement']) |
|
518 | ) { |
||
519 | 3 | $queryPart .= ' WITH DEFAULT'; |
|
520 | } |
||
521 | |||
522 | 4 | $queryParts[] = $queryPart; |
|
523 | |||
524 | 4 | $comment = $this->getColumnComment($column); |
|
525 | |||
526 | 4 | View Code Duplication | if (null !== $comment && '' !== $comment) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
527 | 1 | $commentsSQL[] = $this->getCommentOnColumnSQL( |
|
528 | 1 | $diff->getName($this)->getQuotedName($this), |
|
529 | 1 | $column->getQuotedName($this), |
|
530 | 4 | $comment |
|
531 | ); |
||
532 | } |
||
533 | } |
||
534 | |||
535 | 24 | View Code Duplication | foreach ($diff->removedColumns as $column) { |
536 | 3 | if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { |
|
537 | continue; |
||
538 | } |
||
539 | |||
540 | 3 | $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); |
|
541 | } |
||
542 | |||
543 | 24 | foreach ($diff->changedColumns as $columnDiff) { |
|
544 | 17 | if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { |
|
545 | continue; |
||
546 | } |
||
547 | |||
548 | 17 | if ($columnDiff->hasChanged('comment')) { |
|
549 | 1 | $commentsSQL[] = $this->getCommentOnColumnSQL( |
|
550 | 1 | $diff->getName($this)->getQuotedName($this), |
|
551 | 1 | $columnDiff->column->getQuotedName($this), |
|
552 | 1 | $this->getColumnComment($columnDiff->column) |
|
553 | ); |
||
554 | |||
555 | 1 | if (count($columnDiff->changedProperties) === 1) { |
|
556 | 1 | continue; |
|
557 | } |
||
558 | } |
||
559 | |||
560 | 16 | $this->gatherAlterColumnSQL($diff->fromTable, $columnDiff, $sql, $queryParts); |
|
561 | } |
||
562 | |||
563 | 24 | View Code Duplication | foreach ($diff->renamedColumns as $oldColumnName => $column) { |
564 | 4 | if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { |
|
565 | continue; |
||
566 | } |
||
567 | |||
568 | 4 | $oldColumnName = new Identifier($oldColumnName); |
|
569 | |||
570 | 4 | $queryParts[] = 'RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . |
|
571 | 4 | ' TO ' . $column->getQuotedName($this); |
|
572 | } |
||
573 | |||
574 | 24 | $tableSql = []; |
|
575 | |||
576 | 24 | if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { |
|
577 | 24 | if (count($queryParts) > 0) { |
|
578 | 18 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(" ", $queryParts); |
|
579 | } |
||
580 | |||
581 | // Some table alteration operations require a table reorganization. |
||
582 | 24 | if ( ! empty($diff->removedColumns) || ! empty($diff->changedColumns)) { |
|
583 | 17 | $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName($this)->getQuotedName($this) . "')"; |
|
584 | } |
||
585 | |||
586 | 24 | $sql = array_merge($sql, $commentsSQL); |
|
587 | |||
588 | 24 | if ($diff->newName !== false) { |
|
589 | 2 | $sql[] = 'RENAME TABLE ' . $diff->getName($this)->getQuotedName($this) . ' TO ' . $diff->getNewName()->getQuotedName($this); |
|
590 | } |
||
591 | |||
592 | 24 | $sql = array_merge( |
|
593 | 24 | $this->getPreAlterTableIndexForeignKeySQL($diff), |
|
594 | 24 | $sql, |
|
595 | 24 | $this->getPostAlterTableIndexForeignKeySQL($diff) |
|
596 | ); |
||
597 | } |
||
598 | |||
599 | 24 | return array_merge($sql, $tableSql, $columnSql); |
|
600 | } |
||
601 | |||
602 | /** |
||
603 | * Gathers the table alteration SQL for a given column diff. |
||
604 | * |
||
605 | * @param Table $table The table to gather the SQL for. |
||
606 | * @param ColumnDiff $columnDiff The column diff to evaluate. |
||
607 | * @param array $sql The sequence of table alteration statements to fill. |
||
608 | * @param array $queryParts The sequence of column alteration clauses to fill. |
||
609 | */ |
||
610 | 16 | private function gatherAlterColumnSQL(Table $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) |
|
611 | { |
||
612 | 16 | $alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff); |
|
613 | |||
614 | 16 | if (empty($alterColumnClauses)) { |
|
615 | 2 | return; |
|
616 | } |
||
617 | |||
618 | // If we have a single column alteration, we can append the clause to the main query. |
||
619 | 14 | if (count($alterColumnClauses) === 1) { |
|
620 | 13 | $queryParts[] = current($alterColumnClauses); |
|
621 | |||
622 | 13 | return; |
|
623 | } |
||
624 | |||
625 | // We have multiple alterations for the same column, |
||
626 | // so we need to trigger a complete ALTER TABLE statement |
||
627 | // for each ALTER COLUMN clause. |
||
628 | 1 | foreach ($alterColumnClauses as $alterColumnClause) { |
|
629 | 1 | $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ' . $alterColumnClause; |
|
630 | } |
||
631 | 1 | } |
|
632 | |||
633 | /** |
||
634 | * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. |
||
635 | * |
||
636 | * @param ColumnDiff $columnDiff The column diff to evaluate. |
||
637 | * |
||
638 | * @return array |
||
639 | */ |
||
640 | 16 | private function getAlterColumnClausesSQL(ColumnDiff $columnDiff) |
|
641 | { |
||
642 | 16 | $column = $columnDiff->column->toArray(); |
|
643 | |||
644 | 16 | $alterClause = 'ALTER COLUMN ' . $columnDiff->column->getQuotedName($this); |
|
645 | |||
646 | 16 | if ($column['columnDefinition']) { |
|
647 | 1 | return [$alterClause . ' ' . $column['columnDefinition']]; |
|
648 | } |
||
649 | |||
650 | 15 | $clauses = []; |
|
651 | |||
652 | 15 | if ($columnDiff->hasChanged('type') || |
|
653 | 12 | $columnDiff->hasChanged('length') || |
|
654 | 11 | $columnDiff->hasChanged('precision') || |
|
655 | 10 | $columnDiff->hasChanged('scale') || |
|
656 | 15 | $columnDiff->hasChanged('fixed') |
|
657 | ) { |
||
658 | 8 | $clauses[] = $alterClause . ' SET DATA TYPE ' . $column['type']->getSQLDeclaration($column, $this); |
|
659 | } |
||
660 | |||
661 | 15 | if ($columnDiff->hasChanged('notnull')) { |
|
662 | 4 | $clauses[] = $column['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL'; |
|
663 | } |
||
664 | |||
665 | 15 | if ($columnDiff->hasChanged('default')) { |
|
666 | 4 | if (isset($column['default'])) { |
|
667 | 3 | $defaultClause = $this->getDefaultValueDeclarationSQL($column); |
|
668 | |||
669 | 3 | if ($defaultClause) { |
|
670 | 3 | $clauses[] = $alterClause . ' SET' . $defaultClause; |
|
671 | } |
||
672 | } else { |
||
673 | 1 | $clauses[] = $alterClause . ' DROP DEFAULT'; |
|
674 | } |
||
675 | } |
||
676 | |||
677 | 15 | return $clauses; |
|
678 | } |
||
679 | |||
680 | /** |
||
681 | * {@inheritDoc} |
||
682 | */ |
||
683 | 24 | protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) |
|
684 | { |
||
685 | 24 | $sql = []; |
|
686 | 24 | $table = $diff->getName($this)->getQuotedName($this); |
|
687 | |||
688 | 24 | foreach ($diff->removedIndexes as $remKey => $remIndex) { |
|
689 | foreach ($diff->addedIndexes as $addKey => $addIndex) { |
||
690 | if ($remIndex->getColumns() == $addIndex->getColumns()) { |
||
691 | if ($remIndex->isPrimary()) { |
||
692 | $sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; |
||
693 | } elseif ($remIndex->isUnique()) { |
||
694 | $sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this); |
||
695 | } else { |
||
696 | $sql[] = $this->getDropIndexSQL($remIndex, $table); |
||
697 | } |
||
698 | |||
699 | $sql[] = $this->getCreateIndexSQL($addIndex, $table); |
||
700 | |||
701 | unset($diff->removedIndexes[$remKey]); |
||
702 | unset($diff->addedIndexes[$addKey]); |
||
703 | |||
704 | break; |
||
705 | } |
||
706 | } |
||
707 | } |
||
708 | |||
709 | 24 | $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); |
|
710 | |||
711 | 24 | return $sql; |
|
712 | } |
||
713 | |||
714 | /** |
||
715 | * {@inheritdoc} |
||
716 | */ |
||
717 | 5 | View Code Duplication | protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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.
Loading history...
|
|||
718 | { |
||
719 | 5 | if (strpos($tableName, '.') !== false) { |
|
720 | 2 | list($schema) = explode('.', $tableName); |
|
721 | 2 | $oldIndexName = $schema . '.' . $oldIndexName; |
|
722 | } |
||
723 | |||
724 | 5 | return ['RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this)]; |
|
725 | } |
||
726 | |||
727 | /** |
||
728 | * {@inheritDoc} |
||
729 | */ |
||
730 | 22 | public function getDefaultValueDeclarationSQL($field) |
|
731 | { |
||
732 | 22 | if ( ! empty($field['autoincrement'])) { |
|
733 | 2 | return ''; |
|
734 | } |
||
735 | |||
736 | 21 | if (isset($field['version']) && $field['version']) { |
|
737 | if ((string) $field['type'] != "DateTime") { |
||
738 | $field['default'] = "1"; |
||
739 | } |
||
740 | } |
||
741 | |||
742 | 21 | return parent::getDefaultValueDeclarationSQL($field); |
|
743 | } |
||
744 | |||
745 | /** |
||
746 | * {@inheritDoc} |
||
747 | */ |
||
748 | public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) |
||
749 | { |
||
750 | return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)'; |
||
751 | } |
||
752 | |||
753 | /** |
||
754 | * {@inheritDoc} |
||
755 | */ |
||
756 | 1 | public function getCreateTemporaryTableSnippetSQL() |
|
757 | { |
||
758 | 1 | return "DECLARE GLOBAL TEMPORARY TABLE"; |
|
759 | } |
||
760 | |||
761 | /** |
||
762 | * {@inheritDoc} |
||
763 | */ |
||
764 | public function getTemporaryTableName($tableName) |
||
765 | { |
||
766 | return "SESSION." . $tableName; |
||
767 | } |
||
768 | |||
769 | /** |
||
770 | * {@inheritDoc} |
||
771 | */ |
||
772 | 1 | protected function doModifyLimitQuery($query, $limit, $offset = null) |
|
773 | { |
||
774 | 1 | $where = []; |
|
775 | |||
776 | 1 | if ($offset > 0) { |
|
777 | 1 | $where[] = sprintf('db22.DC_ROWNUM >= %d', $offset + 1); |
|
778 | } |
||
779 | |||
780 | 1 | if ($limit !== null) { |
|
781 | 1 | $where[] = sprintf('db22.DC_ROWNUM <= %d', $offset + $limit); |
|
782 | } |
||
783 | |||
784 | 1 | if (empty($where)) { |
|
785 | 1 | return $query; |
|
786 | } |
||
787 | |||
788 | // Todo OVER() needs ORDER BY data! |
||
789 | 1 | return sprintf( |
|
790 | 1 | 'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (%s) db21) db22 WHERE %s', |
|
791 | 1 | $query, |
|
792 | 1 | implode(' AND ', $where) |
|
793 | ); |
||
794 | } |
||
795 | |||
796 | /** |
||
797 | * {@inheritDoc} |
||
798 | */ |
||
799 | 1 | View Code Duplication | public function getLocateExpression($str, $substr, $startPos = false) |
800 | { |
||
801 | 1 | if ($startPos == false) { |
|
802 | 1 | return 'LOCATE(' . $substr . ', ' . $str . ')'; |
|
803 | } |
||
804 | |||
805 | 1 | return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; |
|
806 | } |
||
807 | |||
808 | /** |
||
809 | * {@inheritDoc} |
||
810 | */ |
||
811 | 1 | View Code Duplication | public function getSubstringExpression($value, $from, $length = null) |
812 | { |
||
813 | 1 | if ($length === null) { |
|
814 | 1 | return 'SUBSTR(' . $value . ', ' . $from . ')'; |
|
815 | } |
||
816 | |||
817 | 1 | return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')'; |
|
818 | } |
||
819 | |||
820 | /** |
||
821 | * {@inheritDoc} |
||
822 | */ |
||
823 | 1 | public function supportsIdentityColumns() |
|
824 | { |
||
825 | 1 | return true; |
|
826 | } |
||
827 | |||
828 | /** |
||
829 | * {@inheritDoc} |
||
830 | */ |
||
831 | 1 | public function prefersIdentityColumns() |
|
832 | { |
||
833 | 1 | return true; |
|
834 | } |
||
835 | |||
836 | /** |
||
837 | * {@inheritDoc} |
||
838 | * |
||
839 | * DB2 returns all column names in SQL result sets in uppercase. |
||
840 | */ |
||
841 | 1 | public function getSQLResultCasing($column) |
|
842 | { |
||
843 | 1 | return strtoupper($column); |
|
844 | } |
||
845 | |||
846 | /** |
||
847 | * {@inheritDoc} |
||
848 | */ |
||
849 | 1 | public function getForUpdateSQL() |
|
850 | { |
||
851 | 1 | return ' WITH RR USE AND KEEP UPDATE LOCKS'; |
|
852 | } |
||
853 | |||
854 | /** |
||
855 | * {@inheritDoc} |
||
856 | */ |
||
857 | public function getDummySelectSQL() |
||
858 | { |
||
859 | return 'SELECT 1 FROM sysibm.sysdummy1'; |
||
860 | } |
||
861 | |||
862 | /** |
||
863 | * {@inheritDoc} |
||
864 | * |
||
865 | * DB2 supports savepoints, but they work semantically different than on other vendor platforms. |
||
866 | * |
||
867 | * TODO: We have to investigate how to get DB2 up and running with savepoints. |
||
868 | */ |
||
869 | 1 | public function supportsSavepoints() |
|
870 | { |
||
871 | 1 | return false; |
|
872 | } |
||
873 | |||
874 | /** |
||
875 | * {@inheritDoc} |
||
876 | */ |
||
877 | 52 | protected function getReservedKeywordsClass() |
|
878 | { |
||
879 | 52 | return Keywords\DB2Keywords::class; |
|
880 | } |
||
881 | } |
||
882 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.