Failed Conditions
Pull Request — master (#2929)
by Alexander
62:06
created

DrizzlePlatform::getDropPrimaryKeySQL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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