DrizzlePlatform::getAlterTableSQL()   F
last analyzed

Complexity

Conditions 15
Paths 648

Size

Total Lines 78
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 240

Importance

Changes 0
Metric Value
eloc 44
dl 0
loc 78
ccs 0
cts 45
cp 0
rs 2.2388
c 0
b 0
f 0
cc 15
nc 648
nop 1
crap 240

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Doctrine\DBAL\Platforms;
4
5
use Doctrine\DBAL\Schema\Identifier;
6
use Doctrine\DBAL\Schema\Index;
7
use Doctrine\DBAL\Schema\Table;
8
use Doctrine\DBAL\Schema\TableDiff;
9
use Doctrine\DBAL\Types\BinaryType;
10
use InvalidArgumentException;
11
use function array_merge;
12
use function array_unique;
13
use function array_values;
14
use function count;
15
use function func_get_args;
16
use function implode;
17
use function is_array;
18
use function is_bool;
19
use function is_numeric;
20
use function is_string;
21
use function sprintf;
22
use function trim;
23
24
/**
25
 * Drizzle platform
26
 */
27
class DrizzlePlatform extends AbstractPlatform
28
{
29
    /**
30
     * {@inheritDoc}
31
     */
32
    public function getName()
33
    {
34
        return 'drizzle';
35
    }
36
37
    /**
38
     * {@inheritDoc}
39
     */
40
    public function getIdentifierQuoteCharacter()
41
    {
42
        return '`';
43
    }
44
45
    /**
46
     * {@inheritDoc}
47
     */
48
    public function getConcatExpression()
49
    {
50
        $args = func_get_args();
51
52
        return 'CONCAT(' . implode(', ', (array) $args) . ')';
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit)
59
    {
60
        $function = $operator === '+' ? 'DATE_ADD' : 'DATE_SUB';
61
62
        return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')';
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     */
68
    public function getDateDiffExpression($date1, $date2)
69
    {
70
        return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')';
71
    }
72
73
    /**
74
     * {@inheritDoc}
75
     */
76
    public function getBooleanTypeDeclarationSQL(array $field)
77
    {
78
        return 'BOOLEAN';
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     */
84
    public function getIntegerTypeDeclarationSQL(array $field)
85
    {
86
        return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
87
    }
88
89
    /**
90
     * {@inheritDoc}
91
     */
92
    protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
93
    {
94
        $autoinc = '';
95
        if (! empty($columnDef['autoincrement'])) {
96
            $autoinc = ' AUTO_INCREMENT';
97
        }
98
99
        return $autoinc;
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     */
105
    public function getBigIntTypeDeclarationSQL(array $field)
106
    {
107
        return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     */
113
    public function getSmallIntTypeDeclarationSQL(array $field)
114
    {
115
        return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
116
    }
117
118
    /**
119
     * {@inheritDoc}
120
     */
121
    protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
122
    {
123
        return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)';
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
130
    {
131
        return 'VARBINARY(' . ($length ?: 255) . ')';
132
    }
133
134
    /**
135
     * {@inheritDoc}
136
     */
137
    protected function initializeDoctrineTypeMappings()
138
    {
139
        $this->doctrineTypeMapping = [
140
            'boolean'       => 'boolean',
141
            'varchar'       => 'string',
142
            'varbinary'     => 'binary',
143
            'integer'       => 'integer',
144
            'blob'          => 'blob',
145
            'decimal'       => 'decimal',
146
            'datetime'      => 'datetime',
147
            'date'          => 'date',
148
            'time'          => 'time',
149
            'text'          => 'text',
150
            'timestamp'     => 'datetime',
151
            'double'        => 'float',
152
            'bigint'        => 'bigint',
153
        ];
154
    }
155
156
    /**
157
     * {@inheritDoc}
158
     */
159
    public function getClobTypeDeclarationSQL(array $field)
160
    {
161
        return 'TEXT';
162
    }
163
164
    /**
165
     * {@inheritDoc}
166
     */
167
    public function getBlobTypeDeclarationSQL(array $field)
168
    {
169
        return 'BLOB';
170
    }
171
172
    /**
173
     * {@inheritDoc}
174
     */
175
    public function getCreateDatabaseSQL($name)
176
    {
177
        return 'CREATE DATABASE ' . $name;
178
    }
179
180
    /**
181
     * {@inheritDoc}
182
     */
183
    public function getDropDatabaseSQL($name)
184
    {
185
        return 'DROP DATABASE ' . $name;
186
    }
187
188
    /**
189
     * {@inheritDoc}
190
     */
191
    protected function _getCreateTableSQL($tableName, array $columns, array $options = [])
192
    {
193
        $queryFields = $this->getColumnDeclarationListSQL($columns);
194
195
        if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
196
            foreach ($options['uniqueConstraints'] as $index => $definition) {
197
                $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition);
198
            }
199
        }
200
201
        // add all indexes
202
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
203
            foreach ($options['indexes'] as $index => $definition) {
204
                $queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
205
            }
206
        }
207
208
        // attach all primary keys
209
        if (isset($options['primary']) && ! empty($options['primary'])) {
210
            $keyColumns   = array_unique(array_values($options['primary']));
211
            $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
212
        }
213
214
        $query = 'CREATE ';
215
216
        if (! empty($options['temporary'])) {
217
            $query .= 'TEMPORARY ';
218
        }
219
220
        $query .= 'TABLE ' . $tableName . ' (' . $queryFields . ') ';
221
        $query .= $this->buildTableOptions($options);
222
        $query .= $this->buildPartitionOptions($options);
223
224
        $sql = [$query];
225
226
        if (isset($options['foreignKeys'])) {
227
            foreach ((array) $options['foreignKeys'] as $definition) {
228
                $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
229
            }
230
        }
231
232
        return $sql;
233
    }
234
235
    /**
236
     * Build SQL for table options
237
     *
238
     * @param mixed[] $options
239
     *
240
     * @return string
241
     */
242
    private function buildTableOptions(array $options)
243
    {
244
        if (isset($options['table_options'])) {
245
            return $options['table_options'];
246
        }
247
248
        $tableOptions = [];
249
250
        // Collate
251
        if (! isset($options['collate'])) {
252
            $options['collate'] = 'utf8_unicode_ci';
253
        }
254
255
        $tableOptions[] = sprintf('COLLATE %s', $options['collate']);
256
257
        // Engine
258
        if (! isset($options['engine'])) {
259
            $options['engine'] = 'InnoDB';
260
        }
261
262
        $tableOptions[] = sprintf('ENGINE = %s', $options['engine']);
263
264
        // Auto increment
265
        if (isset($options['auto_increment'])) {
266
            $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']);
267
        }
268
269
        // Comment
270
        if (isset($options['comment'])) {
271
            $comment = trim($options['comment'], " '");
272
273
            $tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($comment));
274
        }
275
276
        // Row format
277
        if (isset($options['row_format'])) {
278
            $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']);
279
        }
280
281
        return implode(' ', $tableOptions);
282
    }
283
284
    /**
285
     * Build SQL for partition options.
286
     *
287
     * @param mixed[] $options
288
     *
289
     * @return string
290
     */
291
    private function buildPartitionOptions(array $options)
292
    {
293
        return isset($options['partition_options'])
294
            ? ' ' . $options['partition_options']
295
            : '';
296
    }
297
298
    /**
299
     * {@inheritDoc}
300
     */
301
    public function getListDatabasesSQL()
302
    {
303
        return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='LOCAL'";
304
    }
305
306
    /**
307
     * {@inheritDoc}
308
     */
309
    protected function getReservedKeywordsClass()
310
    {
311
        return Keywords\DrizzleKeywords::class;
312
    }
313
314
    /**
315
     * {@inheritDoc}
316
     */
317
    public function getListTablesSQL()
318
    {
319
        return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()";
320
    }
321
322
    /**
323
     * {@inheritDoc}
324
     */
325
    public function getListTableColumnsSQL($table, $database = null)
326
    {
327
        if ($database) {
328
            $databaseSQL = $this->quoteStringLiteral($database);
329
        } else {
330
            $databaseSQL = 'DATABASE()';
331
        }
332
333
        return 'SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT,' .
334
               ' NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME' .
335
               ' FROM DATA_DICTIONARY.COLUMNS' .
336
               ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME = ' . $this->quoteStringLiteral($table);
337
    }
338
339
    /**
340
     * {@inheritDoc}
341
     */
342
    public function getListTableForeignKeysSQL($table, $database = null)
343
    {
344
        if ($database) {
345
            $databaseSQL = $this->quoteStringLiteral($database);
346
        } else {
347
            $databaseSQL = 'DATABASE()';
348
        }
349
350
        return 'SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE' .
351
               ' FROM DATA_DICTIONARY.FOREIGN_KEYS' .
352
               ' WHERE CONSTRAINT_SCHEMA=' . $databaseSQL . ' AND CONSTRAINT_TABLE=' . $this->quoteStringLiteral($table);
353
    }
354
355
    /**
356
     * {@inheritDoc}
357
     */
358
    public function getListTableIndexesSQL($table, $database = null)
359
    {
360
        if ($database) {
361
            $databaseSQL = $this->quoteStringLiteral($database);
362
        } else {
363
            $databaseSQL = 'DATABASE()';
364
        }
365
366
        return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" .
367
               ' FROM DATA_DICTIONARY.INDEX_PARTS' .
368
               ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME=' . $this->quoteStringLiteral($table);
369
    }
370
371
    /**
372
     * {@inheritDoc}
373
     */
374
    public function prefersIdentityColumns()
375
    {
376
        return true;
377
    }
378
379
    /**
380
     * {@inheritDoc}
381
     */
382
    public function supportsIdentityColumns()
383
    {
384
        return true;
385
    }
386
387
    /**
388
     * {@inheritDoc}
389
     */
390
    public function supportsInlineColumnComments()
391
    {
392
        return true;
393
    }
394
395
    /**
396
     * {@inheritDoc}
397
     */
398
    public function supportsViews()
399
    {
400
        return false;
401
    }
402
403
    /**
404
     * {@inheritdoc}
405
     */
406
    public function supportsColumnCollation()
407
    {
408
        return true;
409
    }
410
411
    /**
412
     * {@inheritDoc}
413
     */
414
    public function getDropIndexSQL($index, $table = null)
415
    {
416
        if ($index instanceof Index) {
417
            $indexName = $index->getQuotedName($this);
418
        } elseif (is_string($index)) {
419
            $indexName = $index;
420
        } else {
421
            throw new InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
422
        }
423
424
        if ($table instanceof Table) {
425
            $table = $table->getQuotedName($this);
426
        } elseif (! is_string($table)) {
427
            throw new InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
428
        }
429
430
        if ($index instanceof Index && $index->isPrimary()) {
431
            // drizzle primary keys are always named "PRIMARY",
432
            // so we cannot use them in statements because of them being keyword.
433
            return $this->getDropPrimaryKeySQL($table);
434
        }
435
436
        return 'DROP INDEX ' . $indexName . ' ON ' . $table;
437
    }
438
439
    /**
440
     * {@inheritDoc}
441
     */
442
    protected function getDropPrimaryKeySQL($table)
443
    {
444
        return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
445
    }
446
447
    /**
448
     * {@inheritDoc}
449
     */
450
    public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
451
    {
452
        if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) {
453
            return 'TIMESTAMP';
454
        }
455
456
        return 'DATETIME';
457
    }
458
459
    /**
460
     * {@inheritDoc}
461
     */
462
    public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
463
    {
464
        return 'TIME';
465
    }
466
467
    /**
468
     * {@inheritDoc}
469
     */
470
    public function getDateTypeDeclarationSQL(array $fieldDeclaration)
471
    {
472
        return 'DATE';
473
    }
474
475
    /**
476
     * {@inheritDoc}
477
     */
478
    public function getAlterTableSQL(TableDiff $diff)
479
    {
480
        $columnSql  = [];
481
        $queryParts = [];
482
483
        if ($diff->newName !== false) {
484
            $queryParts[] =  'RENAME TO ' . $diff->getNewName()->getQuotedName($this);
485
        }
486
487
        foreach ($diff->addedColumns as $column) {
488
            if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
489
                continue;
490
            }
491
492
            $columnArray            = $column->toArray();
493
            $columnArray['comment'] = $this->getColumnComment($column);
494
            $queryParts[]           = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
495
        }
496
497
        foreach ($diff->removedColumns as $column) {
498
            if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
499
                continue;
500
            }
501
502
            $queryParts[] =  'DROP ' . $column->getQuotedName($this);
503
        }
504
505
        foreach ($diff->changedColumns as $columnDiff) {
506
            if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
507
                continue;
508
            }
509
510
            $column      = $columnDiff->column;
511
            $columnArray = $column->toArray();
512
513
            // Do not generate column alteration clause if type is binary and only fixed property has changed.
514
            // Drizzle only supports binary type columns with variable length.
515
            // Avoids unnecessary table alteration statements.
516
            if ($columnArray['type'] instanceof BinaryType &&
517
                $columnDiff->hasChanged('fixed') &&
518
                count($columnDiff->changedProperties) === 1
519
            ) {
520
                continue;
521
            }
522
523
            $columnArray['comment'] = $this->getColumnComment($column);
524
            $queryParts[]           =  'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' '
525
                    . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
526
        }
527
528
        foreach ($diff->renamedColumns as $oldColumnName => $column) {
529
            if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
530
                continue;
531
            }
532
533
            $oldColumnName = new Identifier($oldColumnName);
534
535
            $columnArray            = $column->toArray();
536
            $columnArray['comment'] = $this->getColumnComment($column);
537
            $queryParts[]           =  'CHANGE ' . $oldColumnName->getQuotedName($this) . ' '
538
                    . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
539
        }
540
541
        $sql      = [];
542
        $tableSql = [];
543
544
        if (! $this->onSchemaAlterTable($diff, $tableSql)) {
545
            if (count($queryParts) > 0) {
546
                $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts);
547
            }
548
            $sql = array_merge(
549
                $this->getPreAlterTableIndexForeignKeySQL($diff),
550
                $sql,
551
                $this->getPostAlterTableIndexForeignKeySQL($diff)
552
            );
553
        }
554
555
        return array_merge($sql, $tableSql, $columnSql);
556
    }
557
558
    /**
559
     * {@inheritDoc}
560
     */
561
    public function getDropTemporaryTableSQL($table)
562
    {
563
        if ($table instanceof Table) {
564
            $table = $table->getQuotedName($this);
565
        } elseif (! is_string($table)) {
566
            throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
567
        }
568
569
        return 'DROP TEMPORARY TABLE ' . $table;
570
    }
571
572
    /**
573
     * {@inheritDoc}
574
     */
575
    public function convertBooleans($item)
576
    {
577
        if (is_array($item)) {
578
            foreach ($item as $key => $value) {
579
                if (! is_bool($value) && ! is_numeric($item)) {
580
                    continue;
581
                }
582
583
                $item[$key] = $value ? 'true' : 'false';
584
            }
585
        } elseif (is_bool($item) || is_numeric($item)) {
586
            $item = $item ? 'true' : 'false';
587
        }
588
589
        return $item;
590
    }
591
592
    /**
593
     * {@inheritDoc}
594
     */
595
    public function getLocateExpression($str, $substr, $startPos = false)
596
    {
597
        if ($startPos === false) {
598
            return 'LOCATE(' . $substr . ', ' . $str . ')';
599
        }
600
601
        return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')';
602
    }
603
604
    /**
605
     * {@inheritDoc}
606
     *
607
     * @deprecated Use application-generated UUIDs instead
608
     */
609
    public function getGuidExpression()
610
    {
611
        return 'UUID()';
612
    }
613
614
    /**
615
     * {@inheritDoc}
616
     */
617
    public function getRegexpExpression()
618
    {
619
        return 'RLIKE';
620
    }
621
}
622