Passed
Pull Request — main (#122)
by Andreas
12:10
created

CratePlatform::buildTableOptions()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.0312

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 15
ccs 7
cts 8
cp 0.875
rs 10
cc 4
nc 5
nop 1
crap 4.0312
1
<?php
2
/**
3
 * Licensed to CRATE Technology GmbH("Crate") under one or more contributor
4
 * license agreements.  See the NOTICE file distributed with this work for
5
 * additional information regarding copyright ownership.  Crate licenses
6
 * this file to you under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.  You may
8
 * obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
15
 * License for the specific language governing permissions and limitations
16
 * under the License.
17
 *
18
 * However, if you have executed another commercial license agreement
19
 * with Crate these terms will supersede the license and you may use the
20
 * software solely pursuant to the terms of the relevant commercial agreement.
21
 */
22
namespace Crate\DBAL\Platforms;
23
24
use Crate\DBAL\Types\MapType;
25
use Crate\DBAL\Types\TimestampType;
26
use Doctrine\DBAL\DBALException;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\DBALException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs;
28
use Doctrine\DBAL\Event\SchemaCreateTableEventArgs;
29
use Doctrine\DBAL\Events;
30
use Doctrine\DBAL\Platforms\AbstractPlatform;
31
use Doctrine\DBAL\Schema\Identifier;
32
use Doctrine\DBAL\Schema\Index;
33
use Doctrine\DBAL\Schema\Table;
34
use Doctrine\DBAL\Schema\TableDiff;
35
use Doctrine\DBAL\Types\Type;
36
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
37
use InvalidArgumentException;
38
39
class CratePlatform extends AbstractPlatform
40
{
41
42
    const TIMESTAMP_FORMAT =  'Y-m-d\TH:i:s';
43
    const TIMESTAMP_FORMAT_TZ =  'Y-m-d\TH:i:sO';
44
    const TABLE_WHERE_CLAUSE_FORMAT = '%s.table_name = %s AND %s.schema_name = %s';
45
46
    /**
47
     * {@inheritDoc}
48
     */
49 254
    public function __construct()
50
    {
51 254
        parent::__construct();
0 ignored issues
show
Bug introduced by
The method __construct() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. It seems like you code against a sub-type of Doctrine\DBAL\Platforms\AbstractPlatform such as Crate\DBAL\Platforms\CratePlatform. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
        parent::/** @scrutinizer ignore-call */ 
52
                __construct();
Loading history...
52 254
        $this->initializeDoctrineTypeMappings();
53 254
        if (!Type::hasType(MapType::NAME)) {
54
            Type::addType(MapType::NAME, 'Crate\DBAL\Types\MapType');
55
        }
56 254
        if (!Type::hasType(TimestampType::NAME)) {
57
            Type::addType(TimestampType::NAME, 'Crate\DBAL\Types\TimestampType');
58
        }
59 254
        Type::overrideType('array', 'Crate\DBAL\Types\ArrayType');
60
    }
61
62
    /**
63
     * {@inheritDoc}
64
     */
65 2
    public function getSubstringExpression($value, $from = 0, $length = null)
66
    {
67 2
        if ($length === null) {
68 2
            return 'SUBSTR(' . $value . ', ' . $from . ')';
69
        }
70
71 2
        return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')';
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     */
77 2
    public function getNowExpression()
78
    {
79 2
        throw DBALException::notSupported(__METHOD__);
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85 2
    public function getRegexpExpression()
86
    {
87 2
        return 'LIKE';
88
    }
89
90
    /**
91
     * {@inheritDoc}
92
     */
93 2
    public function getDateDiffExpression($date1, $date2)
94
    {
95 2
        throw DBALException::notSupported(__METHOD__);
96
    }
97
98
    /**
99
     * {@inheritDoc}
100
     */
101 6
    public function supportsSequences()
102
    {
103 6
        return false;
104
    }
105
106
    /**
107
     * If we want to support Schemas, we need to implement
108
     * getListNamespacesSQL and getCreateSchemaSQL methods
109
     *
110
     * {@inheritDoc}
111
     */
112 6
    public function supportsSchemas()
113
    {
114 6
        return false;
115
    }
116
117
    /**
118
     * {@inheritDoc}
119
     */
120 2
    public function supportsIdentityColumns()
121
    {
122 2
        return true;
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128 2
    public function supportsIndexes()
129
    {
130 2
        return false;
131
    }
132
133
    /**
134
     * {@inheritDoc}
135
     */
136 118
    public function supportsCommentOnStatement()
137
    {
138 118
        return false;
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144 14
    public function supportsForeignKeyConstraints()
145
    {
146 14
        return false;
147
    }
148
149
    /**
150
     * {@inheritDoc}
151
     */
152 2
    public function supportsForeignKeyOnUpdate()
153
    {
154 2
        return false;
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160 2
    public function supportsViews()
161
    {
162 2
        return false;
163
    }
164
165
    /**
166
     * {@inheritDoc}
167
     */
168 2
    public function prefersSequences()
169
    {
170 2
        return false;
171
    }
172
173
    /**
174
     * {@inheritDoc}
175
     */
176 2
    public function getListDatabasesSQL()
177
    {
178 2
        throw DBALException::notSupported(__METHOD__);
179
    }
180
181
    /**
182
     * {@inheritDoc}
183
     */
184
    public function getListTablesSQL()
185
    {
186
        return "SELECT table_name, schema_name FROM information_schema.tables " .
187
               "WHERE schema_name = 'doc' OR schema_name = 'blob'";
188
    }
189
190
    /**
191
     * {@inheritDoc}
192
     */
193 8
    public function getListTableColumnsSQL($table, $database = null)
194
    {
195 8
        return "SELECT * from information_schema.columns c " .
196 8
               "WHERE " . $this->getTableWhereClause($table);
197
    }
198
199
    /**
200
     * {@inheritDoc}
201
     */
202
    public function getListTableConstraintsSQL($table, $database = null)
0 ignored issues
show
Unused Code introduced by
The parameter $database is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

202
    public function getListTableConstraintsSQL($table, /** @scrutinizer ignore-unused */ $database = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
203
    {
204
        return "SELECT c.constraint_name, c.constraint_type " .
205
               "FROM information_schema.table_constraints c " .
206
               "WHERE " . $this->getTableWhereClause($table) . " AND constraint_type = 'PRIMARY KEY'";
207
    }
208
209
    /**
210
     * {@inheritDoc}
211
     */
212 8
    public function getListTableIndexesSQL($table, $currentDatabase = null)
213
    {
214 8
        return "SELECT c.constraint_name, c.constraint_type, k.column_name " .
215 8
               "FROM information_schema.table_constraints c " .
216 8
               "JOIN information_schema.key_column_usage k on c.constraint_name = k.constraint_name " .
217 8
               "WHERE " . $this->getTableWhereClause($table);
218
    }
219
220 10
    private function getTableWhereClause($table, $tableAlias = 'c')
221
    {
222 10
        if (strpos($table, '.') !== false) {
223
            [$schema, $table] = explode('.', $table);
224
            $schema = $this->quoteStringLiteral($schema);
225
        } else {
226 10
            $schema = $this->quoteStringLiteral('doc');
227
        }
228
229 10
        $table = new Identifier($table);
230 10
        $table = $this->quoteStringLiteral($table->getName());
231
232 10
        return sprintf(
233 10
            $this->getTableWhereClauseFormat(),
234 10
            $tableAlias,
235 10
            $table,
236 10
            $tableAlias,
237 10
            $schema
238 10
        );
239
    }
240
241
    /**
242
     * Return sprintf format string for usage at getTableWhereClause
243
     *
244
     * @return string
245
     */
246
    protected function getTableWhereClauseFormat()
247
    {
248
        return self::TABLE_WHERE_CLAUSE_FORMAT;
249
    }
250
251
    /**
252
     * {@inheritDoc}
253
     */
254 10
    public function getAlterTableSQL(TableDiff $diff)
255
    {
256 10
        $sql = array();
257 10
        $commentsSQL = array();
258 10
        $columnSql = array();
259
260 10
        foreach ($diff->addedColumns as $column) {
261 4
            if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
262
                continue;
263
            }
264
265 4
            $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
266 4
            $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Schema\TableDiff::$name has been deprecated: Use {@see getOldTable()} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

266
            $sql[] = 'ALTER TABLE ' . /** @scrutinizer ignore-deprecated */ $diff->name . ' ' . $query;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
267 4
            if ($comment = $this->getColumnComment($column)) {
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Platforms\...orm::getColumnComment() has been deprecated: This method will be removed without replacement. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

267
            if ($comment = /** @scrutinizer ignore-deprecated */ $this->getColumnComment($column)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
268
                $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Schema\TableDiff::$name has been deprecated: Use {@see getOldTable()} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

268
                $commentsSQL[] = $this->getCommentOnColumnSQL(/** @scrutinizer ignore-deprecated */ $diff->name, $column->getName(), $comment);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
269
            }
270
        }
271
272 10
        if (count($diff->removedColumns) > 0) {
273
            throw DBALException::notSupported("Alter Table: drop columns");
274
        }
275 10
        if (count($diff->changedColumns) > 0) {
276
            throw DBALException::notSupported("Alter Table: change column options");
277
        }
278 10
        if (count($diff->renamedColumns) > 0) {
279
            throw DBALException::notSupported("Alter Table: rename columns");
280
        }
281
282 10
        $tableSql = array();
283
284 10
        if (!$this->onSchemaAlterTable($diff, $tableSql)) {
285 10
            if ($diff->newName !== false) {
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Schema\TableDiff::$newName has been deprecated: Rename tables via {@link AbstractSchemaManager::renameTable()} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

285
            if (/** @scrutinizer ignore-deprecated */ $diff->newName !== false) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
286
                throw DBALException::notSupported("Alter Table: rename table");
287
            }
288
289 10
            $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL);
0 ignored issues
show
Bug introduced by
The method _getAlterTableIndexForeignKeySQL() does not exist on Crate\DBAL\Platforms\CratePlatform. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

289
            $sql = array_merge($sql, $this->/** @scrutinizer ignore-call */ _getAlterTableIndexForeignKeySQL($diff), $commentsSQL);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
290
        }
291
292 10
        return array_merge($sql, $tableSql, $columnSql);
293
    }
294
295
    /**
296
     * {@inheritDoc}
297
     */
298 126
    public function getColumnDeclarationSQL($name, array $column)
299
    {
300 126
        if (isset($column['columnDefinition'])) {
301 68
            $columnDef = $this->getCustomTypeDeclarationSQL($column);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Platforms\...tomTypeDeclarationSQL() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

301
            $columnDef = /** @scrutinizer ignore-deprecated */ $this->getCustomTypeDeclarationSQL($column);
Loading history...
302
        } else {
303 124
            $typeDecl = $column['type']->getSqlDeclaration($column, $this);
304 124
            $columnDef = $typeDecl;
305
        }
306
307 126
        return $name . ' ' . $columnDef;
308
    }
309
310
    /**
311
     * Generate table index column declaration
312
     * @codeCoverageIgnore
313
     */
314
    public function getIndexDeclarationSQL($name, Index $index)
315
    {
316
        $columns = $index->getQuotedColumns($this);
317
        $name = new Identifier($name);
318
319
        if (count($columns) == 0) {
320
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
321
        }
322
323
        return 'INDEX ' . $name->getQuotedName($this) .
324
               ' USING FULLTEXT ('. $this->getIndexFieldDeclarationListSQL($columns) . ')';
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Platforms\...eldDeclarationListSQL() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

324
               ' USING FULLTEXT ('. /** @scrutinizer ignore-deprecated */ $this->getIndexFieldDeclarationListSQL($columns) . ')';
Loading history...
Bug introduced by
$columns of type string[] is incompatible with the type Doctrine\DBAL\Schema\Index expected by parameter $index of Doctrine\DBAL\Platforms\...eldDeclarationListSQL(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

324
               ' USING FULLTEXT ('. $this->getIndexFieldDeclarationListSQL(/** @scrutinizer ignore-type */ $columns) . ')';
Loading history...
325
    }
326
327
    /**
328
     * {@inheritDoc}
329
     *
330
     * Crate wants boolean values converted to the strings 'true'/'false'.
331
     */
332 4
    public function convertBooleans($item)
333
    {
334 4
        if (is_array($item)) {
335 2
            foreach ($item as $key => $value) {
336 2
                if (is_bool($value)) {
337 2
                    $item[$key] = ($value) ? 'true' : 'false';
338 2
                } elseif (is_numeric($value)) {
339 2
                    $item[$key] = ($value > 0) ? 'true' : 'false';
340
                }
341
            }
342
        } else {
343 4
            if (is_bool($item)) {
344 4
                $item = ($item) ? 'true' : 'false';
345 2
            } elseif (is_numeric($item)) {
346 2
                $item = ($item > 0) ? 'true' : 'false';
347
            }
348
        }
349
350 4
        return $item;
351
    }
352
353
    /**
354
     * {@inheritDoc}
355
     */
356 22
    public function getBooleanTypeDeclarationSQL(array $field)
357
    {
358 22
        return 'BOOLEAN';
359
    }
360
361
    /**
362
     * {@inheritDoc}
363
     */
364 114
    public function getIntegerTypeDeclarationSQL(array $field)
365
    {
366 114
        return 'INTEGER';
367
    }
368
369
    /**
370
     * {@inheritDoc}
371
     */
372
    public function getBigIntTypeDeclarationSQL(array $field)
373
    {
374
        return 'LONG';
375
    }
376
377
    /**
378
     * {@inheritDoc}
379
     */
380
    public function getSmallIntTypeDeclarationSQL(array $field)
381
    {
382
        return 'SHORT';
383
    }
384
385
    /**
386
     * {@inheritDoc}
387
     */
388
    public function getFloatDeclarationSQL(array $field)
389
    {
390
        return 'DOUBLE';
391
    }
392
393
    /**
394
     * {@inheritDoc}
395
     */
396
    public function getDecimalTypeDeclarationSQL(array $columnDef)
397
    {
398
        return 'DOUBLE';
399
    }
400
401
    /**
402
     * {@inheritDoc}
403
     */
404 52
    public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
405
    {
406 52
        return 'TIMESTAMP';
407
    }
408
409
    /**
410
     * {@inheritDoc}
411
     */
412 2
    public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
413
    {
414 2
        return 'TIMESTAMP';
415
    }
416
417
    /**
418
     * {@inheritDoc}
419
     */
420 2
    public function getDateTypeDeclarationSQL(array $fieldDeclaration)
421
    {
422 2
        return 'TIMESTAMP';
423
    }
424
425
    /**
426
     * {@inheritDoc}
427
     */
428 2
    public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
429
    {
430 2
        return 'TIMESTAMP';
431
    }
432
433
    /**
434
     * {@inheritDoc}
435
     */
436
    // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
437
    protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
438
    {
439
        return '';
440
    }
441
442
    /**
443
     * {@inheritDoc}
444
     */
445
    protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
446
    {
447
        return 'STRING';
448
    }
449
450
    /**
451
     * {@inheritDoc}
452
     */
453
    public function getClobTypeDeclarationSQL(array $field)
454
    {
455
        return 'STRING';
456
    }
457
458
    /**
459
     * {@inheritDoc}
460 4
     */
461
    public function getName()
462 4
    {
463
        return 'crate';
464
    }
465
466
    /**
467
     * {@inheritDoc}
468
     *
469
     * PostgreSQL returns all column names in SQL result sets in lowercase.
470 2
     */
471
    public function getSQLResultCasing($column)
472 2
    {
473
        return strtolower($column);
474
    }
475
476
    /**
477
     * {@inheritDoc}
478 4
     */
479
    public function getDateTimeTzFormatString()
480 4
    {
481
        return self::TIMESTAMP_FORMAT_TZ;
482
    }
483
484
    /**
485
     * {@inheritDoc}
486 10
     */
487
    public function getDateTimeFormatString()
488 10
    {
489
        return self::TIMESTAMP_FORMAT;
490
    }
491
492
    /**
493
     * {@inheritDoc}
494 2
     */
495
    public function getDateFormatString()
496 2
    {
497
        return self::TIMESTAMP_FORMAT;
498
    }
499
500
    /**
501
     * {@inheritDoc}
502 2
     */
503
    public function getTimeFormatString()
504 2
    {
505
        return self::TIMESTAMP_FORMAT;
506
    }
507
508
    /**
509
     * {@inheritDoc}
510 2
     */
511
    public function getTruncateTableSQL($tableName, $cascade = false)
512 2
    {
513
        throw DBALException::notSupported(__METHOD__);
514
    }
515
516
    /**
517
     * {@inheritDoc}
518 2
     */
519
    public function getReadLockSQL()
520 2
    {
521
        throw DBALException::notSupported(__METHOD__);
522
    }
523
524
    /**
525
     * {@inheritDoc}
526 20
     */
527
    protected function initializeDoctrineTypeMappings()
528 20
    {
529 20
        $this->doctrineTypeMapping = array(
530 20
            'short'         => 'smallint',
531 20
            'integer'       => 'integer',
532 20
            'long'          => 'bigint',
533 20
            'int'           => 'integer',
534 20
            'bool'          => 'boolean',
535 20
            'boolean'       => 'boolean',
536 20
            'string'        => 'string',
537 20
            'float'         => 'float',
538 20
            'double'        => 'float',
539 20
            'timestamp'     => 'timestamp',
540 20
            'object'        => 'map',
541 20
            'array'         => 'array',
542
        );
543
    }
544
545
    /**
546
     * {@inheritDoc}
547 12
     */
548
    public function getDoctrineTypeMapping($dbType)
549
    {
550 12
        // typed arrays will always end up in the same generic php array type
551 2
        if (substr_compare($dbType, 'array', -5) === 0) {
552
            $dbType = 'array';
553 12
        }
554
        return parent::getDoctrineTypeMapping($dbType);
555
    }
556
557
558
    /**
559
     * {@inheritDoc}
560 112
     */
561
    public function getVarcharMaxLength()
562 112
    {
563
        return PHP_INT_MAX;
564
    }
565
566
    /**
567
     * {@inheritDoc}
568 54
     */
569
    protected function getReservedKeywordsClass()
570 54
    {
571
        return 'Crate\DBAL\Platforms\Keywords\CrateKeywords';
572
    }
573
574
    /**
575
     * {@inheritDoc}
576 2
     */
577
    public function getBlobTypeDeclarationSQL(array $field)
578 2
    {
579
        throw DBALException::notSupported(__METHOD__);
580
    }
581
582
    /**
583
     * {@inheritDoc}
584
     * Gets the SQL statement(s) to create a table with the specified name, columns and constraints
585
     * on this platform.
586
     *
587
     * @param Table $table The name of the table.
588
     * @param integer $createFlags
589
     *
590
     * @return array The sequence of SQL statements.
591 126
     */
592
    public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDEXES)
593 126
    {
594
        if (!is_int($createFlags)) {
0 ignored issues
show
introduced by
The condition is_int($createFlags) is always true.
Loading history...
595
            $msg = "Second argument of CratePlatform::getCreateTableSQL() has to be integer.";
596
            throw new InvalidArgumentException($msg);
597
        }
598 126
599 4
        if (count($table->getColumns()) === 0) {
600
            throw DBALException::noColumnsSpecifiedForTable($table->getName());
601
        }
602 122
603 122
        $tableName = $table->getQuotedName($this);
604 122
        $options = $table->getOptions();
605 122
        $options['uniqueConstraints'] = array();
606 122
        $options['indexes'] = array();
607
        $options['primary'] = array();
608 122
609 122
        if (($createFlags&self::CREATE_INDEXES) > 0) {
610
            foreach ($table->getIndexes() as $index) {
611 88
                /* @var $index Index */
612 78
                if ($index->isPrimary()) {
613 78
                    $platform = $this;
614 78
                    $options['primary'] = array_map(function ($columnName) use ($table, $platform) {
615 78
                        return $table->getColumn($columnName)->getQuotedName($platform);
616 78
                    }, $index->getColumns());
617 10
                    $options['primary_index'] = $index;
618 4
                } elseif ($index->isUnique()) {
619 4
                    throw DBALException::notSupported(
620 4
                        "Unique constraints are not supported. Use `primary key` instead"
621
                    );
622 6
                } else {
623
                    $options['indexes'][$index->getName()] = $index;
624
                }
625
            }
626
        }
627 118
628 118
        $columnSql = array();
629
        $columns = array();
630 118
631 118
        foreach ($table->getColumns() as $column) {
632 118
            if (null !== $this->_eventManager &&
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Platforms\...latform::$_eventManager has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

632
            if (null !== /** @scrutinizer ignore-deprecated */ $this->_eventManager &&
Loading history...
633
                $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Platforms\...latform::$_eventManager has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

633
                /** @scrutinizer ignore-deprecated */ $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)
Loading history...
introduced by
The constant Doctrine\DBAL\Events::onSchemaCreateTableColumn has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

633
                $this->_eventManager->hasListeners(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTableColumn)
Loading history...
634 2
            ) {
635 2
                $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this);
0 ignored issues
show
Deprecated Code introduced by
The class Doctrine\DBAL\Event\Sche...ateTableColumnEventArgs has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

635
                $eventArgs = /** @scrutinizer ignore-deprecated */ new SchemaCreateTableColumnEventArgs($column, $table, $this);
Loading history...
636
                $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
0 ignored issues
show
introduced by
The constant Doctrine\DBAL\Events::onSchemaCreateTableColumn has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

636
                $this->_eventManager->dispatchEvent(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTableColumn, $eventArgs);
Loading history...
Deprecated Code introduced by
The property Doctrine\DBAL\Platforms\...latform::$_eventManager has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

636
                /** @scrutinizer ignore-deprecated */ $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
Loading history...
637 2
638
                $columnSql = array_merge($columnSql, $eventArgs->getSql());
639 2
640
                if ($eventArgs->isDefaultPrevented()) {
641
                    continue;
642
                }
643 118
            }
644
            $columns[$column->getQuotedName($this)] = self::prepareColumnData($this, $column, $options['primary']);
645
        }
646 116
647 2
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Platforms\...latform::$_eventManager has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

647
        if (null !== $this->_eventManager && /** @scrutinizer ignore-deprecated */ $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
Loading history...
introduced by
The constant Doctrine\DBAL\Events::onSchemaCreateTable has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

647
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTable)) {
Loading history...
648 2
            $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
0 ignored issues
show
Deprecated Code introduced by
The class Doctrine\DBAL\Event\SchemaCreateTableEventArgs has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

648
            $eventArgs = /** @scrutinizer ignore-deprecated */ new SchemaCreateTableEventArgs($table, $columns, $options, $this);
Loading history...
649
            $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\DBAL\Platforms\...latform::$_eventManager has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

649
            /** @scrutinizer ignore-deprecated */ $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
Loading history...
introduced by
The constant Doctrine\DBAL\Events::onSchemaCreateTable has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

649
            $this->_eventManager->dispatchEvent(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTable, $eventArgs);
Loading history...
650 2
651
            if ($eventArgs->isDefaultPrevented()) {
652
                return array_merge($eventArgs->getSql(), $columnSql);
653
            }
654
        }
655 116
656 114
        $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
657
        if ($this->supportsCommentOnStatement()) {
658
            foreach ($table->getColumns() as $column) {
659
                if ($this->getColumnComment($column)) {
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Platforms\...orm::getColumnComment() has been deprecated: This method will be removed without replacement. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

659
                if (/** @scrutinizer ignore-deprecated */ $this->getColumnComment($column)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
660
                    $sql[] = $this->getCommentOnColumnSQL(
661
                        $tableName,
662
                        $column->getName(),
663
                        $this->getColumnComment($column)
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Platforms\...orm::getColumnComment() has been deprecated: This method will be removed without replacement. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

663
                        /** @scrutinizer ignore-deprecated */ $this->getColumnComment($column)

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
664
                    );
665
                }
666
            }
667
        }
668 114
669
        return array_merge($sql, $columnSql);
670
    }
671
672
    /**
673
     * {@inheritDoc}
674 116
     */
675
    // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
676 116
    protected function _getCreateTableSQL($name, array $columns, array $options = array())
677
    {
678 116
        $columnListSql = $this->getColumnDeclarationListSQL($columns);
679 78
680 78
        if (isset($options['primary']) && ! empty($options['primary'])) {
681
            $keyColumns = array_unique(array_values($options['primary']));
682
            $columnListSql .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
683 116
        }
684 6
685 6
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
686
            foreach ($options['indexes'] as $index => $definition) {
687
                $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
688
            }
689 116
        }
690
 
691
        if (isset($options['foreignKeys'])) {
692
            throw DBALException::notSupported("Create Table: foreign keys");
693 116
        }
694 116
695 116
        $query = 'CREATE TABLE ' . $name . ' (' . $columnListSql . ')';
696 114
        $query .= $this->buildShardingOptions($options);
697 114
        $query .= $this->buildPartitionOptions($options);
698
        $query .= $this->buildTableOptions($options);
699
        return array($query);
700
    }
701
702
    /**
703
     * Build SQL for table options
704
     *
705
     * @param mixed[] $options
706
     *
707 114
     * @return string
708
     */
709 114
    private function buildTableOptions(array $options)
710 110
    {
711
        if (! isset($options['table_options'])) {
712
            return '';
713 4
        }
714 4
715 4
        $tableOptions = [];
716
        foreach ($options['table_options'] as $key => $val) {
717 4
            $tableOptions[] = sprintf('"%s" = %s', $key, $this->quoteStringLiteral($val));
718
        }
719
        if (count($tableOptions) == 0) {
720
            return '';
721 4
        }
722
723
        return sprintf(' WITH (%s)', implode(', ', $tableOptions));
724
    }
725
726
    /**
727
     * Build SQL for sharding options.
728
     *
729
     * @param mixed[] $options
730
     *
731 116
     * @return string
732
     */
733 116
    private function buildShardingOptions(array $options)
734
    {
735 116
        $shardingOptions = [];
736 4
737 4
        if (isset($options['sharding_routing_column'])) {
738
            $columnName = new Identifier($options['sharding_routing_column']);
739 116
            $shardingOptions[] = sprintf('BY (%s)', $columnName->getQuotedName($this));
740 4
        }
741
        if (isset($options['sharding_num_shards'])) {
742
            $shardingOptions[] = sprintf("INTO %d SHARDS", $options['sharding_num_shards']);
743 116
        }
744 112
745
        if (count($shardingOptions) == 0) {
746
            return '';
747 4
        }
748
749
        return sprintf(" CLUSTERED %s", implode(' ', $shardingOptions));
750
    }
751
752
    /**
753
     * Build SQL for partition options.
754
     *
755
     * @param mixed[] $options
756
     *
757 116
     * @return string
758
     */
759 116
    private function buildPartitionOptions(array $options)
760 110
    {
761
        if (! isset($options['partition_columns'])) {
762 6
            return '';
763 6
        }
764 2
        $columns = $options['partition_columns'];
765
        if (! is_array($columns)) {
766 4
            throw new InvalidArgumentException(sprintf("Expecting array type at 'partition_columns'"));
767 4
        }
768 4
        $quotedNames = [];
769 4
        foreach ($columns as $name) {
770
            $name = new Identifier($name);
771
            $quotedNames[] = $name->getQuotedName($this);
772 4
        }
773
774
        return sprintf(" PARTITIONED BY (%s)", implode(', ', $quotedNames));
775
    }
776
777
    /**
778
     * @param \Doctrine\DBAL\Schema\Column $column The name of the table.
779
     * @param array List of primary key column names
0 ignored issues
show
Bug introduced by
The type Crate\DBAL\Platforms\List was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
780
     *
781
     * @return array The column data as associative array.
782 122
     * @throws DBALException
783
     */
784 122
    public static function prepareColumnData(AbstractPlatform $platform, $column, $primaries = array())
785 2
    {
786
        if ($column->hasCustomSchemaOption("unique") ? $column->getCustomSchemaOption("unique") : false) {
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Schema\Col...hasCustomSchemaOption() has been deprecated: Use {@link hasPlatformOption()} instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

786
        if (/** @scrutinizer ignore-deprecated */ $column->hasCustomSchemaOption("unique") ? $column->getCustomSchemaOption("unique") : false) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Deprecated Code introduced by
The function Doctrine\DBAL\Schema\Col...getCustomSchemaOption() has been deprecated: Use {@link getPlatformOption()} instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

786
        if ($column->hasCustomSchemaOption("unique") ? /** @scrutinizer ignore-deprecated */ $column->getCustomSchemaOption("unique") : false) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
787
            throw DBALException::notSupported("Unique constraints are not supported. Use `primary key` instead");
788 120
        }
789 120
790 120
        $columnData = array();
791 120
        $columnData['name'] = $column->getQuotedName($platform);
792 120
        $columnData['type'] = $column->getType();
793 120
        $columnData['length'] = $column->getLength();
794 120
        $columnData['notnull'] = $column->getNotNull();
795 120
        $columnData['fixed'] = $column->getFixed();
796
        $columnData['unique'] = false;
797 120
        $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption("version") : false;
798 120
799
        if (strtolower($columnData['type']) == $platform->getVarcharTypeDeclarationSQLSnippet(0, false)
800
                && $columnData['length'] === null) {
801
            $columnData['length'] = 255;
802 120
        }
803 120
804 120
        $columnData['unsigned'] = $column->getUnsigned();
805 120
        $columnData['precision'] = $column->getPrecision();
806 120
        $columnData['scale'] = $column->getScale();
807 120
        $columnData['default'] = $column->getDefault();
808 120
        $columnData['columnDefinition'] = $column->getColumnDefinition();
809 120
        $columnData['autoincrement'] = $column->getAutoincrement();
810
        $columnData['comment'] = $platform->getColumnComment($column);
811 120
        $columnData['platformOptions'] = $column->getPlatformOptions();
812 76
813
        if (in_array($column->getName(), $primaries)) {
814 120
            $columnData['primary'] = true;
815
        }
816
        return $columnData;
817
    }
818
819
    /**
820 2
     * {@inheritDoc}
821
     */
822 2
    public function getCreateDatabaseSQL($database)
823
    {
824
        throw DBALException::notSupported(__METHOD__);
825
    }
826
827
    /**
828 2
     * {@inheritDoc}
829
     */
830 2
    public function getDropDatabaseSQL($database)
831
    {
832
        throw DBALException::notSupported(__METHOD__);
833
    }
834
    
835
    /**
836 2
     * {@inheritDoc}
837
     */
838 2
    public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
839
    {
840
        throw DBALException::notSupported(__METHOD__);
841
    }
842
    
843
    /**
844 2
     * {@inheritDoc}
845
     */
846 2
    public function getGuidTypeDeclarationSQL(array $field)
847
    {
848
        throw DBALException::notSupported(__METHOD__);
849
    }
850
851
    /**
852
     * Returns the SQL query to return the CrateDB specific table options associated
853
     * with a given table.
854
     *
855 6
     * @return string
856
     */
857 6
    public function getTableOptionsSQL(string $table) : string
858 6
    {
859 6
        return "SELECT clustered_by, number_of_shards, partitioned_by, number_of_replicas, column_policy, settings " .
860
               "FROM information_schema.tables c " .
861
               "WHERE " . $this->getTableWhereClause($table);
862
    }
863
864
    /**
865
     * {@inheritDoc}
866
     */
867
    public function getCurrentDatabaseExpression(): string
868
    {
869
        // TODO: Implement getCurrentDatabaseExpression() method.
870
        //       Added when upgrading to Doctrine3.
871
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
872
}
873