Failed Conditions
Pull Request — master (#2929)
by Alexander
64:54
created

getPreAlterTableIndexForeignKeySQL()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 13
cts 13
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 15
nc 12
nop 1
crap 7
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Platforms;
21
22
use Doctrine\Common\EventManager;
23
use Doctrine\DBAL\DBALException;
24
use Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs;
25
use Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs;
26
use Doctrine\DBAL\Event\SchemaAlterTableEventArgs;
27
use Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs;
28
use Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs;
29
use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs;
30
use Doctrine\DBAL\Event\SchemaCreateTableEventArgs;
31
use Doctrine\DBAL\Event\SchemaDropTableEventArgs;
32
use Doctrine\DBAL\Events;
33
use Doctrine\DBAL\Schema\Column;
34
use Doctrine\DBAL\Schema\ColumnDiff;
35
use Doctrine\DBAL\Schema\Constraint;
36
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
37
use Doctrine\DBAL\Schema\Identifier;
38
use Doctrine\DBAL\Schema\Index;
39
use Doctrine\DBAL\Schema\Sequence;
40
use Doctrine\DBAL\Schema\Table;
41
use Doctrine\DBAL\Schema\TableDiff;
42
use Doctrine\DBAL\TransactionIsolationLevel;
43
use Doctrine\DBAL\Types;
44
use Doctrine\DBAL\Types\Type;
45
use function addcslashes;
46
use function preg_quote;
47
use function preg_replace;
48
use function sprintf;
49
use function strlen;
50
51
/**
52
 * Base class for all DatabasePlatforms. The DatabasePlatforms are the central
53
 * point of abstraction of platform-specific behaviors, features and SQL dialects.
54
 * They are a passive source of information.
55
 *
56
 * @link   www.doctrine-project.org
57
 * @since  2.0
58
 * @author Guilherme Blanco <[email protected]>
59
 * @author Jonathan Wage <[email protected]>
60
 * @author Roman Borschel <[email protected]>
61
 * @author Lukas Smith <[email protected]> (PEAR MDB2 library)
62
 * @author Benjamin Eberlei <[email protected]>
63
 * @todo   Remove any unnecessary methods.
64
 */
65
abstract class AbstractPlatform
66
{
67
    /**
68
     * @var int
69
     */
70
    const CREATE_INDEXES = 1;
71
72
    /**
73
     * @var int
74
     */
75
    const CREATE_FOREIGNKEYS = 2;
76
77
    /**
78
     * @deprecated Use DateIntervalUnit::INTERVAL_UNIT_SECOND.
79
     */
80
    public const DATE_INTERVAL_UNIT_SECOND = DateIntervalUnit::SECOND;
81
82
    /**
83
     * @deprecated Use DateIntervalUnit::MINUTE.
84
     */
85
    public const DATE_INTERVAL_UNIT_MINUTE = DateIntervalUnit::MINUTE;
86
87
    /**
88
     * @deprecated Use DateIntervalUnit::HOUR.
89
     */
90
    public const DATE_INTERVAL_UNIT_HOUR = DateIntervalUnit::HOUR;
91
92
    /**
93
     * @deprecated Use DateIntervalUnit::DAY.
94
     */
95
    public const DATE_INTERVAL_UNIT_DAY = DateIntervalUnit::DAY;
96
97
    /**
98
     * @deprecated Use DateIntervalUnit::WEEK.
99
     */
100
    public const DATE_INTERVAL_UNIT_WEEK = DateIntervalUnit::WEEK;
101
102
    /**
103
     * @deprecated Use DateIntervalUnit::MONTH.
104
     */
105
    public const DATE_INTERVAL_UNIT_MONTH = DateIntervalUnit::MONTH;
106
107
    /**
108
     * @deprecated Use DateIntervalUnit::QUARTER.
109
     */
110
    public const DATE_INTERVAL_UNIT_QUARTER = DateIntervalUnit::QUARTER;
111
112
    /**
113
     * @deprecated Use DateIntervalUnit::QUARTER.
114
     */
115
    public const DATE_INTERVAL_UNIT_YEAR = DateIntervalUnit::YEAR;
116
117
    /**
118
     * @var int
119
     *
120
     * @deprecated Use TrimMode::UNSPECIFIED.
121
     */
122
    public const TRIM_UNSPECIFIED = TrimMode::UNSPECIFIED;
123
124
    /**
125
     * @var int
126
     *
127
     * @deprecated Use TrimMode::LEADING.
128
     */
129
    public const TRIM_LEADING = TrimMode::LEADING;
130
131
    /**
132
     * @var int
133
     *
134
     * @deprecated Use TrimMode::TRAILING.
135
     */
136
    public const TRIM_TRAILING = TrimMode::TRAILING;
137
138
    /**
139
     * @var int
140
     *
141
     * @deprecated Use TrimMode::BOTH.
142
     */
143
    public const TRIM_BOTH = TrimMode::BOTH;
144
145
    /**
146
     * @var array|null
147
     */
148
    protected $doctrineTypeMapping = null;
149
150
    /**
151
     * Contains a list of all columns that should generate parseable column comments for type-detection
152
     * in reverse engineering scenarios.
153
     *
154
     * @var array|null
155
     */
156
    protected $doctrineTypeComments = null;
157
158
    /**
159
     * @var \Doctrine\Common\EventManager
160
     */
161
    protected $_eventManager;
162
163
    /**
164
     * Holds the KeywordList instance for the current platform.
165
     *
166
     * @var \Doctrine\DBAL\Platforms\Keywords\KeywordList
167
     */
168
    protected $_keywords;
169
170
    /**
171
     * Constructor.
172
     */
173 3422
    public function __construct()
174
    {
175 3422
    }
176
177
    /**
178
     * Sets the EventManager used by the Platform.
179
     *
180
     * @param \Doctrine\Common\EventManager $eventManager
181
     */
182 81
    public function setEventManager(EventManager $eventManager)
183
    {
184 81
        $this->_eventManager = $eventManager;
185 81
    }
186
187
    /**
188
     * Gets the EventManager used by the Platform.
189
     *
190
     * @return \Doctrine\Common\EventManager
191
     */
192 45
    public function getEventManager()
193
    {
194 45
        return $this->_eventManager;
195
    }
196
197
    /**
198
     * Returns the SQL snippet that declares a boolean column.
199
     *
200
     * @param array $columnDef
201
     *
202
     * @return string
203
     */
204
    abstract public function getBooleanTypeDeclarationSQL(array $columnDef);
205
206
    /**
207
     * Returns the SQL snippet that declares a 4 byte integer column.
208
     *
209
     * @param array $columnDef
210
     *
211
     * @return string
212
     */
213
    abstract public function getIntegerTypeDeclarationSQL(array $columnDef);
214
215
    /**
216
     * Returns the SQL snippet that declares an 8 byte integer column.
217
     *
218
     * @param array $columnDef
219
     *
220
     * @return string
221
     */
222
    abstract public function getBigIntTypeDeclarationSQL(array $columnDef);
223
224
    /**
225
     * Returns the SQL snippet that declares a 2 byte integer column.
226
     *
227
     * @param array $columnDef
228
     *
229
     * @return string
230
     */
231
    abstract public function getSmallIntTypeDeclarationSQL(array $columnDef);
232
233
    /**
234
     * Returns the SQL snippet that declares common properties of an integer column.
235
     *
236
     * @param array $columnDef
237
     *
238
     * @return string
239
     */
240
    abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef);
241
242
    /**
243
     * Lazy load Doctrine Type Mappings.
244
     *
245
     * @return void
246
     */
247
    abstract protected function initializeDoctrineTypeMappings();
248
249
    /**
250
     * Initializes Doctrine Type Mappings with the platform defaults
251
     * and with all additional type mappings.
252
     *
253
     * @return void
254
     */
255 99
    private function initializeAllDoctrineTypeMappings()
256
    {
257 99
        $this->initializeDoctrineTypeMappings();
258
259 99
        foreach (Type::getTypesMap() as $typeName => $className) {
260 99
            foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) {
261 99
                $this->doctrineTypeMapping[$dbType] = $typeName;
262
            }
263
        }
264 99
    }
265
266
    /**
267
     * Returns the SQL snippet used to declare a VARCHAR column type.
268
     *
269
     * @param array $field
270
     *
271
     * @return string
272
     */
273 331
    public function getVarcharTypeDeclarationSQL(array $field)
274
    {
275 331
        if ( !isset($field['length'])) {
276 81
            $field['length'] = $this->getVarcharDefaultLength();
277
        }
278
279 331
        $fixed = $field['fixed'] ?? false;
280
281 331
        if ($field['length'] > $this->getVarcharMaxLength()) {
282
            return $this->getClobTypeDeclarationSQL($field);
283
        }
284
285 331
        return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed);
286
    }
287
288
    /**
289
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
290
     *
291
     * @param array $field The column definition.
292
     *
293
     * @return string
294
     */
295 22
    public function getBinaryTypeDeclarationSQL(array $field)
296
    {
297 22
        if ( ! isset($field['length'])) {
298 19
            $field['length'] = $this->getBinaryDefaultLength();
299
        }
300
301 22
        $fixed = $field['fixed'] ?? false;
302
303 22
        if ($field['length'] > $this->getBinaryMaxLength()) {
304 21
            return $this->getBlobTypeDeclarationSQL($field);
305
        }
306
307 19
        return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed);
308
    }
309
310
    /**
311
     * Returns the SQL snippet to declare a GUID/UUID field.
312
     *
313
     * By default this maps directly to a CHAR(36) and only maps to more
314
     * special datatypes when the underlying databases support this datatype.
315
     *
316
     * @param array $field
317
     *
318
     * @return string
319
     */
320 6
    public function getGuidTypeDeclarationSQL(array $field)
321
    {
322 6
        $field['length'] = 36;
323 6
        $field['fixed']  = true;
324
325 6
        return $this->getVarcharTypeDeclarationSQL($field);
326
    }
327
328
    /**
329
     * Returns the SQL snippet to declare a JSON field.
330
     *
331
     * By default this maps directly to a CLOB and only maps to more
332
     * special datatypes when the underlying databases support this datatype.
333
     *
334
     * @param array $field
335
     *
336
     * @return string
337
     */
338 30
    public function getJsonTypeDeclarationSQL(array $field)
339
    {
340 30
        return $this->getClobTypeDeclarationSQL($field);
341
    }
342
343
    /**
344
     * @param int  $length
345
     * @param bool $fixed
346
     *
347
     * @return string
348
     *
349
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
350
     */
351
    protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
0 ignored issues
show
Unused Code introduced by
The parameter $fixed 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

351
    protected function getVarcharTypeDeclarationSQLSnippet($length, /** @scrutinizer ignore-unused */ $fixed)

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...
352
    {
353
        throw DBALException::notSupported('VARCHARs not supported by Platform.');
354
    }
355
356
    /**
357
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
358
     *
359
     * @param int  $length The length of the column.
360
     * @param bool $fixed  Whether the column length is fixed.
361
     *
362
     * @return string
363
     *
364
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
365
     */
366
    protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
0 ignored issues
show
Unused Code introduced by
The parameter $fixed 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

366
    protected function getBinaryTypeDeclarationSQLSnippet($length, /** @scrutinizer ignore-unused */ $fixed)

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...
367
    {
368
        throw DBALException::notSupported('BINARY/VARBINARY column types are not supported by this platform.');
369
    }
370
371
    /**
372
     * Returns the SQL snippet used to declare a CLOB column type.
373
     *
374
     * @param array $field
375
     *
376
     * @return string
377
     */
378
    abstract public function getClobTypeDeclarationSQL(array $field);
379
380
    /**
381
     * Returns the SQL Snippet used to declare a BLOB column type.
382
     *
383
     * @param array $field
384
     *
385
     * @return string
386
     */
387
    abstract public function getBlobTypeDeclarationSQL(array $field);
388
389
    /**
390
     * Gets the name of the platform.
391
     *
392
     * @return string
393
     */
394
    abstract public function getName();
395
396
    /**
397
     * Registers a doctrine type to be used in conjunction with a column type of this platform.
398
     *
399
     * @param string $dbType
400
     * @param string $doctrineType
401
     *
402
     * @throws \Doctrine\DBAL\DBALException If the type is not found.
403
     */
404 55
    public function registerDoctrineTypeMapping($dbType, $doctrineType)
405
    {
406 55
        if ($this->doctrineTypeMapping === null) {
407 55
            $this->initializeAllDoctrineTypeMappings();
408
        }
409
410 55
        if (!Types\Type::hasType($doctrineType)) {
411 18
            throw DBALException::typeNotFound($doctrineType);
412
        }
413
414 37
        $dbType = strtolower($dbType);
415 37
        $this->doctrineTypeMapping[$dbType] = $doctrineType;
416
417 37
        $doctrineType = Type::getType($doctrineType);
418
419 37
        if ($doctrineType->requiresSQLCommentHint($this)) {
420 18
            $this->markDoctrineTypeCommented($doctrineType);
421
        }
422 37
    }
423
424
    /**
425
     * Gets the Doctrine type that is mapped for the given database column type.
426
     *
427
     * @param string $dbType
428
     *
429
     * @return string
430
     *
431
     * @throws \Doctrine\DBAL\DBALException
432
     */
433 101
    public function getDoctrineTypeMapping($dbType)
434
    {
435 101
        if ($this->doctrineTypeMapping === null) {
436 21
            $this->initializeAllDoctrineTypeMappings();
437
        }
438
439 101
        $dbType = strtolower($dbType);
440
441 101
        if (!isset($this->doctrineTypeMapping[$dbType])) {
442 18
            throw new \Doctrine\DBAL\DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it.");
443
        }
444
445 83
        return $this->doctrineTypeMapping[$dbType];
446
    }
447
448
    /**
449
     * Checks if a database type is currently supported by this platform.
450
     *
451
     * @param string $dbType
452
     *
453
     * @return bool
454
     */
455 24
    public function hasDoctrineTypeMappingFor($dbType)
456
    {
457 24
        if ($this->doctrineTypeMapping === null) {
458 23
            $this->initializeAllDoctrineTypeMappings();
459
        }
460
461 24
        $dbType = strtolower($dbType);
462
463 24
        return isset($this->doctrineTypeMapping[$dbType]);
464
    }
465
466
    /**
467
     * Initializes the Doctrine Type comments instance variable for in_array() checks.
468
     *
469
     * @return void
470
     */
471 860
    protected function initializeCommentedDoctrineTypes()
472
    {
473 860
        $this->doctrineTypeComments = [];
474
475 860
        foreach (Type::getTypesMap() as $typeName => $className) {
476 860
            $type = Type::getType($typeName);
477
478 860
            if ($type->requiresSQLCommentHint($this)) {
479 860
                $this->doctrineTypeComments[] = $typeName;
480
            }
481
        }
482 860
    }
483
484
    /**
485
     * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type?
486
     *
487
     * @param \Doctrine\DBAL\Types\Type $doctrineType
488
     *
489
     * @return bool
490
     */
491 975
    public function isCommentedDoctrineType(Type $doctrineType)
492
    {
493 975
        if ($this->doctrineTypeComments === null) {
494 842
            $this->initializeCommentedDoctrineTypes();
495
        }
496
497 975
        return in_array($doctrineType->getName(), $this->doctrineTypeComments);
498
    }
499
500
    /**
501
     * Marks this type as to be commented in ALTER TABLE and CREATE TABLE statements.
502
     *
503
     * @param string|\Doctrine\DBAL\Types\Type $doctrineType
504
     *
505
     * @return void
506
     */
507 18
    public function markDoctrineTypeCommented($doctrineType)
508
    {
509 18
        if ($this->doctrineTypeComments === null) {
510 18
            $this->initializeCommentedDoctrineTypes();
511
        }
512
513 18
        $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType;
514 18
    }
515
516
    /**
517
     * Gets the comment to append to a column comment that helps parsing this type in reverse engineering.
518
     *
519
     * @param \Doctrine\DBAL\Types\Type $doctrineType
520
     *
521
     * @return string
522
     */
523 42
    public function getDoctrineTypeComment(Type $doctrineType)
524
    {
525 42
        return '(DC2Type:' . $doctrineType->getName() . ')';
526
    }
527
528
    /**
529
     * Gets the comment of a passed column modified by potential doctrine type comment hints.
530
     *
531
     * @param \Doctrine\DBAL\Schema\Column $column
532
     *
533
     * @return string
534
     */
535 508
    protected function getColumnComment(Column $column)
536
    {
537 508
        $comment = $column->getComment();
538
539 508
        if ($this->isCommentedDoctrineType($column->getType())) {
540 42
            $comment .= $this->getDoctrineTypeComment($column->getType());
541
        }
542
543 508
        return $comment;
544
    }
545
546
    /**
547
     * Gets the character used for identifier quoting.
548
     *
549
     * @return string
550
     */
551 310
    public function getIdentifierQuoteCharacter()
552
    {
553 310
        return '"';
554
    }
555
556
    /**
557
     * Gets the string portion that starts an SQL comment.
558
     *
559
     * @return string
560
     */
561
    public function getSqlCommentStartString()
562
    {
563
        return "--";
564
    }
565
566
    /**
567
     * Gets the string portion that ends an SQL comment.
568
     *
569
     * @return string
570
     */
571
    public function getSqlCommentEndString()
572
    {
573
        return "\n";
574
    }
575
576
    /**
577
     * Gets the maximum length of a varchar field.
578
     *
579
     * @return int
580
     */
581 178
    public function getVarcharMaxLength()
582
    {
583 178
        return 4000;
584
    }
585
586
    /**
587
     * Gets the default length of a varchar field.
588
     *
589
     * @return int
590
     */
591 69
    public function getVarcharDefaultLength()
592
    {
593 69
        return 255;
594
    }
595
596
    /**
597
     * Gets the maximum length of a binary field.
598
     *
599
     * @return int
600
     */
601
    public function getBinaryMaxLength()
602
    {
603
        return 4000;
604
    }
605
606
    /**
607
     * Gets the default length of a binary field.
608
     *
609
     * @return int
610
     */
611 14
    public function getBinaryDefaultLength()
612
    {
613 14
        return 255;
614
    }
615
616
    /**
617
     * Gets all SQL wildcard characters of the platform.
618
     *
619
     * @return array
620
     */
621
    public function getWildcards()
622
    {
623
        return ['%', '_'];
624
    }
625
626
    /**
627
     * Returns the regular expression operator.
628
     *
629
     * @return string
630
     *
631
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
632
     */
633 5
    public function getRegexpExpression()
634
    {
635 5
        throw DBALException::notSupported(__METHOD__);
636
    }
637
638
    /**
639
     * Returns the global unique identifier expression.
640
     *
641
     * @return string
642
     *
643
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
644
     */
645
    public function getGuidExpression()
646
    {
647
        throw DBALException::notSupported(__METHOD__);
648
    }
649
650
    /**
651
     * Returns the SQL snippet to get the average value of a column.
652
     *
653
     * @param string $column The column to use.
654
     *
655
     * @return string Generated SQL including an AVG aggregate function.
656
     */
657
    public function getAvgExpression($column)
658
    {
659
        return 'AVG(' . $column . ')';
660
    }
661
662
    /**
663
     * Returns the SQL snippet to get the number of rows (without a NULL value) of a column.
664
     *
665
     * If a '*' is used instead of a column the number of selected rows is returned.
666
     *
667
     * @param string|integer $column The column to use.
668
     *
669
     * @return string Generated SQL including a COUNT aggregate function.
670
     */
671
    public function getCountExpression($column)
672
    {
673
        return 'COUNT(' . $column . ')';
674
    }
675
676
    /**
677
     * Returns the SQL snippet to get the highest value of a column.
678
     *
679
     * @param string $column The column to use.
680
     *
681
     * @return string Generated SQL including a MAX aggregate function.
682
     */
683
    public function getMaxExpression($column)
684
    {
685
        return 'MAX(' . $column . ')';
686
    }
687
688
    /**
689
     * Returns the SQL snippet to get the lowest value of a column.
690
     *
691
     * @param string $column The column to use.
692
     *
693
     * @return string Generated SQL including a MIN aggregate function.
694
     */
695
    public function getMinExpression($column)
696
    {
697
        return 'MIN(' . $column . ')';
698
    }
699
700
    /**
701
     * Returns the SQL snippet to get the total sum of a column.
702
     *
703
     * @param string $column The column to use.
704
     *
705
     * @return string Generated SQL including a SUM aggregate function.
706
     */
707
    public function getSumExpression($column)
708
    {
709
        return 'SUM(' . $column . ')';
710
    }
711
712
    // scalar functions
713
714
    /**
715
     * Returns the SQL snippet to get the md5 sum of a field.
716
     *
717
     * Note: Not SQL92, but common functionality.
718
     *
719
     * @param string $column
720
     *
721
     * @return string
722
     */
723
    public function getMd5Expression($column)
724
    {
725
        return 'MD5(' . $column . ')';
726
    }
727
728
    /**
729
     * Returns the SQL snippet to get the length of a text field.
730
     *
731
     * @param string $column
732
     *
733
     * @return string
734
     */
735
    public function getLengthExpression($column)
736
    {
737
        return 'LENGTH(' . $column . ')';
738
    }
739
740
    /**
741
     * Returns the SQL snippet to get the squared value of a column.
742
     *
743
     * @param string $column The column to use.
744
     *
745
     * @return string Generated SQL including an SQRT aggregate function.
746
     */
747
    public function getSqrtExpression($column)
748
    {
749
        return 'SQRT(' . $column . ')';
750
    }
751
752
    /**
753
     * Returns the SQL snippet to round a numeric field to the number of decimals specified.
754
     *
755
     * @param string $column
756
     * @param int    $decimals
757
     *
758
     * @return string
759
     */
760
    public function getRoundExpression($column, $decimals = 0)
761
    {
762
        return 'ROUND(' . $column . ', ' . $decimals . ')';
763
    }
764
765
    /**
766
     * Returns the SQL snippet to get the remainder of the division operation $expression1 / $expression2.
767
     *
768
     * @param string $expression1
769
     * @param string $expression2
770
     *
771
     * @return string
772
     */
773
    public function getModExpression($expression1, $expression2)
774
    {
775
        return 'MOD(' . $expression1 . ', ' . $expression2 . ')';
776
    }
777
778
    /**
779
     * Returns the SQL snippet to trim a string.
780
     *
781
     * @param string      $str  The expression to apply the trim to.
782
     * @param int         $mode The position of the trim (leading/trailing/both).
783
     * @param string|bool $char The char to trim, has to be quoted already. Defaults to space.
784
     *
785
     * @return string
786
     */
787
    public function getTrimExpression($str, $mode = TrimMode::UNSPECIFIED, $char = false)
788
    {
789
        $expression = '';
790
791
        switch ($mode) {
792
            case TrimMode::LEADING:
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
793
                $expression = 'LEADING ';
794
                break;
795
796
            case TrimMode::TRAILING:
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
797
                $expression = 'TRAILING ';
798
                break;
799
800
            case TrimMode::BOTH:
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
801
                $expression = 'BOTH ';
802
                break;
803
        }
804
805
        if ($char !== false) {
806
            $expression .= $char . ' ';
0 ignored issues
show
Bug introduced by
Are you sure $char of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

806
            $expression .= /** @scrutinizer ignore-type */ $char . ' ';
Loading history...
807
        }
808
809
        if ($mode || $char !== false) {
810
            $expression .= 'FROM ';
811
        }
812
813
        return 'TRIM(' . $expression . $str . ')';
814
    }
815
816
    /**
817
     * Returns the SQL snippet to trim trailing space characters from the expression.
818
     *
819
     * @param string $str Literal string or column name.
820
     *
821
     * @return string
822
     */
823 4
    public function getRtrimExpression($str)
824
    {
825 4
        return 'RTRIM(' . $str . ')';
826
    }
827
828
    /**
829
     * Returns the SQL snippet to trim leading space characters from the expression.
830
     *
831
     * @param string $str Literal string or column name.
832
     *
833
     * @return string
834
     */
835 4
    public function getLtrimExpression($str)
836
    {
837 4
        return 'LTRIM(' . $str . ')';
838
    }
839
840
    /**
841
     * Returns the SQL snippet to change all characters from the expression to uppercase,
842
     * according to the current character set mapping.
843
     *
844
     * @param string $str Literal string or column name.
845
     *
846
     * @return string
847
     */
848
    public function getUpperExpression($str)
849
    {
850
        return 'UPPER(' . $str . ')';
851
    }
852
853
    /**
854
     * Returns the SQL snippet to change all characters from the expression to lowercase,
855
     * according to the current character set mapping.
856
     *
857
     * @param string $str Literal string or column name.
858
     *
859
     * @return string
860
     */
861
    public function getLowerExpression($str)
862
    {
863
        return 'LOWER(' . $str . ')';
864
    }
865
866
    /**
867
     * Returns the SQL snippet to get the position of the first occurrence of substring $substr in string $str.
868
     *
869
     * @param string   $str      Literal string.
870
     * @param string   $substr   Literal string to find.
871
     * @param int|bool $startPos Position to start at, beginning of string by default.
872
     *
873
     * @return string
874
     *
875
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
876
     */
877
    public function getLocateExpression($str, $substr, $startPos = false)
0 ignored issues
show
Unused Code introduced by
The parameter $substr 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

877
    public function getLocateExpression($str, /** @scrutinizer ignore-unused */ $substr, $startPos = false)

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...
Unused Code introduced by
The parameter $startPos 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

877
    public function getLocateExpression($str, $substr, /** @scrutinizer ignore-unused */ $startPos = false)

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...
878
    {
879
        throw DBALException::notSupported(__METHOD__);
880
    }
881
882
    /**
883
     * Returns the SQL snippet to get the current system date.
884
     *
885
     * @return string
886
     */
887
    public function getNowExpression()
888
    {
889
        return 'NOW()';
890
    }
891
892
    /**
893
     * Returns a SQL snippet to get a substring inside an SQL statement.
894
     *
895
     * Note: Not SQL92, but common functionality.
896
     *
897
     * SQLite only supports the 2 parameter variant of this function.
898
     *
899
     * @param string   $value  An sql string literal or column name/alias.
900
     * @param int      $from   Where to start the substring portion.
901
     * @param int|null $length The substring portion length.
902
     *
903
     * @return string
904
     */
905
    public function getSubstringExpression($value, $from, $length = null)
906
    {
907
        if ($length === null) {
908
            return 'SUBSTRING(' . $value . ' FROM ' . $from . ')';
909
        }
910
911
        return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')';
912
    }
913
914
    /**
915
     * Returns a SQL snippet to concatenate the given expressions.
916
     *
917
     * Accepts an arbitrary number of string parameters. Each parameter must contain an expression.
918
     *
919
     * @return string
920
     */
921 6
    public function getConcatExpression()
922
    {
923 6
        return join(' || ', func_get_args());
924
    }
925
926
    /**
927
     * Returns the SQL for a logical not.
928
     *
929
     * Example:
930
     * <code>
931
     * $q = new Doctrine_Query();
932
     * $e = $q->expr;
933
     * $q->select('*')->from('table')
934
     *   ->where($e->eq('id', $e->not('null'));
935
     * </code>
936
     *
937
     * @param string $expression
938
     *
939
     * @return string The logical expression.
940
     */
941
    public function getNotExpression($expression)
942
    {
943
        return 'NOT(' . $expression . ')';
944
    }
945
946
    /**
947
     * Returns the SQL that checks if an expression is null.
948
     *
949
     * @param string $expression The expression that should be compared to null.
950
     *
951
     * @return string The logical expression.
952
     */
953 4
    public function getIsNullExpression($expression)
954
    {
955 4
        return $expression . ' IS NULL';
956
    }
957
958
    /**
959
     * Returns the SQL that checks if an expression is not null.
960
     *
961
     * @param string $expression The expression that should be compared to null.
962
     *
963
     * @return string The logical expression.
964
     */
965
    public function getIsNotNullExpression($expression)
966
    {
967
        return $expression . ' IS NOT NULL';
968
    }
969
970
    /**
971
     * Returns the SQL that checks if an expression evaluates to a value between two values.
972
     *
973
     * The parameter $expression is checked if it is between $value1 and $value2.
974
     *
975
     * Note: There is a slight difference in the way BETWEEN works on some databases.
976
     * http://www.w3schools.com/sql/sql_between.asp. If you want complete database
977
     * independence you should avoid using between().
978
     *
979
     * @param string $expression The value to compare to.
980
     * @param string $value1     The lower value to compare with.
981
     * @param string $value2     The higher value to compare with.
982
     *
983
     * @return string The logical expression.
984
     */
985
    public function getBetweenExpression($expression, $value1, $value2)
986
    {
987
        return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2;
988
    }
989
990
    /**
991
     * Returns the SQL to get the arccosine of a value.
992
     *
993
     * @param string $value
994
     *
995
     * @return string
996
     */
997
    public function getAcosExpression($value)
998
    {
999
        return 'ACOS(' . $value . ')';
1000
    }
1001
1002
    /**
1003
     * Returns the SQL to get the sine of a value.
1004
     *
1005
     * @param string $value
1006
     *
1007
     * @return string
1008
     */
1009
    public function getSinExpression($value)
1010
    {
1011
        return 'SIN(' . $value . ')';
1012
    }
1013
1014
    /**
1015
     * Returns the SQL to get the PI value.
1016
     *
1017
     * @return string
1018
     */
1019
    public function getPiExpression()
1020
    {
1021
        return 'PI()';
1022
    }
1023
1024
    /**
1025
     * Returns the SQL to get the cosine of a value.
1026
     *
1027
     * @param string $value
1028
     *
1029
     * @return string
1030
     */
1031
    public function getCosExpression($value)
1032
    {
1033
        return 'COS(' . $value . ')';
1034
    }
1035
1036
    /**
1037
     * Returns the SQL to calculate the difference in days between the two passed dates.
1038
     *
1039
     * Computes diff = date1 - date2.
1040
     *
1041
     * @param string $date1
1042
     * @param string $date2
1043
     *
1044
     * @return string
1045
     *
1046
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1047
     */
1048
    public function getDateDiffExpression($date1, $date2)
0 ignored issues
show
Unused Code introduced by
The parameter $date1 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

1048
    public function getDateDiffExpression(/** @scrutinizer ignore-unused */ $date1, $date2)

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...
Unused Code introduced by
The parameter $date2 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

1048
    public function getDateDiffExpression($date1, /** @scrutinizer ignore-unused */ $date2)

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...
1049
    {
1050
        throw DBALException::notSupported(__METHOD__);
1051
    }
1052
1053
    /**
1054
     * Returns the SQL to add the number of given seconds to a date.
1055
     *
1056
     * @param string $date
1057
     * @param int    $seconds
1058
     *
1059
     * @return string
1060
     *
1061
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1062
     */
1063 6
    public function getDateAddSecondsExpression($date, $seconds)
1064
    {
1065 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, DateIntervalUnit::SECOND);
1066
    }
1067
1068
    /**
1069
     * Returns the SQL to subtract the number of given seconds from a date.
1070
     *
1071
     * @param string $date
1072
     * @param int    $seconds
1073
     *
1074
     * @return string
1075
     *
1076
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1077
     */
1078 6
    public function getDateSubSecondsExpression($date, $seconds)
1079
    {
1080 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, DateIntervalUnit::SECOND);
1081
    }
1082
1083
    /**
1084
     * Returns the SQL to add the number of given minutes to a date.
1085
     *
1086
     * @param string $date
1087
     * @param int    $minutes
1088
     *
1089
     * @return string
1090
     *
1091
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1092
     */
1093 6
    public function getDateAddMinutesExpression($date, $minutes)
1094
    {
1095 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, DateIntervalUnit::MINUTE);
1096
    }
1097
1098
    /**
1099
     * Returns the SQL to subtract the number of given minutes from a date.
1100
     *
1101
     * @param string $date
1102
     * @param int    $minutes
1103
     *
1104
     * @return string
1105
     *
1106
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1107
     */
1108 6
    public function getDateSubMinutesExpression($date, $minutes)
1109
    {
1110 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, DateIntervalUnit::MINUTE);
1111
    }
1112
1113
    /**
1114
     * Returns the SQL to add the number of given hours to a date.
1115
     *
1116
     * @param string $date
1117
     * @param int    $hours
1118
     *
1119
     * @return string
1120
     *
1121
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1122
     */
1123 6
    public function getDateAddHourExpression($date, $hours)
1124
    {
1125 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $hours, DateIntervalUnit::HOUR);
1126
    }
1127
1128
    /**
1129
     * Returns the SQL to subtract the number of given hours to a date.
1130
     *
1131
     * @param string $date
1132
     * @param int    $hours
1133
     *
1134
     * @return string
1135
     *
1136
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1137
     */
1138 6
    public function getDateSubHourExpression($date, $hours)
1139
    {
1140 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $hours, DateIntervalUnit::HOUR);
1141
    }
1142
1143
    /**
1144
     * Returns the SQL to add the number of given days to a date.
1145
     *
1146
     * @param string $date
1147
     * @param int    $days
1148
     *
1149
     * @return string
1150
     *
1151
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1152
     */
1153 6
    public function getDateAddDaysExpression($date, $days)
1154
    {
1155 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $days, DateIntervalUnit::DAY);
1156
    }
1157
1158
    /**
1159
     * Returns the SQL to subtract the number of given days to a date.
1160
     *
1161
     * @param string $date
1162
     * @param int    $days
1163
     *
1164
     * @return string
1165
     *
1166
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1167
     */
1168 6
    public function getDateSubDaysExpression($date, $days)
1169
    {
1170 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $days, DateIntervalUnit::DAY);
1171
    }
1172
1173
    /**
1174
     * Returns the SQL to add the number of given weeks to a date.
1175
     *
1176
     * @param string $date
1177
     * @param int    $weeks
1178
     *
1179
     * @return string
1180
     *
1181
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1182
     */
1183 6
    public function getDateAddWeeksExpression($date, $weeks)
1184
    {
1185 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, DateIntervalUnit::WEEK);
1186
    }
1187
1188
    /**
1189
     * Returns the SQL to subtract the number of given weeks from a date.
1190
     *
1191
     * @param string $date
1192
     * @param int    $weeks
1193
     *
1194
     * @return string
1195
     *
1196
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1197
     */
1198 6
    public function getDateSubWeeksExpression($date, $weeks)
1199
    {
1200 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, DateIntervalUnit::WEEK);
1201
    }
1202
1203
    /**
1204
     * Returns the SQL to add the number of given months to a date.
1205
     *
1206
     * @param string $date
1207
     * @param int    $months
1208
     *
1209
     * @return string
1210
     *
1211
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1212
     */
1213 6
    public function getDateAddMonthExpression($date, $months)
1214
    {
1215 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $months, DateIntervalUnit::MONTH);
1216
    }
1217
1218
    /**
1219
     * Returns the SQL to subtract the number of given months to a date.
1220
     *
1221
     * @param string $date
1222
     * @param int    $months
1223
     *
1224
     * @return string
1225
     *
1226
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1227
     */
1228 6
    public function getDateSubMonthExpression($date, $months)
1229
    {
1230 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $months, DateIntervalUnit::MONTH);
1231
    }
1232
1233
    /**
1234
     * Returns the SQL to add the number of given quarters to a date.
1235
     *
1236
     * @param string $date
1237
     * @param int    $quarters
1238
     *
1239
     * @return string
1240
     *
1241
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1242
     */
1243 6
    public function getDateAddQuartersExpression($date, $quarters)
1244
    {
1245 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, DateIntervalUnit::QUARTER);
1246
    }
1247
1248
    /**
1249
     * Returns the SQL to subtract the number of given quarters from a date.
1250
     *
1251
     * @param string $date
1252
     * @param int    $quarters
1253
     *
1254
     * @return string
1255
     *
1256
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1257
     */
1258 6
    public function getDateSubQuartersExpression($date, $quarters)
1259
    {
1260 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, DateIntervalUnit::QUARTER);
1261
    }
1262
1263
    /**
1264
     * Returns the SQL to add the number of given years to a date.
1265
     *
1266
     * @param string $date
1267
     * @param int    $years
1268
     *
1269
     * @return string
1270
     *
1271
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1272
     */
1273 6
    public function getDateAddYearsExpression($date, $years)
1274
    {
1275 6
        return $this->getDateArithmeticIntervalExpression($date, '+', $years, DateIntervalUnit::YEAR);
1276
    }
1277
1278
    /**
1279
     * Returns the SQL to subtract the number of given years from a date.
1280
     *
1281
     * @param string $date
1282
     * @param int    $years
1283
     *
1284
     * @return string
1285
     *
1286
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1287
     */
1288 6
    public function getDateSubYearsExpression($date, $years)
1289
    {
1290 6
        return $this->getDateArithmeticIntervalExpression($date, '-', $years, DateIntervalUnit::YEAR);
1291
    }
1292
1293
    /**
1294
     * Returns the SQL for a date arithmetic expression.
1295
     *
1296
     * @param string $date     The column or literal representing a date to perform the arithmetic operation on.
1297
     * @param string $operator The arithmetic operator (+ or -).
1298
     * @param int    $interval The interval that shall be calculated into the date.
1299
     * @param string $unit     The unit of the interval that shall be calculated into the date.
1300
     *                         One of the DATE_INTERVAL_UNIT_* constants.
1301
     *
1302
     * @return string
1303
     *
1304
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1305
     */
1306
    protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit)
0 ignored issues
show
Unused Code introduced by
The parameter $operator 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

1306
    protected function getDateArithmeticIntervalExpression($date, /** @scrutinizer ignore-unused */ $operator, $interval, $unit)

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...
Unused Code introduced by
The parameter $interval 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

1306
    protected function getDateArithmeticIntervalExpression($date, $operator, /** @scrutinizer ignore-unused */ $interval, $unit)

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...
Unused Code introduced by
The parameter $unit 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

1306
    protected function getDateArithmeticIntervalExpression($date, $operator, $interval, /** @scrutinizer ignore-unused */ $unit)

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...
1307
    {
1308
        throw DBALException::notSupported(__METHOD__);
1309
    }
1310
1311
    /**
1312
     * Returns the SQL bit AND comparison expression.
1313
     *
1314
     * @param string $value1
1315
     * @param string $value2
1316
     *
1317
     * @return string
1318
     */
1319 17
    public function getBitAndComparisonExpression($value1, $value2)
1320
    {
1321 17
        return '(' . $value1 . ' & ' . $value2 . ')';
1322
    }
1323
1324
    /**
1325
     * Returns the SQL bit OR comparison expression.
1326
     *
1327
     * @param string $value1
1328
     * @param string $value2
1329
     *
1330
     * @return string
1331
     */
1332 17
    public function getBitOrComparisonExpression($value1, $value2)
1333
    {
1334 17
        return '(' . $value1 . ' | ' . $value2 . ')';
1335
    }
1336
1337
    /**
1338
     * Returns the FOR UPDATE expression.
1339
     *
1340
     * @return string
1341
     */
1342
    public function getForUpdateSQL()
1343
    {
1344
        return 'FOR UPDATE';
1345
    }
1346
1347
    /**
1348
     * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification.
1349
     *
1350
     * @param string   $fromClause The FROM clause to append the hint for the given lock mode to.
1351
     * @param int|null $lockMode   One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will
1352
     *                             be appended to the FROM clause.
1353
     *
1354
     * @return string
1355
     */
1356
    public function appendLockHint($fromClause, $lockMode)
0 ignored issues
show
Unused Code introduced by
The parameter $lockMode 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

1356
    public function appendLockHint($fromClause, /** @scrutinizer ignore-unused */ $lockMode)

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...
1357
    {
1358
        return $fromClause;
1359
    }
1360
1361
    /**
1362
     * Returns the SQL snippet to append to any SELECT statement which locks rows in shared read lock.
1363
     *
1364
     * This defaults to the ANSI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database
1365
     * vendors allow to lighten this constraint up to be a real read lock.
1366
     *
1367
     * @return string
1368
     */
1369
    public function getReadLockSQL()
1370
    {
1371
        return $this->getForUpdateSQL();
1372
    }
1373
1374
    /**
1375
     * Returns the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows.
1376
     *
1377
     * The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ANSI SQL standard.
1378
     *
1379
     * @return string
1380
     */
1381
    public function getWriteLockSQL()
1382
    {
1383
        return $this->getForUpdateSQL();
1384
    }
1385
1386
    /**
1387
     * Returns the SQL snippet to drop an existing database.
1388
     *
1389
     * @param string $database The name of the database that should be dropped.
1390
     *
1391
     * @return string
1392
     */
1393 5
    public function getDropDatabaseSQL($database)
1394
    {
1395 5
        return 'DROP DATABASE ' . $database;
1396
    }
1397
1398
    /**
1399
     * Returns the SQL snippet to drop an existing table.
1400
     *
1401
     * @param \Doctrine\DBAL\Schema\Table|string $table
1402
     *
1403
     * @return string
1404
     *
1405
     * @throws \InvalidArgumentException
1406
     */
1407 109
    public function getDropTableSQL($table)
1408
    {
1409 109
        $tableArg = $table;
1410
1411 109
        if ($table instanceof Table) {
1412 27
            $table = $table->getQuotedName($this);
1413 94
        } elseif (!is_string($table)) {
0 ignored issues
show
introduced by
The condition is_string($table) is always true.
Loading history...
1414
            throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
1415
        }
1416
1417 109
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaDropTable)) {
1418 18
            $eventArgs = new SchemaDropTableEventArgs($tableArg, $this);
1419 18
            $this->_eventManager->dispatchEvent(Events::onSchemaDropTable, $eventArgs);
1420
1421 18
            if ($eventArgs->isDefaultPrevented()) {
1422
                return $eventArgs->getSql();
1423
            }
1424
        }
1425
1426 109
        return 'DROP TABLE ' . $table;
1427
    }
1428
1429
    /**
1430
     * Returns the SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction.
1431
     *
1432
     * @param \Doctrine\DBAL\Schema\Table|string $table
1433
     *
1434
     * @return string
1435
     */
1436 2
    public function getDropTemporaryTableSQL($table)
1437
    {
1438 2
        return $this->getDropTableSQL($table);
1439
    }
1440
1441
    /**
1442
     * Returns the SQL to drop an index from a table.
1443
     *
1444
     * @param \Doctrine\DBAL\Schema\Index|string $index
1445
     * @param \Doctrine\DBAL\Schema\Table|string $table
1446
     *
1447
     * @return string
1448
     *
1449
     * @throws \InvalidArgumentException
1450
     */
1451 10
    public function getDropIndexSQL($index, $table = null)
1452
    {
1453 10
        if ($index instanceof Index) {
1454 9
            $index = $index->getQuotedName($this);
1455 1
        } elseif (!is_string($index)) {
0 ignored issues
show
introduced by
The condition is_string($index) is always true.
Loading history...
1456
            throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
1457
        }
1458
1459 10
        return 'DROP INDEX ' . $index;
1460
    }
1461
1462
    /**
1463
     * Returns the SQL to drop a constraint.
1464
     *
1465
     * @param \Doctrine\DBAL\Schema\Constraint|string $constraint
1466
     * @param \Doctrine\DBAL\Schema\Table|string      $table
1467
     *
1468
     * @return string
1469
     */
1470 36
    public function getDropConstraintSQL($constraint, $table)
1471
    {
1472 36
        if (! $constraint instanceof Constraint) {
1473 26
            $constraint = new Identifier($constraint);
1474
        }
1475
1476 36
        if (! $table instanceof Table) {
1477 36
            $table = new Identifier($table);
1478
        }
1479
1480 36
        $constraint = $constraint->getQuotedName($this);
1481 36
        $table = $table->getQuotedName($this);
1482
1483 36
        return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint;
1484
    }
1485
1486
    /**
1487
     * Returns the SQL to drop a foreign key.
1488
     *
1489
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey
1490
     * @param \Doctrine\DBAL\Schema\Table|string                $table
1491
     *
1492
     * @return string
1493
     */
1494 21
    public function getDropForeignKeySQL($foreignKey, $table)
1495
    {
1496 21
        if (! $foreignKey instanceof ForeignKeyConstraint) {
1497 8
            $foreignKey = new Identifier($foreignKey);
1498
        }
1499
1500 21
        if (! $table instanceof Table) {
1501 21
            $table = new Identifier($table);
1502
        }
1503
1504 21
        $foreignKey = $foreignKey->getQuotedName($this);
1505 21
        $table = $table->getQuotedName($this);
1506
1507 21
        return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey;
1508
    }
1509
1510
    /**
1511
     * Returns the SQL statement(s) to create a table with the specified name, columns and constraints
1512
     * on this platform.
1513
     *
1514
     * @param \Doctrine\DBAL\Schema\Table $table
1515
     * @param int                         $createFlags
1516
     *
1517
     * @return array The sequence of SQL statements.
1518
     *
1519
     * @throws \Doctrine\DBAL\DBALException
1520
     * @throws \InvalidArgumentException
1521
     */
1522 399
    public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDEXES)
1523
    {
1524 399
        if ( ! is_int($createFlags)) {
0 ignored issues
show
introduced by
The condition is_int($createFlags) is always true.
Loading history...
1525
            throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer.");
1526
        }
1527
1528 399
        if (count($table->getColumns()) === 0) {
1529 18
            throw DBALException::noColumnsSpecifiedForTable($table->getName());
1530
        }
1531
1532 381
        $tableName = $table->getQuotedName($this);
1533 381
        $options = $table->getOptions();
1534 381
        $options['uniqueConstraints'] = [];
1535 381
        $options['indexes'] = [];
1536 381
        $options['primary'] = [];
1537
1538 381
        if (($createFlags&self::CREATE_INDEXES) > 0) {
1539 358
            foreach ($table->getIndexes() as $index) {
1540
                /* @var $index Index */
1541 249
                if ($index->isPrimary()) {
1542 184
                    $options['primary']       = $index->getQuotedColumns($this);
1543 184
                    $options['primary_index'] = $index;
1544
                } else {
1545 249
                    $options['indexes'][$index->getQuotedName($this)] = $index;
1546
                }
1547
            }
1548
        }
1549
1550 381
        $columnSql = [];
1551 381
        $columns = [];
1552
1553 381
        foreach ($table->getColumns() as $column) {
1554
            /* @var \Doctrine\DBAL\Schema\Column $column */
1555
1556 381
            if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) {
1557 18
                $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this);
1558 18
                $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
1559
1560 18
                $columnSql = array_merge($columnSql, $eventArgs->getSql());
1561
1562 18
                if ($eventArgs->isDefaultPrevented()) {
1563
                    continue;
1564
                }
1565
            }
1566
1567 381
            $columnData = $column->toArray();
1568 381
            $columnData['name'] = $column->getQuotedName($this);
1569 381
            $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption('version') : false;
1570 381
            $columnData['comment'] = $this->getColumnComment($column);
1571
1572 381
            if ($columnData['type'] instanceof Types\StringType && $columnData['length'] === null) {
1573 142
                $columnData['length'] = 255;
1574
            }
1575
1576 381
            if (in_array($column->getName(), $options['primary'])) {
1577 164
                $columnData['primary'] = true;
1578
            }
1579
1580 381
            $columns[$columnData['name']] = $columnData;
1581
        }
1582
1583 381
        if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) {
1584 174
            $options['foreignKeys'] = [];
1585 174
            foreach ($table->getForeignKeys() as $fkConstraint) {
1586 31
                $options['foreignKeys'][] = $fkConstraint;
1587
            }
1588
        }
1589
1590 381
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
1591 18
            $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
1592 18
            $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
1593
1594 18
            if ($eventArgs->isDefaultPrevented()) {
1595
                return array_merge($eventArgs->getSql(), $columnSql);
1596
            }
1597
        }
1598
1599 381
        $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
1600 381
        if ($this->supportsCommentOnStatement()) {
1601 141
            foreach ($table->getColumns() as $column) {
1602 141
                $comment = $this->getColumnComment($column);
1603
1604 141
                if (null !== $comment && '' !== $comment) {
1605 141
                    $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment);
1606
                }
1607
            }
1608
        }
1609
1610 381
        return array_merge($sql, $columnSql);
1611
    }
1612
1613
    /**
1614
     * @param string $tableName
1615
     * @param string $columnName
1616
     * @param string $comment
1617
     *
1618
     * @return string
1619
     */
1620 34
    public function getCommentOnColumnSQL($tableName, $columnName, $comment)
1621
    {
1622 34
        $tableName = new Identifier($tableName);
1623 34
        $columnName = new Identifier($columnName);
1624 34
        $comment = $this->quoteStringLiteral($comment);
1625
1626 34
        return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) .
1627 34
            " IS " . $comment;
1628
    }
1629
1630
    /**
1631
     * Returns the SQL to create inline comment on a column.
1632
     *
1633
     * @param string $comment
1634
     *
1635
     * @return string
1636
     *
1637
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1638
     */
1639 41
    public function getInlineColumnCommentSQL($comment)
1640
    {
1641 41
        if (! $this->supportsInlineColumnComments()) {
1642 14
            throw DBALException::notSupported(__METHOD__);
1643
        }
1644
1645 27
        return "COMMENT " . $this->quoteStringLiteral($comment);
1646
    }
1647
1648
    /**
1649
     * Returns the SQL used to create a table.
1650
     *
1651
     * @param string $tableName
1652
     * @param array  $columns
1653
     * @param array  $options
1654
     *
1655
     * @return array
1656
     */
1657 23
    protected function _getCreateTableSQL($tableName, array $columns, array $options = [])
1658
    {
1659 23
        $columnListSql = $this->getColumnDeclarationListSQL($columns);
1660
1661 23
        if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
1662
            foreach ($options['uniqueConstraints'] as $name => $definition) {
1663
                $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
1664
            }
1665
        }
1666
1667 23
        if (isset($options['primary']) && ! empty($options['primary'])) {
1668 10
            $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
1669
        }
1670
1671 23
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
1672
            foreach ($options['indexes'] as $index => $definition) {
1673
                $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
1674
            }
1675
        }
1676
1677 23
        $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
1678
1679 23
        $check = $this->getCheckDeclarationSQL($columns);
1680 23
        if ( ! empty($check)) {
1681 1
            $query .= ', ' . $check;
1682
        }
1683 23
        $query .= ')';
1684
1685 23
        $sql[] = $query;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$sql was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sql = array(); before regardless.
Loading history...
1686
1687 23
        if (isset($options['foreignKeys'])) {
1688 3
            foreach ((array) $options['foreignKeys'] as $definition) {
1689 3
                $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
1690
            }
1691
        }
1692
1693 23
        return $sql;
1694
    }
1695
1696
    /**
1697
     * @return string
1698
     */
1699 2
    public function getCreateTemporaryTableSnippetSQL()
1700
    {
1701 2
        return "CREATE TEMPORARY TABLE";
1702
    }
1703
1704
    /**
1705
     * Returns the SQL to create a sequence on this platform.
1706
     *
1707
     * @param \Doctrine\DBAL\Schema\Sequence $sequence
1708
     *
1709
     * @return string
1710
     *
1711
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1712
     */
1713
    public function getCreateSequenceSQL(Sequence $sequence)
0 ignored issues
show
Unused Code introduced by
The parameter $sequence 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

1713
    public function getCreateSequenceSQL(/** @scrutinizer ignore-unused */ Sequence $sequence)

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...
1714
    {
1715
        throw DBALException::notSupported(__METHOD__);
1716
    }
1717
1718
    /**
1719
     * Returns the SQL to change a sequence on this platform.
1720
     *
1721
     * @param \Doctrine\DBAL\Schema\Sequence $sequence
1722
     *
1723
     * @return string
1724
     *
1725
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1726
     */
1727
    public function getAlterSequenceSQL(Sequence $sequence)
0 ignored issues
show
Unused Code introduced by
The parameter $sequence 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

1727
    public function getAlterSequenceSQL(/** @scrutinizer ignore-unused */ Sequence $sequence)

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...
1728
    {
1729
        throw DBALException::notSupported(__METHOD__);
1730
    }
1731
1732
    /**
1733
     * Returns the SQL to create a constraint on a table on this platform.
1734
     *
1735
     * @param \Doctrine\DBAL\Schema\Constraint   $constraint
1736
     * @param \Doctrine\DBAL\Schema\Table|string $table
1737
     *
1738
     * @return string
1739
     *
1740
     * @throws \InvalidArgumentException
1741
     */
1742 16
    public function getCreateConstraintSQL(Constraint $constraint, $table)
1743
    {
1744 16
        if ($table instanceof Table) {
1745
            $table = $table->getQuotedName($this);
1746
        }
1747
1748 16
        $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this);
1749
1750 16
        $columnList = '('. implode(', ', $constraint->getQuotedColumns($this)) . ')';
1751
1752 16
        $referencesClause = '';
1753 16
        if ($constraint instanceof Index) {
1754 16
            if ($constraint->isPrimary()) {
1755 16
                $query .= ' PRIMARY KEY';
1756 13
            } elseif ($constraint->isUnique()) {
1757 13
                $query .= ' UNIQUE';
1758
            } else {
1759
                throw new \InvalidArgumentException(
1760 16
                    'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().'
1761
                );
1762
            }
1763 13
        } elseif ($constraint instanceof ForeignKeyConstraint) {
1764 13
            $query .= ' FOREIGN KEY';
1765
1766 13
            $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) .
1767 13
                ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')';
1768
        }
1769 16
        $query .= ' '.$columnList.$referencesClause;
1770
1771 16
        return $query;
1772
    }
1773
1774
    /**
1775
     * Returns the SQL to create an index on a table on this platform.
1776
     *
1777
     * @param \Doctrine\DBAL\Schema\Index        $index
1778
     * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created.
1779
     *
1780
     * @return string
1781
     *
1782
     * @throws \InvalidArgumentException
1783
     */
1784 155
    public function getCreateIndexSQL(Index $index, $table)
1785
    {
1786 155
        if ($table instanceof Table) {
1787 1
            $table = $table->getQuotedName($this);
1788
        }
1789 155
        $name = $index->getQuotedName($this);
1790 155
        $columns = $index->getQuotedColumns($this);
1791
1792 155
        if (count($columns) == 0) {
1793
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
1794
        }
1795
1796 155
        if ($index->isPrimary()) {
1797 21
            return $this->getCreatePrimaryKeySQL($index, $table);
1798
        }
1799
1800 136
        $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table;
1801 136
        $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index);
1802
1803 136
        return $query;
1804
    }
1805
1806
    /**
1807
     * Adds condition for partial index.
1808
     *
1809
     * @param \Doctrine\DBAL\Schema\Index $index
1810
     *
1811
     * @return string
1812
     */
1813 183
    protected function getPartialIndexSQL(Index $index)
1814
    {
1815 183
        if ($this->supportsPartialIndexes() && $index->hasOption('where')) {
1816 5
            return  ' WHERE ' . $index->getOption('where');
1817
        }
1818
1819 178
        return '';
1820
    }
1821
1822
    /**
1823
     * Adds additional flags for index generation.
1824
     *
1825
     * @param \Doctrine\DBAL\Schema\Index $index
1826
     *
1827
     * @return string
1828
     */
1829 67
    protected function getCreateIndexSQLFlags(Index $index)
1830
    {
1831 67
        return $index->isUnique() ? 'UNIQUE ' : '';
1832
    }
1833
1834
    /**
1835
     * Returns the SQL to create an unnamed primary key constraint.
1836
     *
1837
     * @param \Doctrine\DBAL\Schema\Index        $index
1838
     * @param \Doctrine\DBAL\Schema\Table|string $table
1839
     *
1840
     * @return string
1841
     */
1842 17
    public function getCreatePrimaryKeySQL(Index $index, $table)
1843
    {
1844 17
        return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
0 ignored issues
show
Bug introduced by
Are you sure $table of type Doctrine\DBAL\Schema\Table|string can be used in concatenation? ( Ignorable by Annotation )

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

1844
        return 'ALTER TABLE ' . /** @scrutinizer ignore-type */ $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
Loading history...
1845
    }
1846
1847
    /**
1848
     * Returns the SQL to create a named schema.
1849
     *
1850
     * @param string $schemaName
1851
     *
1852
     * @return string
1853
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1854
     */
1855 10
    public function getCreateSchemaSQL($schemaName)
0 ignored issues
show
Unused Code introduced by
The parameter $schemaName 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

1855
    public function getCreateSchemaSQL(/** @scrutinizer ignore-unused */ $schemaName)

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...
1856
    {
1857 10
        throw DBALException::notSupported(__METHOD__);
1858
    }
1859
1860
    /**
1861
     * Quotes a string so that it can be safely used as a table or column name,
1862
     * even if it is a reserved word of the platform. This also detects identifier
1863
     * chains separated by dot and quotes them independently.
1864
     *
1865
     * NOTE: Just because you CAN use quoted identifiers doesn't mean
1866
     * you SHOULD use them. In general, they end up causing way more
1867
     * problems than they solve.
1868
     *
1869
     * @param string $str The identifier name to be quoted.
1870
     *
1871
     * @return string The quoted identifier string.
1872
     */
1873 392
    public function quoteIdentifier($str)
1874
    {
1875 392
        if (strpos($str, ".") !== false) {
1876 18
            $parts = array_map([$this, "quoteSingleIdentifier"], explode(".", $str));
1877
1878 18
            return implode(".", $parts);
1879
        }
1880
1881 392
        return $this->quoteSingleIdentifier($str);
1882
    }
1883
1884
    /**
1885
     * Quotes a single identifier (no dot chain separation).
1886
     *
1887
     * @param string $str The identifier name to be quoted.
1888
     *
1889
     * @return string The quoted identifier string.
1890
     */
1891 378
    public function quoteSingleIdentifier($str)
1892
    {
1893 378
        $c = $this->getIdentifierQuoteCharacter();
1894
1895 378
        return $c . str_replace($c, $c.$c, $str) . $c;
1896
    }
1897
1898
    /**
1899
     * Returns the SQL to create a new foreign key.
1900
     *
1901
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key constraint.
1902
     * @param \Doctrine\DBAL\Schema\Table|string         $table      The name of the table on which the foreign key is to be created.
1903
     *
1904
     * @return string
1905
     */
1906 78
    public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
1907
    {
1908 78
        if ($table instanceof Table) {
1909 1
            $table = $table->getQuotedName($this);
1910
        }
1911
1912 78
        $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey);
1913
1914 78
        return $query;
1915
    }
1916
1917
    /**
1918
     * Gets the SQL statements for altering an existing table.
1919
     *
1920
     * This method returns an array of SQL statements, since some platforms need several statements.
1921
     *
1922
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
1923
     *
1924
     * @return array
1925
     *
1926
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1927
     */
1928
    public function getAlterTableSQL(TableDiff $diff)
1929
    {
1930
        throw DBALException::notSupported(__METHOD__);
1931
    }
1932
1933
    /**
1934
     * @param \Doctrine\DBAL\Schema\Column    $column
1935
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
1936
     * @param array                           $columnSql
1937
     *
1938
     * @return bool
1939
     */
1940 96
    protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql)
1941
    {
1942 96
        if (null === $this->_eventManager) {
1943 77
            return false;
1944
        }
1945
1946 19
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) {
1947 1
            return false;
1948
        }
1949
1950 18
        $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this);
1951 18
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableAddColumn, $eventArgs);
1952
1953 18
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
1954
1955 18
        return $eventArgs->isDefaultPrevented();
1956
    }
1957
1958
    /**
1959
     * @param \Doctrine\DBAL\Schema\Column    $column
1960
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
1961
     * @param array                           $columnSql
1962
     *
1963
     * @return bool
1964
     */
1965 76
    protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql)
1966
    {
1967 76
        if (null === $this->_eventManager) {
1968 57
            return false;
1969
        }
1970
1971 19
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) {
1972 1
            return false;
1973
        }
1974
1975 18
        $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this);
1976 18
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRemoveColumn, $eventArgs);
1977
1978 18
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
1979
1980 18
        return $eventArgs->isDefaultPrevented();
1981
    }
1982
1983
    /**
1984
     * @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff
1985
     * @param \Doctrine\DBAL\Schema\TableDiff  $diff
1986
     * @param array                            $columnSql
1987
     *
1988
     * @return bool
1989
     */
1990 185
    protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql)
1991
    {
1992 185
        if (null === $this->_eventManager) {
1993 155
            return false;
1994
        }
1995
1996 30
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) {
1997 12
            return false;
1998
        }
1999
2000 18
        $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this);
2001 18
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs);
2002
2003 18
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
2004
2005 18
        return $eventArgs->isDefaultPrevented();
2006
    }
2007
2008
    /**
2009
     * @param string                          $oldColumnName
2010
     * @param \Doctrine\DBAL\Schema\Column    $column
2011
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2012
     * @param array                           $columnSql
2013
     *
2014
     * @return bool
2015
     */
2016 76
    protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql)
2017
    {
2018 76
        if (null === $this->_eventManager) {
2019 58
            return false;
2020
        }
2021
2022 18
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) {
2023
            return false;
2024
        }
2025
2026 18
        $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this);
2027 18
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRenameColumn, $eventArgs);
2028
2029 18
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
2030
2031 18
        return $eventArgs->isDefaultPrevented();
2032
    }
2033
2034
    /**
2035
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2036
     * @param array                           $sql
2037
     *
2038
     * @return bool
2039
     */
2040 358
    protected function onSchemaAlterTable(TableDiff $diff, &$sql)
2041
    {
2042 358
        if (null === $this->_eventManager) {
2043 321
            return false;
2044
        }
2045
2046 37
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) {
2047 19
            return false;
2048
        }
2049
2050 18
        $eventArgs = new SchemaAlterTableEventArgs($diff, $this);
2051 18
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTable, $eventArgs);
2052
2053 18
        $sql = array_merge($sql, $eventArgs->getSql());
2054
2055 18
        return $eventArgs->isDefaultPrevented();
2056
    }
2057
2058
    /**
2059
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2060
     *
2061
     * @return array
2062
     */
2063 326
    protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
2064
    {
2065 326
        $tableName = $diff->getName($this)->getQuotedName($this);
2066
2067 326
        $sql = [];
2068 326
        if ($this->supportsForeignKeyConstraints()) {
2069 326
            foreach ($diff->removedForeignKeys as $foreignKey) {
2070 25
                $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
2071
            }
2072 326
            foreach ($diff->changedForeignKeys as $foreignKey) {
2073 20
                $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
2074
            }
2075
        }
2076
2077 326
        foreach ($diff->removedIndexes as $index) {
2078 11
            $sql[] = $this->getDropIndexSQL($index, $tableName);
2079
        }
2080 326
        foreach ($diff->changedIndexes as $index) {
2081 16
            if ($index->isPrimary()) {
2082
                $sql[] = $this->getDropPrimaryKeySQL($tableName);
2083
                continue;
2084 326
            }
2085
2086
            $sql[] = $this->getDropIndexSQL($index, $tableName);
2087
        }
2088
2089
        return $sql;
2090
    }
2091
2092 326
    /**
2093
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2094 326
     *
2095 34
     * @return array
2096 326
     */
2097
    protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
2098 326
    {
2099
        $tableName = (false !== $diff->newName)
2100 326
            ? $diff->getNewName()->getQuotedName($this)
2101 326
            : $diff->getName($this)->getQuotedName($this);
2102 20
2103
        $sql = [];
2104
2105 326
        if ($this->supportsForeignKeyConstraints()) {
2106 20
            foreach ($diff->addedForeignKeys as $foreignKey) {
2107
                $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
2108
            }
2109
2110 326
            foreach ($diff->changedForeignKeys as $foreignKey) {
2111 3
                $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
2112
            }
2113
        }
2114 326
2115 16
        foreach ($diff->addedIndexes as $index) {
2116
            $sql[] = $this->getCreateIndexSQL($index, $tableName);
2117
        }
2118 326
2119 85
        foreach ($diff->changedIndexes as $index) {
2120 85
            $sql[] = $this->getCreateIndexSQL($index, $tableName);
2121 85
        }
2122 85
2123
        foreach ($diff->renamedIndexes as $oldIndexName => $index) {
2124
            $oldIndexName = new Identifier($oldIndexName);
2125
            $sql          = array_merge(
2126 326
                $sql,
2127
                $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName)
2128
            );
2129
        }
2130
2131
        return $sql;
2132
    }
2133
2134
    /**
2135
     * Returns the SQL for renaming an index on a table.
2136
     *
2137
     * @param string                      $oldIndexName The name of the index to rename from.
2138 10
     * @param \Doctrine\DBAL\Schema\Index $index        The definition of the index to rename to.
2139
     * @param string                      $tableName    The table to rename the given index on.
2140
     *
2141 10
     * @return array The sequence of SQL statements for renaming the given index.
2142 10
     */
2143
    protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName)
2144
    {
2145
        return [
2146
            $this->getDropIndexSQL($oldIndexName, $tableName),
2147
            $this->getCreateIndexSQL($index, $tableName)
2148
        ];
2149
    }
2150
2151
    /**
2152
     * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions.
2153
     *
2154
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2155
     *
2156
     * @return array
2157
     */
2158
    protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff)
2159
    {
2160
        return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff));
2161
    }
2162
2163
    /**
2164
     * Gets declaration of a number of fields in bulk.
2165
     *
2166
     * @param array $fields A multidimensional associative array.
2167
     *                      The first dimension determines the field name, while the second
2168
     *                      dimension is keyed with the name of the properties
2169
     *                      of the field being declared as array indexes. Currently, the types
2170
     *                      of supported field properties are as follows:
2171
     *
2172
     *      length
2173
     *          Integer value that determines the maximum length of the text
2174
     *          field. If this argument is missing the field should be
2175
     *          declared to have the longest length allowed by the DBMS.
2176
     *
2177
     *      default
2178
     *          Text value to be used as default for this field.
2179
     *
2180
     *      notnull
2181
     *          Boolean flag that indicates whether this field is constrained
2182
     *          to not be set to null.
2183
     *      charset
2184
     *          Text value with the default CHARACTER SET for this field.
2185
     *      collation
2186
     *          Text value with the default COLLATION for this field.
2187 381
     *      unique
2188
     *          unique constraint
2189 381
     *
2190
     * @return string
2191 381
     */
2192 381
    public function getColumnDeclarationListSQL(array $fields)
2193
    {
2194
        $queryFields = [];
2195 381
2196
        foreach ($fields as $fieldName => $field) {
2197
            $queryFields[] = $this->getColumnDeclarationSQL($fieldName, $field);
2198
        }
2199
2200
        return implode(', ', $queryFields);
2201
    }
2202
2203
    /**
2204
     * Obtains DBMS specific SQL code portion needed to declare a generic type
2205
     * field to be used in statements like CREATE TABLE.
2206
     *
2207
     * @param string $name  The name the field to be declared.
2208
     * @param array  $field An associative array with the name of the properties
2209
     *                      of the field being declared as array indexes. Currently, the types
2210
     *                      of supported field properties are as follows:
2211
     *
2212
     *      length
2213
     *          Integer value that determines the maximum length of the text
2214
     *          field. If this argument is missing the field should be
2215
     *          declared to have the longest length allowed by the DBMS.
2216
     *
2217
     *      default
2218
     *          Text value to be used as default for this field.
2219
     *
2220
     *      notnull
2221
     *          Boolean flag that indicates whether this field is constrained
2222
     *          to not be set to null.
2223
     *      charset
2224
     *          Text value with the default CHARACTER SET for this field.
2225
     *      collation
2226
     *          Text value with the default COLLATION for this field.
2227
     *      unique
2228
     *          unique constraint
2229
     *      check
2230
     *          column check constraint
2231 432
     *      columnDefinition
2232
     *          a string that defines the complete column
2233 432
     *
2234 15
     * @return string DBMS specific SQL code portion that should be used to declare the column.
2235
     */
2236 418
    public function getColumnDeclarationSQL($name, array $field)
2237
    {
2238 418
        if (isset($field['columnDefinition'])) {
2239 418
            $columnDef = $this->getCustomTypeDeclarationSQL($field);
2240
        } else {
2241 418
            $default = $this->getDefaultValueDeclarationSQL($field);
2242 418
2243
            $charset = (isset($field['charset']) && $field['charset']) ?
2244 418
                ' ' . $this->getColumnCharsetDeclarationSQL($field['charset']) : '';
2245
2246 418
            $collation = (isset($field['collation']) && $field['collation']) ?
2247 418
                ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : '';
2248
2249 418
            $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
2250 418
2251
            $unique = (isset($field['unique']) && $field['unique']) ?
2252 418
                ' ' . $this->getUniqueFieldDeclarationSQL() : '';
2253 418
2254
            $check = (isset($field['check']) && $field['check']) ?
2255 418
                ' ' . $field['check'] : '';
2256 53
2257
            $typeDecl = $field['type']->getSQLDeclaration($field, $this);
2258
            $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
2259
2260 432
            if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') {
2261
                $columnDef .= ' ' . $this->getInlineColumnCommentSQL($field['comment']);
2262
            }
2263
        }
2264
2265
        return $name . ' ' . $columnDef;
2266
    }
2267
2268
    /**
2269
     * Returns the SQL snippet that declares a floating point column of arbitrary precision.
2270 133
     *
2271
     * @param array $columnDef
2272 133
     *
2273 133
     * @return string
2274 133
     */
2275 133
    public function getDecimalTypeDeclarationSQL(array $columnDef)
2276
    {
2277 133
        $columnDef['precision'] = ( ! isset($columnDef['precision']) || empty($columnDef['precision']))
2278
            ? 10 : $columnDef['precision'];
2279
        $columnDef['scale'] = ( ! isset($columnDef['scale']) || empty($columnDef['scale']))
2280
            ? 0 : $columnDef['scale'];
2281
2282
        return 'NUMERIC(' . $columnDef['precision'] . ', ' . $columnDef['scale'] . ')';
2283
    }
2284
2285
    /**
2286
     * Obtains DBMS specific SQL code portion needed to set a default value
2287
     * declaration to be used in statements like CREATE TABLE.
2288 472
     *
2289
     * @param array $field The field definition array.
2290 472
     *
2291 405
     * @return string DBMS specific SQL code portion needed to set a default value.
2292
     */
2293
    public function getDefaultValueDeclarationSQL($field)
2294 88
    {
2295
        if ( ! isset($field['default'])) {
2296 88
            return empty($field['notnull']) ? ' DEFAULT NULL' : '';
2297
        }
2298
2299
        $default = $field['default'];
2300 88
2301
        if ( ! isset($field['type'])) {
2302 88
            return " DEFAULT '" . $default . "'";
2303 23
        }
2304
2305
        $type = $field['type'];
2306 67
2307 15
        if ($type instanceof Types\PhpIntegerMappingType) {
2308
            return ' DEFAULT ' . $default;
2309
        }
2310 52
2311
        if ($type instanceof Types\PhpDateTimeMappingType && $default === $this->getCurrentTimestampSQL()) {
2312
            return ' DEFAULT ' . $this->getCurrentTimestampSQL();
2313
        }
2314 52
2315 15
        if ($type instanceof Types\TimeType && $default === $this->getCurrentTimeSQL()) {
2316
            return ' DEFAULT ' . $this->getCurrentTimeSQL();
2317
        }
2318 37
2319 15
        if ($type instanceof Types\DateType && $default === $this->getCurrentDateSQL()) {
2320
            return ' DEFAULT ' . $this->getCurrentDateSQL();
2321
        }
2322 37
2323
        if ($type instanceof Types\BooleanType) {
2324
            return " DEFAULT '" . $this->convertBooleans($default) . "'";
2325
        }
2326
2327
        return " DEFAULT '" . $default . "'";
2328
    }
2329
2330
    /**
2331
     * Obtains DBMS specific SQL code portion needed to set a CHECK constraint
2332
     * declaration to be used in statements like CREATE TABLE.
2333 117
     *
2334
     * @param array $definition The check definition.
2335 117
     *
2336 117
     * @return string DBMS specific SQL code portion needed to set a CHECK constraint.
2337 117
     */
2338
    public function getCheckDeclarationSQL(array $definition)
2339
    {
2340 117
        $constraints = [];
2341 5
        foreach ($definition as $field => $def) {
2342
            if (is_string($def)) {
2343
                $constraints[] = 'CHECK (' . $def . ')';
2344 117
            } else {
2345 117
                if (isset($def['min'])) {
2346
                    $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')';
2347
                }
2348
2349
                if (isset($def['max'])) {
2350 117
                    $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')';
2351
                }
2352
            }
2353
        }
2354
2355
        return implode(', ', $constraints);
2356
    }
2357
2358
    /**
2359
     * Obtains DBMS specific SQL code portion needed to set a unique
2360
     * constraint declaration to be used in statements like CREATE TABLE.
2361
     *
2362
     * @param string                      $name  The name of the unique constraint.
2363
     * @param \Doctrine\DBAL\Schema\Index $index The index definition.
2364 28
     *
2365
     * @return string DBMS specific SQL code portion needed to set a constraint.
2366 28
     *
2367 28
     * @throws \InvalidArgumentException
2368
     */
2369 28
    public function getUniqueConstraintDeclarationSQL($name, Index $index)
2370
    {
2371
        $columns = $index->getQuotedColumns($this);
2372
        $name = new Identifier($name);
2373 28
2374 28
        if (count($columns) === 0) {
2375 28
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
2376
        }
2377
2378
        return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE ('
2379
            . $this->getIndexFieldDeclarationListSQL($columns)
2380
            . ')' . $this->getPartialIndexSQL($index);
2381
    }
2382
2383
    /**
2384
     * Obtains DBMS specific SQL code portion needed to set an index
2385
     * declaration to be used in statements like CREATE TABLE.
2386
     *
2387
     * @param string                      $name  The name of the index.
2388
     * @param \Doctrine\DBAL\Schema\Index $index The index definition.
2389 46
     *
2390
     * @return string DBMS specific SQL code portion needed to set an index.
2391 46
     *
2392 46
     * @throws \InvalidArgumentException
2393
     */
2394 46
    public function getIndexDeclarationSQL($name, Index $index)
2395
    {
2396
        $columns = $index->getQuotedColumns($this);
2397
        $name = new Identifier($name);
2398 46
2399 46
        if (count($columns) === 0) {
2400 46
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
2401
        }
2402
2403
        return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' ('
2404
            . $this->getIndexFieldDeclarationListSQL($columns)
2405
            . ')' . $this->getPartialIndexSQL($index);
2406
    }
2407
2408
    /**
2409
     * Obtains SQL code portion needed to create a custom column,
2410
     * e.g. when a field has the "columnDefinition" keyword.
2411
     * Only "AUTOINCREMENT" and "PRIMARY KEY" are added if appropriate.
2412 19
     *
2413
     * @param array $columnDef
2414 19
     *
2415
     * @return string
2416
     */
2417
    public function getCustomTypeDeclarationSQL(array $columnDef)
2418
    {
2419
        return $columnDef['columnDefinition'];
2420
    }
2421
2422
    /**
2423
     * Obtains DBMS specific SQL code portion needed to set an index
2424
     * declaration to be used in statements like CREATE TABLE.
2425 253
     *
2426
     * @param array $fields
2427 253
     *
2428
     * @return string
2429 253
     */
2430 253
    public function getIndexFieldDeclarationListSQL(array $fields)
2431
    {
2432
        $ret = [];
2433 253
2434
        foreach ($fields as $field => $definition) {
2435
            if (is_array($definition)) {
2436
                $ret[] = $field;
2437 253
            } else {
2438
                $ret[] = $definition;
2439
            }
2440
        }
2441
2442
        return implode(', ', $ret);
2443
    }
2444
2445
    /**
2446
     * Returns the required SQL string that fits between CREATE ... TABLE
2447
     * to create the table as a temporary table.
2448
     *
2449
     * Should be overridden in driver classes to return the correct string for the
2450
     * specific database type.
2451
     *
2452
     * The default is to return the string "TEMPORARY" - this will result in a
2453
     * SQL error for any database that does not support temporary tables, or that
2454
     * requires a different SQL command from "CREATE TEMPORARY TABLE".
2455
     *
2456
     * @return string The string required to be placed between "CREATE" and "TABLE"
2457
     *                to generate a temporary table, if possible.
2458
     */
2459
    public function getTemporaryTableSQL()
2460
    {
2461
        return 'TEMPORARY';
2462
    }
2463
2464
    /**
2465
     * Some vendors require temporary table names to be qualified specially.
2466
     *
2467
     * @param string $tableName
2468
     *
2469
     * @return string
2470
     */
2471
    public function getTemporaryTableName($tableName)
2472
    {
2473
        return $tableName;
2474
    }
2475
2476
    /**
2477
     * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2478
     * of a field declaration to be used in statements like CREATE TABLE.
2479
     *
2480 113
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey
2481
     *
2482 113
     * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2483 101
     *                of a field declaration.
2484
     */
2485 101
    public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey)
2486
    {
2487
        $sql  = $this->getForeignKeyBaseDeclarationSQL($foreignKey);
2488
        $sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey);
2489
2490
        return $sql;
2491
    }
2492
2493
    /**
2494
     * Returns the FOREIGN KEY query section dealing with non-standard options
2495
     * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
2496 97
     *
2497
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key definition.
2498 97
     *
2499 97
     * @return string
2500 4
     */
2501
    public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
2502 97
    {
2503 9
        $query = '';
2504
        if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) {
2505
            $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate'));
2506 97
        }
2507
        if ($foreignKey->hasOption('onDelete')) {
2508
            $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
2509
        }
2510
2511
        return $query;
2512
    }
2513
2514
    /**
2515
     * Returns the given referential action in uppercase if valid, otherwise throws an exception.
2516
     *
2517
     * @param string $action The foreign key referential action.
2518 121
     *
2519
     * @return string
2520 121
     *
2521
     * @throws \InvalidArgumentException if unknown referential action given
2522 121
     */
2523 82
    public function getForeignKeyReferentialActionSQL($action)
2524 61
    {
2525 48
        $upper = strtoupper($action);
2526 34
        switch ($upper) {
2527 104
            case 'CASCADE':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
2528
            case 'SET NULL':
2529 17
            case 'NO ACTION':
2530
            case 'RESTRICT':
2531
            case 'SET DEFAULT':
2532
                return $upper;
2533
            default:
2534
                throw new \InvalidArgumentException('Invalid foreign key action: ' . $upper);
2535
        }
2536
    }
2537
2538
    /**
2539
     * Obtains DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2540
     * of a field declaration to be used in statements like CREATE TABLE.
2541
     *
2542
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey
2543 73
     *
2544
     * @return string
2545 73
     *
2546 73
     * @throws \InvalidArgumentException
2547 59
     */
2548
    public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey)
2549 73
    {
2550
        $sql = '';
2551 73
        if (strlen($foreignKey->getName())) {
2552
            $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' ';
2553
        }
2554 73
        $sql .= 'FOREIGN KEY (';
2555
2556
        if (count($foreignKey->getLocalColumns()) === 0) {
2557 73
            throw new \InvalidArgumentException("Incomplete definition. 'local' required.");
2558
        }
2559
        if (count($foreignKey->getForeignColumns()) === 0) {
2560
            throw new \InvalidArgumentException("Incomplete definition. 'foreign' required.");
2561 73
        }
2562 73
        if (strlen($foreignKey->getForeignTableName()) === 0) {
2563 73
            throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required.");
2564 73
        }
2565
2566 73
        $sql .= implode(', ', $foreignKey->getQuotedLocalColumns($this))
2567
            . ') REFERENCES '
2568
            . $foreignKey->getQuotedForeignTableName($this) . ' ('
2569
            . implode(', ', $foreignKey->getQuotedForeignColumns($this)) . ')';
2570
2571
        return $sql;
2572
    }
2573
2574
    /**
2575
     * Obtains DBMS specific SQL code portion needed to set the UNIQUE constraint
2576
     * of a field declaration to be used in statements like CREATE TABLE.
2577
     *
2578
     * @return string DBMS specific SQL code portion needed to set the UNIQUE constraint
2579
     *                of a field declaration.
2580
     */
2581
    public function getUniqueFieldDeclarationSQL()
2582
    {
2583
        return 'UNIQUE';
2584
    }
2585
2586
    /**
2587
     * Obtains DBMS specific SQL code portion needed to set the CHARACTER SET
2588
     * of a field declaration to be used in statements like CREATE TABLE.
2589
     *
2590
     * @param string $charset The name of the charset.
2591
     *
2592
     * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
2593
     *                of a field declaration.
2594
     */
2595
    public function getColumnCharsetDeclarationSQL($charset)
0 ignored issues
show
Unused Code introduced by
The parameter $charset 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

2595
    public function getColumnCharsetDeclarationSQL(/** @scrutinizer ignore-unused */ $charset)

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...
2596
    {
2597
        return '';
2598
    }
2599
2600
    /**
2601
     * Obtains DBMS specific SQL code portion needed to set the COLLATION
2602
     * of a field declaration to be used in statements like CREATE TABLE.
2603
     *
2604 1
     * @param string $collation The name of the collation.
2605
     *
2606 1
     * @return string DBMS specific SQL code portion needed to set the COLLATION
2607
     *                of a field declaration.
2608
     */
2609
    public function getColumnCollationDeclarationSQL($collation)
2610
    {
2611
        return $this->supportsColumnCollation() ? 'COLLATE ' . $collation : '';
2612
    }
2613
2614
    /**
2615 5
     * Whether the platform prefers sequences for ID generation.
2616
     * Subclasses should override this method to return TRUE if they prefer sequences.
2617 5
     *
2618
     * @return bool
2619
     */
2620
    public function prefersSequences()
2621
    {
2622
        return false;
2623
    }
2624
2625
    /**
2626 6
     * Whether the platform prefers identity columns (eg. autoincrement) for ID generation.
2627
     * Subclasses should override this method to return TRUE if they prefer identity columns.
2628 6
     *
2629
     * @return bool
2630
     */
2631
    public function prefersIdentityColumns()
2632
    {
2633
        return false;
2634
    }
2635
2636
    /**
2637
     * Some platforms need the boolean values to be converted.
2638
     *
2639
     * The default conversion in this implementation converts to integers (false => 0, true => 1).
2640
     *
2641
     * Note: if the input is not a boolean the original input might be returned.
2642
     *
2643
     * There are two contexts when converting booleans: Literals and Prepared Statements.
2644
     * This method should handle the literal case
2645 23
     *
2646
     * @param mixed $item A boolean or an array of them.
2647 23
     *
2648
     * @return mixed A boolean database value or an array of them.
2649
     */
2650
    public function convertBooleans($item)
2651
    {
2652
        if (is_array($item)) {
2653 23
            foreach ($item as $k => $value) {
2654 22
                if (is_bool($value)) {
2655
                    $item[$k] = (int) $value;
2656
                }
2657 23
            }
2658
        } elseif (is_bool($item)) {
2659
            $item = (int) $item;
2660
        }
2661
2662
        return $item;
2663
    }
2664
2665
    /**
2666
     * Some platforms have boolean literals that needs to be correctly converted
2667
     *
2668
     * The default conversion tries to convert value into bool "(bool)$item"
2669 49
     *
2670
     * @param mixed $item
2671 49
     *
2672
     * @return bool|null
2673
     */
2674
    public function convertFromBoolean($item)
2675
    {
2676
        return null === $item ? null: (bool) $item ;
2677
    }
2678
2679
    /**
2680
     * This method should handle the prepared statements case. When there is no
2681
     * distinction, it's OK to use the same method.
2682
     *
2683
     * Note: if the input is not a boolean the original input might be returned.
2684 8
     *
2685
     * @param mixed $item A boolean or an array of them.
2686 8
     *
2687
     * @return mixed A boolean database value or an array of them.
2688
     */
2689
    public function convertBooleansToDatabaseValue($item)
2690
    {
2691
        return $this->convertBooleans($item);
2692
    }
2693
2694 11
    /**
2695
     * Returns the SQL specific for the platform to get the current date.
2696 11
     *
2697
     * @return string
2698
     */
2699
    public function getCurrentDateSQL()
2700
    {
2701
        return 'CURRENT_DATE';
2702
    }
2703
2704
    /**
2705
     * Returns the SQL specific for the platform to get the current time.
2706
     *
2707
     * @return string
2708
     */
2709
    public function getCurrentTimeSQL()
2710
    {
2711
        return 'CURRENT_TIME';
2712
    }
2713
2714 17
    /**
2715
     * Returns the SQL specific for the platform to get the current timestamp
2716 17
     *
2717
     * @return string
2718
     */
2719
    public function getCurrentTimestampSQL()
2720
    {
2721
        return 'CURRENT_TIMESTAMP';
2722
    }
2723
2724
    /**
2725
     * Returns the SQL for a given transaction isolation level Connection constant.
2726
     *
2727
     * @param int $level
2728 11
     *
2729
     * @return string
2730
     *
2731 11
     * @throws \InvalidArgumentException
2732 11
     */
2733 11
    protected function _getTransactionIsolationLevelSQL($level)
2734 11
    {
2735 11
        switch ($level) {
2736 11
            case TransactionIsolationLevel::READ_UNCOMMITTED:
2737 11
                return 'READ UNCOMMITTED';
2738 11
            case TransactionIsolationLevel::READ_COMMITTED:
2739
                return 'READ COMMITTED';
2740
            case TransactionIsolationLevel::REPEATABLE_READ:
2741
                return 'REPEATABLE READ';
2742
            case TransactionIsolationLevel::SERIALIZABLE:
2743
                return 'SERIALIZABLE';
2744
            default:
2745
                throw new \InvalidArgumentException('Invalid isolation level:' . $level);
2746
        }
2747
    }
2748
2749 1
    /**
2750
     * @return string
2751 1
     *
2752
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2753
     */
2754
    public function getListDatabasesSQL()
2755
    {
2756
        throw DBALException::notSupported(__METHOD__);
2757
    }
2758
2759
    /**
2760
     * Returns the SQL statement for retrieving the namespaces defined in the database.
2761
     *
2762
     * @return string
2763
     *
2764
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2765
     */
2766
    public function getListNamespacesSQL()
2767
    {
2768
        throw DBALException::notSupported(__METHOD__);
2769
    }
2770
2771
    /**
2772
     * @param string $database
2773
     *
2774
     * @return string
2775
     *
2776
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2777
     */
2778
    public function getListSequencesSQL($database)
2779
    {
2780
        throw DBALException::notSupported(__METHOD__);
2781
    }
2782
2783
    /**
2784
     * @param string $table
2785
     *
2786
     * @return string
2787
     *
2788
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2789
     */
2790
    public function getListTableConstraintsSQL($table)
2791
    {
2792
        throw DBALException::notSupported(__METHOD__);
2793
    }
2794
2795
    /**
2796
     * @param string      $table
2797
     * @param string|null $database
2798
     *
2799
     * @return string
2800
     *
2801
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2802
     */
2803
    public function getListTableColumnsSQL($table, $database = null)
2804
    {
2805
        throw DBALException::notSupported(__METHOD__);
2806
    }
2807
2808
    /**
2809
     * @return string
2810
     *
2811
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2812
     */
2813
    public function getListTablesSQL()
2814
    {
2815
        throw DBALException::notSupported(__METHOD__);
2816
    }
2817
2818
    /**
2819
     * @return string
2820
     *
2821
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2822
     */
2823
    public function getListUsersSQL()
2824
    {
2825
        throw DBALException::notSupported(__METHOD__);
2826
    }
2827
2828
    /**
2829
     * Returns the SQL to list all views of a database or user.
2830
     *
2831
     * @param string $database
2832
     *
2833
     * @return string
2834
     *
2835
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2836
     */
2837
    public function getListViewsSQL($database)
2838
    {
2839
        throw DBALException::notSupported(__METHOD__);
2840
    }
2841
2842
    /**
2843
     * Returns the list of indexes for the current database.
2844
     *
2845
     * The current database parameter is optional but will always be passed
2846
     * when using the SchemaManager API and is the database the given table is in.
2847
     *
2848
     * Attention: Some platforms only support currentDatabase when they
2849
     * are connected with that database. Cross-database information schema
2850
     * requests may be impossible.
2851
     *
2852
     * @param string $table
2853
     * @param string $currentDatabase
2854
     *
2855
     * @return string
2856
     *
2857
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2858
     */
2859
    public function getListTableIndexesSQL($table, $currentDatabase = null)
2860
    {
2861
        throw DBALException::notSupported(__METHOD__);
2862
    }
2863
2864
    /**
2865
     * @param string $table
2866
     *
2867
     * @return string
2868
     *
2869
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2870
     */
2871
    public function getListTableForeignKeysSQL($table)
2872
    {
2873
        throw DBALException::notSupported(__METHOD__);
2874
    }
2875
2876
    /**
2877
     * @param string $name
2878
     * @param string $sql
2879
     *
2880
     * @return string
2881
     *
2882
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2883
     */
2884
    public function getCreateViewSQL($name, $sql)
2885
    {
2886
        throw DBALException::notSupported(__METHOD__);
2887
    }
2888
2889
    /**
2890
     * @param string $name
2891
     *
2892
     * @return string
2893
     *
2894
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2895
     */
2896
    public function getDropViewSQL($name)
2897
    {
2898
        throw DBALException::notSupported(__METHOD__);
2899
    }
2900
2901
    /**
2902
     * Returns the SQL snippet to drop an existing sequence.
2903
     *
2904
     * @param Sequence|string $sequence
2905
     *
2906
     * @return string
2907
     *
2908
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2909
     */
2910
    public function getDropSequenceSQL($sequence)
0 ignored issues
show
Unused Code introduced by
The parameter $sequence 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

2910
    public function getDropSequenceSQL(/** @scrutinizer ignore-unused */ $sequence)

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...
2911
    {
2912
        throw DBALException::notSupported(__METHOD__);
2913
    }
2914
2915
    /**
2916
     * @param string $sequenceName
2917
     *
2918
     * @return string
2919
     *
2920
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2921
     */
2922
    public function getSequenceNextValSQL($sequenceName)
0 ignored issues
show
Unused Code introduced by
The parameter $sequenceName 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

2922
    public function getSequenceNextValSQL(/** @scrutinizer ignore-unused */ $sequenceName)

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...
2923
    {
2924
        throw DBALException::notSupported(__METHOD__);
2925
    }
2926
2927
    /**
2928
     * Returns the SQL to create a new database.
2929
     *
2930
     * @param string $database The name of the database that should be created.
2931 1
     *
2932
     * @return string
2933 1
     *
2934
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2935
     */
2936
    public function getCreateDatabaseSQL($database)
2937
    {
2938
        throw DBALException::notSupported(__METHOD__);
2939
    }
2940
2941
    /**
2942
     * Returns the SQL to set the transaction isolation level.
2943
     *
2944
     * @param int $level
2945
     *
2946
     * @return string
2947
     *
2948
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2949
     */
2950
    public function getSetTransactionIsolationSQL($level)
2951
    {
2952
        throw DBALException::notSupported(__METHOD__);
2953
    }
2954
2955
    /**
2956
     * Obtains DBMS specific SQL to be used to create datetime fields in
2957
     * statements like CREATE TABLE.
2958
     *
2959
     * @param array $fieldDeclaration
2960
     *
2961
     * @return string
2962
     *
2963
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2964
     */
2965
    public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
2966
    {
2967
        throw DBALException::notSupported(__METHOD__);
2968
    }
2969
2970
    /**
2971
     * Obtains DBMS specific SQL to be used to create datetime with timezone offset fields.
2972 15
     *
2973
     * @param array $fieldDeclaration
2974 15
     *
2975
     * @return string
2976
     */
2977
    public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
2978
    {
2979
        return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration);
2980
    }
2981
2982
2983
    /**
2984
     * Obtains DBMS specific SQL to be used to create date fields in statements
2985
     * like CREATE TABLE.
2986
     *
2987
     * @param array $fieldDeclaration
2988
     *
2989
     * @return string
2990
     *
2991
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2992
     */
2993
    public function getDateTypeDeclarationSQL(array $fieldDeclaration)
2994
    {
2995
        throw DBALException::notSupported(__METHOD__);
2996
    }
2997
2998
    /**
2999
     * Obtains DBMS specific SQL to be used to create time fields in statements
3000
     * like CREATE TABLE.
3001
     *
3002
     * @param array $fieldDeclaration
3003
     *
3004
     * @return string
3005
     *
3006
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3007
     */
3008
    public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
3009
    {
3010
        throw DBALException::notSupported(__METHOD__);
3011
    }
3012
3013 105
    /**
3014
     * @param array $fieldDeclaration
3015 105
     *
3016
     * @return string
3017
     */
3018
    public function getFloatDeclarationSQL(array $fieldDeclaration)
3019
    {
3020
        return 'DOUBLE PRECISION';
3021
    }
3022
3023
    /**
3024
     * Gets the default transaction isolation level of the platform.
3025
     *
3026
     * @return int The default isolation level.
3027
     *
3028
     * @see TransactionIsolationLevel
3029
     */
3030
    public function getDefaultTransactionIsolationLevel()
3031
    {
3032
        return TransactionIsolationLevel::READ_COMMITTED;
3033
    }
3034
3035
    /* supports*() methods */
3036
3037 6
    /**
3038
     * Whether the platform supports sequences.
3039 6
     *
3040
     * @return bool
3041
     */
3042
    public function supportsSequences()
3043
    {
3044
        return false;
3045
    }
3046
3047
    /**
3048
     * Whether the platform supports identity columns.
3049
     *
3050 1
     * Identity columns are columns that receive an auto-generated value from the
3051
     * database on insert of a row.
3052 1
     *
3053
     * @return bool
3054
     */
3055
    public function supportsIdentityColumns()
3056
    {
3057
        return false;
3058
    }
3059
3060
    /**
3061
     * Whether the platform emulates identity columns through sequences.
3062
     *
3063
     * Some platforms that do not support identity columns natively
3064 13
     * but support sequences can emulate identity columns by using
3065
     * sequences.
3066 13
     *
3067
     * @return bool
3068
     */
3069
    public function usesSequenceEmulatedIdentityColumns()
3070
    {
3071
        return false;
3072
    }
3073
3074
    /**
3075
     * Returns the name of the sequence for a particular identity column in a particular table.
3076
     *
3077
     * @param string $tableName  The name of the table to return the sequence name for.
3078
     * @param string $columnName The name of the identity column in the table to return the sequence name for.
3079
     *
3080
     * @return string
3081 12
     *
3082
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3083 12
     *
3084
     * @see    usesSequenceEmulatedIdentityColumns
3085
     */
3086
    public function getIdentitySequenceName($tableName, $columnName)
3087
    {
3088
        throw DBALException::notSupported(__METHOD__);
3089
    }
3090
3091 4
    /**
3092
     * Whether the platform supports indexes.
3093 4
     *
3094
     * @return bool
3095
     */
3096
    public function supportsIndexes()
3097
    {
3098
        return true;
3099
    }
3100
3101 143
    /**
3102
     * Whether the platform supports partial indexes.
3103 143
     *
3104
     * @return bool
3105
     */
3106
    public function supportsPartialIndexes()
3107
    {
3108
        return false;
3109
    }
3110
3111 5
    /**
3112
     * Whether the platform supports altering tables.
3113 5
     *
3114
     * @return bool
3115
     */
3116
    public function supportsAlterTable()
3117
    {
3118
        return true;
3119
    }
3120
3121 4
    /**
3122
     * Whether the platform supports transactions.
3123 4
     *
3124
     * @return bool
3125
     */
3126
    public function supportsTransactions()
3127
    {
3128
        return true;
3129
    }
3130
3131 22
    /**
3132
     * Whether the platform supports savepoints.
3133 22
     *
3134
     * @return bool
3135
     */
3136
    public function supportsSavepoints()
3137
    {
3138
        return true;
3139
    }
3140
3141 5
    /**
3142
     * Whether the platform supports releasing savepoints.
3143 5
     *
3144
     * @return bool
3145
     */
3146
    public function supportsReleaseSavepoints()
3147
    {
3148
        return $this->supportsSavepoints();
3149
    }
3150
3151 4
    /**
3152
     * Whether the platform supports primary key constraints.
3153 4
     *
3154
     * @return bool
3155
     */
3156
    public function supportsPrimaryConstraints()
3157
    {
3158
        return true;
3159
    }
3160
3161 423
    /**
3162
     * Whether the platform supports foreign key constraints.
3163 423
     *
3164
     * @return bool
3165
     */
3166
    public function supportsForeignKeyConstraints()
3167
    {
3168
        return true;
3169
    }
3170
3171 101
    /**
3172
     * Whether this platform supports onUpdate in foreign key constraints.
3173 101
     *
3174
     * @return bool
3175
     */
3176
    public function supportsForeignKeyOnUpdate()
3177
    {
3178
        return ($this->supportsForeignKeyConstraints() && true);
3179
    }
3180
3181 10
    /**
3182
     * Whether the platform supports database schemas.
3183 10
     *
3184
     * @return bool
3185
     */
3186
    public function supportsSchemas()
3187
    {
3188
        return false;
3189
    }
3190
3191
    /**
3192
     * Whether this platform can emulate schemas.
3193
     *
3194
     * Platforms that either support or emulate schemas don't automatically
3195 4
     * filter a schema for the namespaced elements in {@link
3196
     * AbstractManager#createSchema}.
3197 4
     *
3198
     * @return bool
3199
     */
3200
    public function canEmulateSchemas()
3201
    {
3202
        return false;
3203
    }
3204
3205
    /**
3206
     * Returns the default schema name.
3207
     *
3208
     * @return string
3209
     *
3210
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3211
     */
3212
    public function getDefaultSchemaName()
3213
    {
3214
        throw DBALException::notSupported(__METHOD__);
3215
    }
3216
3217
    /**
3218
     * Whether this platform supports create database.
3219 4
     *
3220
     * Some databases don't allow to create and drop databases at all or only with certain tools.
3221 4
     *
3222
     * @return bool
3223
     */
3224
    public function supportsCreateDropDatabase()
3225
    {
3226
        return true;
3227
    }
3228
3229 4
    /**
3230
     * Whether the platform supports getting the affected rows of a recent update/delete type query.
3231 4
     *
3232
     * @return bool
3233
     */
3234
    public function supportsGettingAffectedRows()
3235
    {
3236
        return true;
3237
    }
3238
3239 196
    /**
3240
     * Whether this platform support to add inline column comments as postfix.
3241 196
     *
3242
     * @return bool
3243
     */
3244
    public function supportsInlineColumnComments()
3245
    {
3246
        return false;
3247
    }
3248
3249 247
    /**
3250
     * Whether this platform support the proprietary syntax "COMMENT ON asset".
3251 247
     *
3252
     * @return bool
3253
     */
3254
    public function supportsCommentOnStatement()
3255
    {
3256
        return false;
3257
    }
3258
3259 300
    /**
3260
     * Does this platform have native guid type.
3261 300
     *
3262
     * @return bool
3263
     */
3264
    public function hasNativeGuidType()
3265
    {
3266
        return false;
3267
    }
3268
3269 626
    /**
3270
     * Does this platform have native JSON type.
3271 626
     *
3272
     * @return bool
3273
     */
3274
    public function hasNativeJsonType()
3275
    {
3276
        return false;
3277
    }
3278
3279
    /**
3280
     * @deprecated
3281
     * @todo Remove in 3.0
3282
     */
3283
    public function getIdentityColumnNullInsertSQL()
3284
    {
3285
        return "";
3286
    }
3287
3288 1
    /**
3289
     * Whether this platform supports views.
3290 1
     *
3291
     * @return bool
3292
     */
3293
    public function supportsViews()
3294
    {
3295
        return true;
3296
    }
3297
3298
    /**
3299
     * Does this platform support column collation?
3300
     *
3301
     * @return bool
3302
     */
3303
    public function supportsColumnCollation()
3304
    {
3305
        return false;
3306
    }
3307
3308
    /**
3309 18
     * Gets the format string, as accepted by the date() function, that describes
3310
     * the format of a stored datetime value of this platform.
3311 18
     *
3312
     * @return string The format string.
3313
     */
3314
    public function getDateTimeFormatString()
3315
    {
3316
        return 'Y-m-d H:i:s';
3317
    }
3318
3319
    /**
3320 8
     * Gets the format string, as accepted by the date() function, that describes
3321
     * the format of a stored datetime with timezone value of this platform.
3322 8
     *
3323
     * @return string The format string.
3324
     */
3325
    public function getDateTimeTzFormatString()
3326
    {
3327
        return 'Y-m-d H:i:s';
3328
    }
3329
3330
    /**
3331 7
     * Gets the format string, as accepted by the date() function, that describes
3332
     * the format of a stored date value of this platform.
3333 7
     *
3334
     * @return string The format string.
3335
     */
3336
    public function getDateFormatString()
3337
    {
3338
        return 'Y-m-d';
3339
    }
3340
3341
    /**
3342 6
     * Gets the format string, as accepted by the date() function, that describes
3343
     * the format of a stored time value of this platform.
3344 6
     *
3345
     * @return string The format string.
3346
     */
3347
    public function getTimeFormatString()
3348
    {
3349
        return 'H:i:s';
3350
    }
3351
3352
    /**
3353
     * Adds an driver-specific LIMIT clause to the query.
3354
     *
3355
     * @param string   $query
3356
     * @param int|null $limit
3357
     * @param int|null $offset
3358 118
     *
3359
     * @return string
3360 118
     *
3361 112
     * @throws DBALException
3362
     */
3363
    final public function modifyLimitQuery($query, $limit, $offset = null)
3364 118
    {
3365 47
        if ($limit !== null) {
3366
            $limit = (int) $limit;
3367 47
        }
3368
3369
        if ($offset !== null) {
3370 47
            $offset = (int) $offset;
3371
3372
            if ($offset < 0) {
3373
                throw new DBALException("LIMIT argument offset=$offset is not valid");
3374
            }
3375 118
            if ($offset > 0 && ! $this->supportsLimitOffset()) {
3376
                throw new DBALException(sprintf("Platform %s does not support offset values in limit queries.", $this->getName()));
3377
            }
3378
        }
3379
3380
        return $this->doModifyLimitQuery($query, $limit, $offset);
3381
    }
3382
3383
    /**
3384
     * Adds an driver-specific LIMIT clause to the query.
3385
     *
3386
     * @param string   $query
3387 19
     * @param int|null $limit
3388
     * @param int|null $offset
3389 19
     *
3390 19
     * @return string
3391
     */
3392
    protected function doModifyLimitQuery($query, $limit, $offset)
3393 19
    {
3394 13
        if ($limit !== null) {
3395
            $query .= ' LIMIT ' . $limit;
3396
        }
3397 19
3398
        if ($offset !== null) {
3399
            $query .= ' OFFSET ' . $offset;
3400
        }
3401
3402
        return $query;
3403
    }
3404
3405 18
    /**
3406
     * Whether the database platform support offsets in modify limit clauses.
3407 18
     *
3408
     * @return bool
3409
     */
3410
    public function supportsLimitOffset()
3411
    {
3412
        return true;
3413
    }
3414
3415
    /**
3416
     * Gets the character casing of a column in an SQL result set of this platform.
3417
     *
3418
     * @param string $column The column name for which to get the correct character casing.
3419
     *
3420
     * @return string The column name in the character casing used in SQL result sets.
3421
     */
3422
    public function getSQLResultCasing($column)
3423
    {
3424
        return $column;
3425
    }
3426
3427
    /**
3428
     * Makes any fixes to a name of a schema element (table, sequence, ...) that are required
3429
     * by restrictions of the platform, like a maximum length.
3430
     *
3431
     * @param string $schemaElementName
3432
     *
3433
     * @return string
3434
     */
3435
    public function fixSchemaElementName($schemaElementName)
3436
    {
3437
        return $schemaElementName;
3438
    }
3439
3440 14
    /**
3441
     * Maximum length of any given database identifier, like tables or column names.
3442 14
     *
3443
     * @return int
3444
     */
3445
    public function getMaxIdentifierLength()
3446
    {
3447
        return 63;
3448
    }
3449
3450
    /**
3451
     * Returns the insert SQL for an empty insert statement.
3452
     *
3453 1
     * @param string $tableName
3454
     * @param string $identifierColumnName
3455 1
     *
3456
     * @return string
3457
     */
3458
    public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
3459
    {
3460
        return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)';
3461
    }
3462
3463
    /**
3464
     * Generates a Truncate Table SQL statement for a given table.
3465
     *
3466
     * Cascade is not supported on many platforms but would optionally cascade the truncate by
3467
     * following the foreign keys.
3468
     *
3469 3
     * @param string $tableName
3470
     * @param bool   $cascade
3471 3
     *
3472
     * @return string
3473 3
     */
3474
    public function getTruncateTableSQL($tableName, $cascade = false)
0 ignored issues
show
Unused Code introduced by
The parameter $cascade 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

3474
    public function getTruncateTableSQL($tableName, /** @scrutinizer ignore-unused */ $cascade = false)

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...
3475
    {
3476
        $tableIdentifier = new Identifier($tableName);
3477
3478
        return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this);
3479
    }
3480
3481 8
    /**
3482
     * This is for test reasons, many vendors have special requirements for dummy statements.
3483 8
     *
3484
     * @return string
3485
     */
3486
    public function getDummySelectSQL()
3487
    {
3488
        return 'SELECT 1';
3489
    }
3490
3491
    /**
3492
     * Returns the SQL to create a new savepoint.
3493 1
     *
3494
     * @param string $savepoint
3495 1
     *
3496
     * @return string
3497
     */
3498
    public function createSavePoint($savepoint)
3499
    {
3500
        return 'SAVEPOINT ' . $savepoint;
3501
    }
3502
3503
    /**
3504
     * Returns the SQL to release a savepoint.
3505 1
     *
3506
     * @param string $savepoint
3507 1
     *
3508
     * @return string
3509
     */
3510
    public function releaseSavePoint($savepoint)
3511
    {
3512
        return 'RELEASE SAVEPOINT ' . $savepoint;
3513
    }
3514
3515
    /**
3516
     * Returns the SQL to rollback a savepoint.
3517 1
     *
3518
     * @param string $savepoint
3519 1
     *
3520
     * @return string
3521
     */
3522
    public function rollbackSavePoint($savepoint)
3523
    {
3524
        return 'ROLLBACK TO SAVEPOINT ' . $savepoint;
3525
    }
3526
3527
    /**
3528
     * Returns the keyword list instance of this platform.
3529 1078
     *
3530
     * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList
3531
     *
3532 1078
     * @throws \Doctrine\DBAL\DBALException If no keyword list is specified.
3533 1011
     */
3534
    final public function getReservedKeywordsList()
3535
    {
3536 954
        // Check for an existing instantiation of the keywords class.
3537 954
        if ($this->_keywords) {
3538 954
            return $this->_keywords;
3539
        }
3540
3541
        $class = $this->getReservedKeywordsClass();
3542
        $keywords = new $class;
3543 954
        if ( ! $keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList) {
3544
            throw DBALException::notSupported(__METHOD__);
3545 954
        }
3546
3547
        // Store the instance so it doesn't need to be generated on every request.
3548
        $this->_keywords = $keywords;
3549
3550
        return $keywords;
3551
    }
3552
3553
    /**
3554
     * Returns the class name of the reserved keywords list.
3555
     *
3556
     * @return string
3557
     *
3558
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3559
     */
3560
    protected function getReservedKeywordsClass()
3561
    {
3562
        throw DBALException::notSupported(__METHOD__);
3563
    }
3564
3565
    /**
3566
     * Quotes a literal string.
3567
     * This method is NOT meant to fix SQL injections!
3568
     * It is only meant to escape this platform's string literal
3569
     * quote character inside the given literal string.
3570 334
     *
3571
     * @param string $str The literal string to be quoted.
3572 334
     *
3573
     * @return string The quoted literal string.
3574 334
     */
3575
    public function quoteStringLiteral($str)
3576
    {
3577
        $c = $this->getStringLiteralQuoteCharacter();
3578
3579
        return $c . str_replace($c, $c . $c, $str) . $c;
3580
    }
3581
3582 352
    /**
3583
     * Gets the character used for string literal quoting.
3584 352
     *
3585
     * @return string
3586
     */
3587
    public function getStringLiteralQuoteCharacter()
3588
    {
3589
        return "'";
3590
    }
3591
3592
    /**
3593
     * Escapes metacharacters in a string intended to be used with a LIKE
3594
     * operator.
3595 19
     *
3596
     * @param string $inputString a literal, unquoted string
3597 19
     * @param string $escapeChar  should be reused by the caller in the LIKE
3598 19
     *                            expression.
3599 19
     */
3600 19
    final public function escapeStringForLike(string $inputString, string $escapeChar) : string
3601
    {
3602
        return preg_replace(
3603
            '~([' . preg_quote($this->getLikeWildcardCharacters() . $escapeChar, '~') . '])~u',
3604 19
            addcslashes($escapeChar, '\\') . '$1',
3605
            $inputString
3606 19
        );
3607
    }
3608
3609
    protected function getLikeWildcardCharacters() : string
3610
    {
3611
        return '%_';
3612
    }
3613
3614
    protected function getDropPrimaryKeySQL(string $table) : string
3615
    {
3616
        return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
3617
    }
3618
}
3619