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

CratePlatform::getDateFormatString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * Licensed to CRATE Technology GmbH("Crate") under one or more contributor
5
 * license agreements.  See the NOTICE file distributed with this work for
6
 * additional information regarding copyright ownership.  Crate licenses
7
 * this file to you under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.  You may
9
 * obtain a copy of the License at
10
 *
11
 * http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
16
 * License for the specific language governing permissions and limitations
17
 * under the License.
18
 *
19
 * However, if you have executed another commercial license agreement
20
 * with Crate these terms will supersede the license and you may use the
21
 * software solely pursuant to the terms of the relevant commercial agreement.
22
 */
23
24
namespace Crate\DBAL\Platforms;
25
26
use Crate\DBAL\Types\MapType;
27
use Crate\DBAL\Types\TimestampType;
28
use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs;
29
use Doctrine\DBAL\Event\SchemaCreateTableEventArgs;
30
use Doctrine\DBAL\Events;
31
use Doctrine\DBAL\Exception as DBALException;
32
use Doctrine\DBAL\Platforms\AbstractPlatform;
33
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
34
use Doctrine\DBAL\Schema\Identifier;
35
use Doctrine\DBAL\Schema\Index;
36
use Doctrine\DBAL\Schema\Table;
37
use Doctrine\DBAL\Schema\TableDiff;
38
use Doctrine\DBAL\TransactionIsolationLevel;
39
use Doctrine\DBAL\Types\Type;
40
use InvalidArgumentException;
41
42
class CratePlatform extends AbstractPlatform
43
{
44
    public const TIMESTAMP_FORMAT =  'Y-m-d\TH:i:s';
45
    public const TIMESTAMP_FORMAT_TZ =  'Y-m-d\TH:i:sO';
46
    public const TABLE_WHERE_CLAUSE_FORMAT = '%s.table_name = %s AND %s.schema_name = %s';
47
48
    /**
49
     * {@inheritDoc}
50
     */
51 262
    public function __construct()
52
    {
53 262
        $this->initializeDoctrineTypeMappings();
54 262
        if (!Type::hasType(MapType::NAME)) {
55
            Type::addType(MapType::NAME, 'Crate\DBAL\Types\MapType');
56
        }
57 262
        if (!Type::hasType(TimestampType::NAME)) {
58
            Type::addType(TimestampType::NAME, 'Crate\DBAL\Types\TimestampType');
59
        }
60 262
        Type::overrideType('array', 'Crate\DBAL\Types\ArrayType');
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66 2
    public function getDefaultTransactionIsolationLevel()
67
    {
68
        // CrateDB provides `READ_UNCOMMITTED` isolation levels.
69
        // https://github.com/crate/crate/blob/master/server/src/main/java/io/crate/analyze/ShowStatementAnalyzer.java#L69-L85
70 2
        return TransactionIsolationLevel::READ_UNCOMMITTED;
71
    }
72
73
    /**
74
     * {@inheritDoc}
75
     */
76 2
    public function getSubstringExpression($value, $from = 0, $length = null): string
77
    {
78 2
        if ($length === null) {
79 2
            return 'SUBSTR(' . $value . ', ' . $from . ')';
80
        }
81
82 2
        return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')';
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     */
88 2
    public function getNowExpression()
89
    {
90 2
        throw DBALException::notSupported(__METHOD__);
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     */
96 2
    public function getRegexpExpression(): string
97
    {
98 2
        return 'LIKE';
99
    }
100
101
    /**
102
     * {@inheritDoc}
103
     */
104 2
    public function getDateDiffExpression($date1, $date2): string
105
    {
106 2
        throw DBALException::notSupported(__METHOD__);
107
    }
108
109
    /**
110
     * {@inheritDoc}
111
     */
112 8
    public function supportsSequences(): bool
113
    {
114 8
        return false;
115
    }
116
117
    /**
118
     * If we want to support Schemas, we need to implement
119
     * getListNamespacesSQL and getCreateSchemaSQL methods
120
     *
121
     * {@inheritDoc}
122
     */
123 10
    public function supportsSchemas(): bool
124
    {
125 10
        return false;
126
    }
127
128
    /**
129
     * {@inheritDoc}
130
     */
131 2
    public function supportsIdentityColumns(): bool
132
    {
133 2
        return true;
134
    }
135
136
    /**
137
     * {@inheritDoc}
138
     */
139 2
    public function supportsIndexes()
140
    {
141 2
        return false;
142
    }
143
144
    /**
145
     * {@inheritDoc}
146
     */
147 112
    public function supportsCommentOnStatement(): bool
148
    {
149 112
        return false;
150
    }
151
152
    /**
153
     * {@inheritDoc}
154
     */
155 10
    public function supportsForeignKeyConstraints()
156
    {
157 10
        return false;
158
    }
159
160
    /**
161
     * {@inheritDoc}
162
     */
163 2
    public function supportsForeignKeyOnUpdate()
164
    {
165 2
        return false;
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     */
171 2
    public function supportsViews()
172
    {
173 2
        return false;
174
    }
175
176
    /**
177
     * {@inheritDoc}
178
     */
179 2
    public function prefersSequences()
180
    {
181 2
        return false;
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     */
187 2
    public function getListDatabasesSQL(): string
188
    {
189 2
        throw DBALException::notSupported(__METHOD__);
190
    }
191
192
    /**
193
     * {@inheritDoc}
194
     */
195
    public function getListTablesSQL()
196
    {
197
        return "SELECT table_name, schema_name FROM information_schema.tables " .
198
               "WHERE schema_name = 'doc' OR schema_name = 'blob'";
199
    }
200
201
    /**
202
     * {@inheritDoc}
203
     */
204 8
    public function getListTableColumnsSQL($table, $database = null)
205
    {
206 8
        return "SELECT * from information_schema.columns c " .
207 8
               "WHERE " . $this->getTableWhereClause($table);
208
    }
209
210
    /**
211
     * {@inheritDoc}
212
     */
213
    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

213
    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...
214
    {
215
        return "SELECT c.constraint_name, c.constraint_type " .
216
               "FROM information_schema.table_constraints c " .
217
               "WHERE " . $this->getTableWhereClause($table) . " AND constraint_type = 'PRIMARY KEY'";
218
    }
219
220
    /**
221
     * {@inheritDoc}
222
     */
223 8
    public function getListTableIndexesSQL($table, $currentDatabase = null)
224
    {
225 8
        return "SELECT c.constraint_name, c.constraint_type, k.column_name " .
226 8
               "FROM information_schema.table_constraints c " .
227 8
               "JOIN information_schema.key_column_usage k on c.constraint_name = k.constraint_name " .
228 8
               "WHERE " . $this->getTableWhereClause($table);
229
    }
230
231 10
    private function getTableWhereClause($table, $tableAlias = 'c')
232
    {
233 10
        if (strpos($table, '.') !== false) {
234
            [$schema, $table] = explode('.', $table);
235
            $schema = $this->quoteStringLiteral($schema);
236
        } else {
237 10
            $schema = $this->quoteStringLiteral('doc');
238
        }
239
240 10
        $table = new Identifier($table);
241 10
        $table = $this->quoteStringLiteral($table->getName());
242
243 10
        return sprintf(
244 10
            $this->getTableWhereClauseFormat(),
245 10
            $tableAlias,
246 10
            $table,
247 10
            $tableAlias,
248 10
            $schema
249 10
        );
250
    }
251
252
    /**
253
     * Return sprintf format string for usage at getTableWhereClause
254
     *
255
     * @return string
256
     */
257
    protected function getTableWhereClauseFormat()
258
    {
259
        return self::TABLE_WHERE_CLAUSE_FORMAT;
260
    }
261
262
    /**
263
     * {@inheritDoc}
264
     */
265 6
    public function getAlterTableSQL(TableDiff $diff): array
266
    {
267 6
        $sql = array();
268 6
        $commentsSQL = array();
269 6
        $columnSql = array();
270
271 6
        foreach ($diff->addedColumns as $column) {
272 4
            if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
273
                continue;
274
            }
275
276 4
            $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
277 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

277
            $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...
278 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

278
            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...
279
                $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

279
                $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...
280
            }
281
        }
282
283 6
        if (count($diff->removedColumns) > 0) {
284
            throw DBALException::notSupported("Alter Table: drop columns");
285
        }
286 6
        if (count($diff->changedColumns) > 0) {
287
            throw DBALException::notSupported("Alter Table: change column options");
288
        }
289 6
        if (count($diff->renamedColumns) > 0) {
290
            throw DBALException::notSupported("Alter Table: rename columns");
291
        }
292
293 6
        $tableSql = array();
294
295 6
        if (!$this->onSchemaAlterTable($diff, $tableSql)) {
296 6
            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

296
            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...
297
                throw DBALException::notSupported("Alter Table: rename table");
298
            }
299
300 6
            $sql = array_merge($sql, $this->getPreAlterTableIndexForeignKeySQL($diff), $commentsSQL);
301
        }
302
303 6
        return array_merge($sql, $tableSql, $columnSql);
304
    }
305
306
    /**
307
     * {@inheritDoc}
308
     */
309 122
    public function getColumnDeclarationSQL($name, array $column): string
310
    {
311 122
        if (isset($column['columnDefinition'])) {
312 62
            $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

312
            $columnDef = /** @scrutinizer ignore-deprecated */ $this->getCustomTypeDeclarationSQL($column);
Loading history...
313
        } else {
314 120
            $typeDecl = $column['type']->getSqlDeclaration($column, $this);
315 120
            $columnDef = $typeDecl;
316
        }
317
318 122
        return $name . ' ' . $columnDef;
319
    }
320
321
    /**
322
     * Generate table index column declaration
323
     * @param string $name
324
     * @param Index $index
325
     * @codeCoverageIgnore
326
     */
327
    public function getIndexDeclarationSQL($name, Index $index): string
328
    {
329
        $columns = $index->getQuotedColumns($this);
330
        $name = new Identifier($name);
331
332
        if (count($columns) == 0) {
333
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
334
        }
335
336
        return 'INDEX ' . $name->getQuotedName($this) .
337
               ' USING FULLTEXT ('. $this->getIndexFieldDeclarationListSQL($index) . ')';
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

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

647
            if (null !== /** @scrutinizer ignore-deprecated */ $this->_eventManager &&
Loading history...
648 112
                $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

648
                /** @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

648
                $this->_eventManager->hasListeners(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTableColumn)
Loading history...
649
            ) {
650 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

650
                $eventArgs = /** @scrutinizer ignore-deprecated */ new SchemaCreateTableColumnEventArgs($column, $table, $this);
Loading history...
651 2
                $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

651
                $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

651
                /** @scrutinizer ignore-deprecated */ $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
Loading history...
652
653 2
                $columnSql = array_merge($columnSql, $eventArgs->getSql());
654
655 2
                if ($eventArgs->isDefaultPrevented()) {
656
                    continue;
657
                }
658
            }
659 112
            $columns[$column->getQuotedName($this)] = self::prepareColumnData($this, $column, $options['primary']);
660
        }
661
662 110
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
0 ignored issues
show
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

662
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTable)) {
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

662
        if (null !== /** @scrutinizer ignore-deprecated */ $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
Loading history...
663 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

663
            $eventArgs = /** @scrutinizer ignore-deprecated */ new SchemaCreateTableEventArgs($table, $columns, $options, $this);
Loading history...
664 2
            $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
0 ignored issues
show
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

664
            $this->_eventManager->dispatchEvent(/** @scrutinizer ignore-deprecated */ Events::onSchemaCreateTable, $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

664
            /** @scrutinizer ignore-deprecated */ $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
Loading history...
665
666 2
            if ($eventArgs->isDefaultPrevented()) {
667
                return array_merge($eventArgs->getSql(), $columnSql);
668
            }
669
        }
670
671 110
        $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
672 108
        if ($this->supportsCommentOnStatement()) {
673
            foreach ($table->getColumns() as $column) {
674
                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

674
                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...
675
                    $sql[] = $this->getCommentOnColumnSQL(
676
                        $tableName,
677
                        $column->getName(),
678
                        $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

678
                        /** @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...
679
                    );
680
                }
681
            }
682
        }
683
684 108
        return array_merge($sql, $columnSql);
685
    }
686
687
    /**
688
     * {@inheritDoc}
689
     */
690
    // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
691 110
    protected function _getCreateTableSQL($name, array $columns, array $options = array()): array
692
    {
693 110
        $columnListSql = $this->getColumnDeclarationListSQL($columns);
694
695 110
        if (isset($options['primary']) && ! empty($options['primary'])) {
696 72
            $keyColumns = array_unique(array_values($options['primary']));
697 72
            $columnListSql .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
698
        }
699
700 110
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
701 6
            foreach ($options['indexes'] as $index => $definition) {
702 6
                $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
703
            }
704
        }
705
706 110
        if (isset($options['foreignKeys'])) {
707
            throw DBALException::notSupported("Create Table: foreign keys");
708
        }
709
710 110
        $query = 'CREATE TABLE ' . $name . ' (' . $columnListSql . ')';
711 110
        $query .= $this->buildShardingOptions($options);
712 110
        $query .= $this->buildPartitionOptions($options);
713 108
        $query .= $this->buildTableOptions($options);
714 108
        return array($query);
715
    }
716
717
    /**
718
     * Build SQL for table options
719
     *
720
     * @param mixed[] $options
721
     *
722
     * @return string
723
     */
724 108
    private function buildTableOptions(array $options)
725
    {
726 108
        if (! isset($options['table_options'])) {
727 104
            return '';
728
        }
729
730 4
        $tableOptions = [];
731 4
        foreach ($options['table_options'] as $key => $val) {
732 4
            $tableOptions[] = sprintf('"%s" = %s', $key, $this->quoteStringLiteral($val));
733
        }
734 4
        if (count($tableOptions) == 0) {
735
            return '';
736
        }
737
738 4
        return sprintf(' WITH (%s)', implode(', ', $tableOptions));
739
    }
740
741
    /**
742
     * Build SQL for sharding options.
743
     *
744
     * @param mixed[] $options
745
     *
746
     * @return string
747
     */
748 110
    private function buildShardingOptions(array $options)
749
    {
750 110
        $shardingOptions = [];
751
752 110
        if (isset($options['sharding_routing_column'])) {
753 4
            $columnName = new Identifier($options['sharding_routing_column']);
754 4
            $shardingOptions[] = sprintf('BY (%s)', $columnName->getQuotedName($this));
755
        }
756 110
        if (isset($options['sharding_num_shards'])) {
757 4
            $shardingOptions[] = sprintf("INTO %d SHARDS", $options['sharding_num_shards']);
758
        }
759
760 110
        if (count($shardingOptions) == 0) {
761 106
            return '';
762
        }
763
764 4
        return sprintf(" CLUSTERED %s", implode(' ', $shardingOptions));
765
    }
766
767
    /**
768
     * Build SQL for partition options.
769
     *
770
     * @param mixed[] $options
771
     *
772
     * @return string
773
     */
774 110
    private function buildPartitionOptions(array $options)
775
    {
776 110
        if (! isset($options['partition_columns'])) {
777 104
            return '';
778
        }
779 6
        $columns = $options['partition_columns'];
780 6
        if (! is_array($columns)) {
781 2
            throw new InvalidArgumentException(sprintf("Expecting array type at 'partition_columns'"));
782
        }
783 4
        $quotedNames = [];
784 4
        foreach ($columns as $name) {
785 4
            $name = new Identifier($name);
786 4
            $quotedNames[] = $name->getQuotedName($this);
787
        }
788
789 4
        return sprintf(" PARTITIONED BY (%s)", implode(', ', $quotedNames));
790
    }
791
792
    /**
793
     * @param \Doctrine\DBAL\Schema\Column $column The name of the table.
794
     * @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...
795
     *
796
     * @return array The column data as associative array.
797
     * @throws DBALException
798
     */
799 116
    public static function prepareColumnData(AbstractPlatform $platform, $column, $primaries = array())
800
    {
801 116
        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

801
        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

801
        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...
802 2
            throw DBALException::notSupported("Unique constraints are not supported. Use `primary key` instead");
803
        }
804
805 114
        $columnData = array();
806 114
        $columnData['name'] = $column->getQuotedName($platform);
807 114
        $columnData['type'] = $column->getType();
808 114
        $columnData['length'] = $column->getLength();
809 114
        $columnData['notnull'] = $column->getNotNull();
810 114
        $columnData['fixed'] = $column->getFixed();
811 114
        $columnData['unique'] = false;
812 114
        $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption("version") : false;
813
814 114
        if (strtolower($columnData['type']->getName()) ==
815 114
            strtolower($platform->getVarcharTypeDeclarationSQLSnippet(0, false))
816 114
                && $columnData['length'] === null) {
817
            $columnData['length'] = 255;
818
        }
819
820 114
        $columnData['unsigned'] = $column->getUnsigned();
821 114
        $columnData['precision'] = $column->getPrecision();
822 114
        $columnData['scale'] = $column->getScale();
823 114
        $columnData['default'] = $column->getDefault();
824 114
        $columnData['columnDefinition'] = $column->getColumnDefinition();
825 114
        $columnData['autoincrement'] = $column->getAutoincrement();
826 114
        $columnData['comment'] = $platform->getColumnComment($column);
827 114
        $columnData['platformOptions'] = $column->getPlatformOptions();
828
829 114
        if (in_array($column->getName(), $primaries)) {
830 70
            $columnData['primary'] = true;
831
        }
832 114
        return $columnData;
833
    }
834
835
    /**
836
     * {@inheritDoc}
837
     */
838 2
    public function getCreateDatabaseSQL($database): string
839
    {
840 2
        throw DBALException::notSupported(__METHOD__);
841
    }
842
843
    /**
844
     * {@inheritDoc}
845
     */
846 2
    public function getDropDatabaseSQL($database): string
847
    {
848 2
        throw DBALException::notSupported(__METHOD__);
849
    }
850
851
    /**
852
     * {@inheritDoc}
853
     */
854
    public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table): string
855
    {
856
        throw DBALException::notSupported(__METHOD__);
857
    }
858
859
    /**
860
     * {@inheritDoc}
861
     */
862 2
    public function getGuidTypeDeclarationSQL(array $field): string
863
    {
864 2
        throw DBALException::notSupported(__METHOD__);
865
    }
866
867
    /**
868
     * Returns the SQL query to return the CrateDB specific table options associated
869
     * with a given table.
870
     *
871
     * @return string
872
     */
873 6
    public function getTableOptionsSQL(string $table): string
874
    {
875 6
        return "SELECT clustered_by, number_of_shards, partitioned_by, number_of_replicas, column_policy, settings " .
876 6
               "FROM information_schema.tables c " .
877 6
               "WHERE " . $this->getTableWhereClause($table);
878
    }
879
880
    /**
881
     * {@inheritDoc}
882
     */
883 10
    public function getCurrentDatabaseExpression(): string
884
    {
885
        // Added by Doctrine 3.
886 10
        return 'CURRENT_DATABASE()';
887
    }
888
}
889