Passed
Pull Request — main (#136)
by
unknown
12:06
created

CratePlatform::getDateTimeTzFormatString()   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 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
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
 * 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\Exception;
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 252
    public function __construct()
50
    {
51 252
        parent::__construct();
52 252
        $this->initializeDoctrineTypeMappings();
53 252
        if (!Type::hasType(MapType::NAME)) {
54
            Type::addType(MapType::NAME, 'Crate\DBAL\Types\MapType');
55
        }
56 252
        if (!Type::hasType(TimestampType::NAME)) {
57
            Type::addType(TimestampType::NAME, 'Crate\DBAL\Types\TimestampType');
58
        }
59 252
        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 Exception::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 Exception::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 12
    public function supportsForeignKeyConstraints()
145
    {
146 12
        return false;
147
    }
148
149
    /**
150
     * {@inheritDoc}
151
     */
152 2
    public function supportsViews()
153
    {
154 2
        return false;
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160 2
    public function getListDatabasesSQL()
161
    {
162 2
        throw Exception::notSupported(__METHOD__);
163
    }
164
165
    /**
166
     * {@inheritDoc}
167
     */
168
    public function getListTablesSQL()
169
    {
170
        return "SELECT table_name, schema_name FROM information_schema.tables " .
171
               "WHERE schema_name = 'doc' OR schema_name = 'blob'";
172
    }
173
174
    /**
175
     * {@inheritDoc}
176
     */
177 8
    public function getListTableColumnsSQL($table, $database = null)
178
    {
179 8
        return "SELECT * from information_schema.columns c " .
180 8
               "WHERE " . $this->getTableWhereClause($table);
181
    }
182
183
    /**
184
     * {@inheritDoc}
185
     */
186
    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

186
    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...
187
    {
188
        return "SELECT c.constraint_name, c.constraint_type " .
189
               "FROM information_schema.table_constraints c " .
190
               "WHERE " . $this->getTableWhereClause($table) . " AND constraint_type = 'PRIMARY KEY'";
191
    }
192
193
    /**
194
     * {@inheritDoc}
195
     */
196 8
    public function getListTableIndexesSQL($table, $currentDatabase = null)
197
    {
198 8
        return "SELECT c.constraint_name, c.constraint_type, k.column_name " .
199 8
               "FROM information_schema.table_constraints c " .
200 8
               "JOIN information_schema.key_column_usage k on c.constraint_name = k.constraint_name " .
201 8
               "WHERE " . $this->getTableWhereClause($table);
202
    }
203
204 10
    private function getTableWhereClause($table, $tableAlias = 'c')
205
    {
206 10
        if (strpos($table, '.') !== false) {
207
            [$schema, $table] = explode('.', $table);
208
            $schema = $this->quoteStringLiteral($schema);
209
        } else {
210 10
            $schema = $this->quoteStringLiteral('doc');
211
        }
212
213 10
        $table = new Identifier($table);
214 10
        $table = $this->quoteStringLiteral($table->getName());
215
216 10
        return sprintf(
217 10
            $this->getTableWhereClauseFormat(),
218 10
            $tableAlias,
219 10
            $table,
220 10
            $tableAlias,
221 10
            $schema
222 10
        );
223
    }
224
225
    /**
226
     * Return sprintf format string for usage at getTableWhereClause
227
     *
228
     * @return string
229
     */
230
    protected function getTableWhereClauseFormat()
231
    {
232
        return self::TABLE_WHERE_CLAUSE_FORMAT;
233
    }
234
235
    /**
236
     * {@inheritDoc}
237
     */
238 8
    public function getAlterTableSQL(TableDiff $diff)
239
    {
240 8
        $sql = array();
241 8
        $commentsSQL = array();
242 8
        $columnSql = array();
243
244 8
        foreach ($diff->addedColumns as $column) {
245 2
            if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
246
                continue;
247
            }
248
249 2
            $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
250 2
            $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
251 2
            if ($comment = $this->getColumnComment($column)) {
252
                $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
253
            }
254
        }
255
256 8
        if (count($diff->removedColumns) > 0) {
257
            throw Exception::notSupported("Alter Table: drop columns");
258
        }
259 8
        if (count($diff->changedColumns) > 0) {
260
            throw Exception::notSupported("Alter Table: change column options");
261
        }
262 8
        if (count($diff->renamedColumns) > 0) {
263
            throw Exception::notSupported("Alter Table: rename columns");
264
        }
265
266 8
        $tableSql = array();
267
268 8
        if (!$this->onSchemaAlterTable($diff, $tableSql)) {
269 8
            if ($diff->newName !== false) {
270
                throw Exception::notSupported("Alter Table: rename table");
271
            }
272
273 8
            $sql = array_merge($sql, $this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff), $commentsSQL);
274
        }
275
276 8
        return array_merge($sql, $tableSql, $columnSql);
277
    }
278
279
    /**
280
     * {@inheritDoc}
281
     */
282 124
    public function getColumnDeclarationSQL($name, array $column)
283
    {
284 124
        if (isset($column['columnDefinition'])) {
285 68
            $columnDef = $this->getCustomTypeDeclarationSQL($column);
286
        } else {
287 122
            $typeDecl = $column['type']->getSqlDeclaration($column, $this);
288 122
            $columnDef = $typeDecl;
289
        }
290
291 124
        return $name . ' ' . $columnDef;
292
    }
293
294
    /**
295
     * Generate table index column declaration
296
     * @codeCoverageIgnore
297
     */
298
    public function getIndexDeclarationSQL($name, Index $index)
299
    {
300
        $columns = $index->getQuotedColumns($this);
301
        $name = new Identifier($name);
302
303
        if (count($columns) == 0) {
304
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
305
        }
306
307
        return 'INDEX ' . $name->getQuotedName($this) .
308
               ' USING FULLTEXT ('. $this->getIndexFieldDeclarationListSQL($columns) . ')';
309
    }
310
311
    /**
312
     * {@inheritDoc}
313
     *
314
     * Crate wants boolean values converted to the strings 'true'/'false'.
315
     */
316 4
    public function convertBooleans($item)
317
    {
318 4
        if (is_array($item)) {
319 2
            foreach ($item as $key => $value) {
320 2
                if (is_bool($value)) {
321 2
                    $item[$key] = ($value) ? 'true' : 'false';
322 2
                } elseif (is_numeric($value)) {
323 2
                    $item[$key] = ($value > 0) ? 'true' : 'false';
324
                }
325
            }
326
        } else {
327 4
            if (is_bool($item)) {
328 4
                $item = ($item) ? 'true' : 'false';
329 2
            } elseif (is_numeric($item)) {
330 2
                $item = ($item > 0) ? 'true' : 'false';
331
            }
332
        }
333
334 4
        return $item;
335
    }
336
337
    /**
338
     * {@inheritDoc}
339
     */
340 22
    public function getBooleanTypeDeclarationSQL(array $field)
341
    {
342 22
        return 'BOOLEAN';
343
    }
344
345
    /**
346
     * {@inheritDoc}
347
     */
348 112
    public function getIntegerTypeDeclarationSQL(array $field)
349
    {
350 112
        return 'INTEGER';
351
    }
352
353
    /**
354
     * {@inheritDoc}
355
     */
356
    public function getBigIntTypeDeclarationSQL(array $field)
357
    {
358
        return 'LONG';
359
    }
360
361
    /**
362
     * {@inheritDoc}
363
     */
364
    public function getSmallIntTypeDeclarationSQL(array $field)
365
    {
366
        return 'SHORT';
367
    }
368
369
    /**
370
     * {@inheritDoc}
371
     */
372
    public function getFloatDeclarationSQL(array $field)
373
    {
374
        return 'DOUBLE';
375
    }
376
377
    /**
378
     * {@inheritDoc}
379
     */
380
    public function getDecimalTypeDeclarationSQL(array $columnDef)
381
    {
382
        return 'DOUBLE';
383
    }
384
385
    /**
386
     * {@inheritDoc}
387
     */
388 52
    public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
389
    {
390 52
        return 'TIMESTAMP';
391
    }
392
393
    /**
394
     * {@inheritDoc}
395
     */
396 2
    public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
397
    {
398 2
        return 'TIMESTAMP';
399
    }
400
401
    /**
402
     * {@inheritDoc}
403
     */
404 2
    public function getDateTypeDeclarationSQL(array $fieldDeclaration)
405
    {
406 2
        return 'TIMESTAMP';
407
    }
408
409
    /**
410
     * {@inheritDoc}
411
     */
412 2
    public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
413
    {
414 2
        return 'TIMESTAMP';
415
    }
416
417
    /**
418
     * {@inheritDoc}
419
     */
420
    protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
421
    {
422
        return '';
423
    }
424
425
    /**
426
     * {@inheritDoc}
427
     */
428
    protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
429
    {
430
        return 'STRING';
431
    }
432
433
    /**
434
     * {@inheritDoc}
435
     */
436
    public function getClobTypeDeclarationSQL(array $field)
437
    {
438
        return 'STRING';
439
    }
440
441
    /**
442
     * {@inheritDoc}
443
     */
444 4
    public function getName()
445
    {
446 4
        return 'crate';
447
    }
448
449
    /**
450
     * {@inheritDoc}
451
     *
452
     * PostgreSQL returns all column names in SQL result sets in lowercase.
453
     */
454 2
    public function getSQLResultCasing($column)
455
    {
456
457 2
        return strtolower($column);
458
    }
459
460
    /**
461
     * {@inheritDoc}
462
     */
463 4
    public function getDateTimeTzFormatString()
464
    {
465 4
        return self::TIMESTAMP_FORMAT_TZ;
466
    }
467
468
    /**
469
     * {@inheritDoc}
470
     */
471 10
    public function getDateTimeFormatString()
472
    {
473 10
        return self::TIMESTAMP_FORMAT;
474
    }
475
476
    /**
477
     * {@inheritDoc}
478
     */
479 2
    public function getDateFormatString()
480
    {
481 2
        return self::TIMESTAMP_FORMAT;
482
    }
483
484
    /**
485
     * {@inheritDoc}
486
     */
487 2
    public function getTimeFormatString()
488
    {
489 2
        return self::TIMESTAMP_FORMAT;
490
    }
491
492
    /**
493
     * {@inheritDoc}
494
     */
495 2
    public function getTruncateTableSQL($tableName, $cascade = false)
496
    {
497 2
        throw Exception::notSupported(__METHOD__);
498
    }
499
500
    /**
501
     * {@inheritDoc}
502
     */
503 2
    public function getReadLockSQL()
504
    {
505 2
        throw Exception::notSupported(__METHOD__);
506
    }
507
508
    /**
509
     * {@inheritDoc}
510
     */
511 20
    protected function initializeDoctrineTypeMappings()
512
    {
513 20
        $this->doctrineTypeMapping = array(
514 20
            'short'         => 'smallint',
515 20
            'integer'       => 'integer',
516 20
            'long'          => 'bigint',
517 20
            'int'           => 'integer',
518 20
            'bool'          => 'boolean',
519 20
            'boolean'       => 'boolean',
520 20
            'string'        => 'string',
521 20
            'float'         => 'float',
522 20
            'double'        => 'float',
523 20
            'timestamp'     => 'timestamp',
524 20
            'object'        => 'map',
525 20
            'array'         => 'array',
526 20
        );
527
    }
528
529
    /**
530
     * {@inheritDoc}
531
     */
532 12
    public function getDoctrineTypeMapping($dbType)
533
    {
534
        // typed arrays will always end up in the same generic php array type
535 12
        if (substr_compare($dbType, 'array', -5) === 0) {
536 2
            $dbType = 'array';
537
        }
538 12
        return parent::getDoctrineTypeMapping($dbType);
539
    }
540
541
542
    /**
543
     * {@inheritDoc}
544
     */
545 112
    public function getVarcharMaxLength()
546
    {
547 112
        return PHP_INT_MAX;
548
    }
549
550
    /**
551
     * {@inheritDoc}
552
     */
553 52
    protected function getReservedKeywordsClass()
554
    {
555 52
        return 'Crate\DBAL\Platforms\Keywords\CrateKeywords';
556
    }
557
558
    /**
559
     * {@inheritDoc}
560
     */
561 2
    public function getBlobTypeDeclarationSQL(array $field)
562
    {
563 2
        throw Exception::notSupported(__METHOD__);
564
    }
565
566
    /**
567
     * {@inheritDoc}
568
     * Gets the SQL statement(s) to create a table with the specified name, columns and constraints
569
     * on this platform.
570
     *
571
     * @param Table $table The name of the table.
572
     * @param integer $createFlags
573
     *
574
     * @return array The sequence of SQL statements.
575
     */
576 126
    public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDEXES)
577
    {
578 126
        if (!is_int($createFlags)) {
0 ignored issues
show
introduced by
The condition is_int($createFlags) is always true.
Loading history...
579
            $msg = "Second argument of CratePlatform::getCreateTableSQL() has to be integer.";
580
            throw new InvalidArgumentException($msg);
581
        }
582
583 126
        if (count($table->getColumns()) === 0) {
584 4
            throw Exception::noColumnsSpecifiedForTable($table->getName());
585
        }
586
587 122
        $tableName = $table->getQuotedName($this);
588 122
        $options = $table->getOptions();
589 122
        $options['uniqueConstraints'] = array();
590 122
        $options['indexes'] = array();
591 122
        $options['primary'] = array();
592
593 122
        if (($createFlags&self::CREATE_INDEXES) > 0) {
594 122
            foreach ($table->getIndexes() as $index) {
595
                /* @var $index Index */
596 88
                if ($index->isPrimary()) {
597 78
                    $platform = $this;
598 78
                    $options['primary'] = array_map(function ($columnName) use ($table, $platform) {
599 78
                        return $table->getColumn($columnName)->getQuotedName($platform);
600 78
                    }, $index->getColumns());
601 78
                    $options['primary_index'] = $index;
602 10
                } elseif ($index->isUnique()) {
603 4
                    throw Exception::notSupported(
604 4
                        "Unique constraints are not supported. Use `primary key` instead"
605 4
                    );
606
                } else {
607 6
                    $options['indexes'][$index->getName()] = $index;
608
                }
609
            }
610
        }
611
612 118
        $columnSql = array();
613 118
        $columns = array();
614
615 118
        foreach ($table->getColumns() as $column) {
616 118
            if (null !== $this->_eventManager &&
617 118
                $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)
618
            ) {
619 2
                $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this);
620 2
                $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
621
622 2
                $columnSql = array_merge($columnSql, $eventArgs->getSql());
623
624 2
                if ($eventArgs->isDefaultPrevented()) {
625
                    continue;
626
                }
627
            }
628 118
            $columns[$column->getQuotedName($this)] = self::prepareColumnData($this, $column, $options['primary']);
629
        }
630
631 116
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
632 2
            $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
633 2
            $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
634
635 2
            if ($eventArgs->isDefaultPrevented()) {
636
                return array_merge($eventArgs->getSql(), $columnSql);
637
            }
638
        }
639
640 116
        $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
641 114
        if ($this->supportsCommentOnStatement()) {
642
            foreach ($table->getColumns() as $column) {
643
                if ($this->getColumnComment($column)) {
644
                    $sql[] = $this->getCommentOnColumnSQL(
645
                        $tableName,
646
                        $column->getName(),
647
                        $this->getColumnComment($column)
648
                    );
649
                }
650
            }
651
        }
652
653 114
        return array_merge($sql, $columnSql);
654
    }
655
656
    /**
657
     * {@inheritDoc}
658
     */
659 116
    protected function _getCreateTableSQL($name, array $columns, array $options = array())
660
    {
661 116
        $columnListSql = $this->getColumnDeclarationListSQL($columns);
662
663 116
        if (isset($options['primary']) && ! empty($options['primary'])) {
664 78
            $keyColumns = array_unique(array_values($options['primary']));
665 78
            $columnListSql .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
666
        }
667
668 116
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
669 6
            foreach ($options['indexes'] as $index => $definition) {
670 6
                $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
671
            }
672
        }
673
674 116
        if (isset($options['foreignKeys'])) {
675
            throw Exception::notSupported("Create Table: foreign keys");
676
        }
677
678 116
        $query = 'CREATE TABLE ' . $name . ' (' . $columnListSql . ')';
679 116
        $query .= $this->buildShardingOptions($options);
680 116
        $query .= $this->buildPartitionOptions($options);
681 114
        $query .= $this->buildTableOptions($options);
682 114
        return array($query);
683
    }
684
685
    /**
686
     * Build SQL for table options
687
     *
688
     * @param mixed[] $options
689
     *
690
     * @return string
691
     */
692 114
    private function buildTableOptions(array $options)
693
    {
694 114
        if (! isset($options['table_options'])) {
695 110
            return '';
696
        }
697
698 4
        $tableOptions = [];
699 4
        foreach ($options['table_options'] as $key => $val) {
700 4
            $tableOptions[] = sprintf('"%s" = %s', $key, $this->quoteStringLiteral($val));
701
        }
702 4
        if (count($tableOptions) == 0) {
703
            return '';
704
        }
705
706 4
        return sprintf(' WITH (%s)', implode(', ', $tableOptions));
707
    }
708
709
    /**
710
     * Build SQL for sharding options.
711
     *
712
     * @param mixed[] $options
713
     *
714
     * @return string
715
     */
716 116
    private function buildShardingOptions(array $options)
717
    {
718 116
        $shardingOptions = [];
719
720 116
        if (isset($options['sharding_routing_column'])) {
721 4
            $columnName = new Identifier($options['sharding_routing_column']);
722 4
            $shardingOptions[] = sprintf('BY (%s)', $columnName->getQuotedName($this));
723
        }
724 116
        if (isset($options['sharding_num_shards'])) {
725 4
            $shardingOptions[] = sprintf("INTO %d SHARDS", $options['sharding_num_shards']);
726
        }
727
728 116
        if (count($shardingOptions) == 0) {
729 112
            return '';
730
        }
731
732 4
        return sprintf(" CLUSTERED %s", implode(' ', $shardingOptions));
733
    }
734
735
    /**
736
     * Build SQL for partition options.
737
     *
738
     * @param mixed[] $options
739
     *
740
     * @return string
741
     */
742 116
    private function buildPartitionOptions(array $options)
743
    {
744 116
        if (! isset($options['partition_columns'])) {
745 110
            return '';
746
        }
747 6
        $columns = $options['partition_columns'];
748 6
        if (! is_array($columns)) {
749 2
            throw new InvalidArgumentException(sprintf("Expecting array type at 'partition_columns'"));
750
        }
751 4
        $quotedNames = [];
752 4
        foreach ($columns as $name) {
753 4
            $name = new Identifier($name);
754 4
            $quotedNames[] = $name->getQuotedName($this);
755
        }
756
757 4
        return sprintf(" PARTITIONED BY (%s)", implode(', ', $quotedNames));
758
    }
759
760
    /**
761
     * @param \Doctrine\DBAL\Schema\Column $column The name of the table.
762
     * @param array $primaries List of primary key column names
763
     *
764
     * @return array The column data as associative array.
765
     * @throws Exception
766
     */
767 122
    public static function prepareColumnData(AbstractPlatform $platform, $column, $primaries = array())
768
    {
769 122
        if ($column->hasCustomSchemaOption("unique") ? $column->getCustomSchemaOption("unique") : false) {
770 2
            throw Exception::notSupported("Unique constraints are not supported. Use `primary key` instead");
771
        }
772
773 120
        $columnData = array();
774 120
        $columnData['name'] = $column->getQuotedName($platform);
775 120
        $columnData['type'] = $column->getType();
776 120
        $columnData['length'] = $column->getLength();
777 120
        $columnData['notnull'] = $column->getNotNull();
778 120
        $columnData['fixed'] = $column->getFixed();
779 120
        $columnData['unique'] = false;
780 120
        $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption("version") : false;
781
782 120
        if (strtolower($columnData['type']) == $platform->getVarcharTypeDeclarationSQLSnippet(0, false)
783 120
                && $columnData['length'] === null) {
784
            $columnData['length'] = 255;
785
        }
786
787 120
        $columnData['unsigned'] = $column->getUnsigned();
788 120
        $columnData['precision'] = $column->getPrecision();
789 120
        $columnData['scale'] = $column->getScale();
790 120
        $columnData['default'] = $column->getDefault();
791 120
        $columnData['columnDefinition'] = $column->getColumnDefinition();
792 120
        $columnData['autoincrement'] = $column->getAutoincrement();
793 120
        $columnData['comment'] = $platform->getColumnComment($column);
794 120
        $columnData['platformOptions'] = $column->getPlatformOptions();
795
796 120
        if (in_array($column->getName(), $primaries)) {
797 76
            $columnData['primary'] = true;
798
        }
799 120
        return $columnData;
800
    }
801
802
    /**
803
     * {@inheritDoc}
804
     */
805 2
    public function getCreateDatabaseSQL($database)
806
    {
807 2
        throw Exception::notSupported(__METHOD__);
808
    }
809
810
    /**
811
     * {@inheritDoc}
812
     */
813 2
    public function getDropDatabaseSQL($database)
814
    {
815 2
        throw Exception::notSupported(__METHOD__);
816
    }
817
818
    /**
819
     * {@inheritDoc}
820
     */
821 2
    public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
822
    {
823 2
        throw Exception::notSupported(__METHOD__);
824
    }
825
826
    /**
827
     * {@inheritDoc}
828
     */
829 2
    public function getGuidTypeDeclarationSQL(array $field)
830
    {
831 2
        throw Exception::notSupported(__METHOD__);
832
    }
833
834
    /**
835
     * Returns the SQL query to return the CrateDB specific table options associated
836
     * with a given table.
837
     *
838
     * @return string
839
     */
840 6
    public function getTableOptionsSQL(string $table) : string
841
    {
842 6
        return "SELECT clustered_by, number_of_shards, partitioned_by, number_of_replicas, column_policy, settings " .
843 6
               "FROM information_schema.tables c " .
844 6
               "WHERE " . $this->getTableWhereClause($table);
845
    }
846
}
847