Failed Conditions
Pull Request — master (#2929)
by Alexander
63:56
created

getPreAlterTableIndexForeignKeySQL()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 12
cts 12
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 3405
    protected $_keywords;
169
170 3405
    /**
171
     * Constructor.
172
     */
173
    public function __construct()
174
    {
175
    }
176
177 82
    /**
178
     * Sets the EventManager used by the Platform.
179 82
     *
180 82
     * @param \Doctrine\Common\EventManager $eventManager
181
     */
182
    public function setEventManager(EventManager $eventManager)
183
    {
184
        $this->_eventManager = $eventManager;
185
    }
186
187 45
    /**
188
     * Gets the EventManager used by the Platform.
189 45
     *
190
     * @return \Doctrine\Common\EventManager
191
     */
192
    public function getEventManager()
193
    {
194
        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 99
     * Initializes Doctrine Type Mappings with the platform defaults
251
     * and with all additional type mappings.
252 99
     *
253
     * @return void
254 99
     */
255 99
    private function initializeAllDoctrineTypeMappings()
256 99
    {
257
        $this->initializeDoctrineTypeMappings();
258
259 99
        foreach (Type::getTypesMap() as $typeName => $className) {
260
            foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) {
261
                $this->doctrineTypeMapping[$dbType] = $typeName;
262
            }
263
        }
264
    }
265
266
    /**
267
     * Returns the SQL snippet used to declare a VARCHAR column type.
268 331
     *
269
     * @param array $field
270 331
     *
271 81
     * @return string
272
     */
273
    public function getVarcharTypeDeclarationSQL(array $field)
274 331
    {
275
        if ( !isset($field['length'])) {
276 331
            $field['length'] = $this->getVarcharDefaultLength();
277
        }
278
279
        $fixed = $field['fixed'] ?? false;
280 331
281
        if ($field['length'] > $this->getVarcharMaxLength()) {
282
            return $this->getClobTypeDeclarationSQL($field);
283
        }
284
285
        return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed);
286
    }
287
288
    /**
289
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
290 22
     *
291
     * @param array $field The column definition.
292 22
     *
293 19
     * @return string
294
     */
295
    public function getBinaryTypeDeclarationSQL(array $field)
296 22
    {
297
        if ( ! isset($field['length'])) {
298 22
            $field['length'] = $this->getBinaryDefaultLength();
299 21
        }
300
301
        $fixed = $field['fixed'] ?? false;
302 19
303
        if ($field['length'] > $this->getBinaryMaxLength()) {
304
            return $this->getBlobTypeDeclarationSQL($field);
305
        }
306
307
        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 6
     *
316
     * @param array $field
317 6
     *
318 6
     * @return string
319
     */
320 6
    public function getGuidTypeDeclarationSQL(array $field)
321
    {
322
        $field['length'] = 36;
323
        $field['fixed']  = true;
324
325
        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 30
     *
334
     * @param array $field
335 30
     *
336
     * @return string
337
     */
338
    public function getJsonTypeDeclarationSQL(array $field)
339
    {
340
        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 55
     * @param string $dbType
400
     * @param string $doctrineType
401 55
     *
402 55
     * @throws \Doctrine\DBAL\DBALException If the type is not found.
403
     */
404
    public function registerDoctrineTypeMapping($dbType, $doctrineType)
405 55
    {
406 18
        if ($this->doctrineTypeMapping === null) {
407
            $this->initializeAllDoctrineTypeMappings();
408
        }
409 37
410 37
        if (!Types\Type::hasType($doctrineType)) {
411
            throw DBALException::typeNotFound($doctrineType);
412 37
        }
413
414 37
        $dbType = strtolower($dbType);
415 18
        $this->doctrineTypeMapping[$dbType] = $doctrineType;
416
417 37
        $doctrineType = Type::getType($doctrineType);
418
419
        if ($doctrineType->requiresSQLCommentHint($this)) {
420
            $this->markDoctrineTypeCommented($doctrineType);
421
        }
422
    }
423
424
    /**
425
     * Gets the Doctrine type that is mapped for the given database column type.
426
     *
427
     * @param string $dbType
428 101
     *
429
     * @return string
430 101
     *
431 21
     * @throws \Doctrine\DBAL\DBALException
432
     */
433
    public function getDoctrineTypeMapping($dbType)
434 101
    {
435
        if ($this->doctrineTypeMapping === null) {
436 101
            $this->initializeAllDoctrineTypeMappings();
437 18
        }
438
439
        $dbType = strtolower($dbType);
440 83
441
        if (!isset($this->doctrineTypeMapping[$dbType])) {
442
            throw new \Doctrine\DBAL\DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it.");
443
        }
444
445
        return $this->doctrineTypeMapping[$dbType];
446
    }
447
448
    /**
449
     * Checks if a database type is currently supported by this platform.
450 24
     *
451
     * @param string $dbType
452 24
     *
453 23
     * @return bool
454
     */
455
    public function hasDoctrineTypeMappingFor($dbType)
456 24
    {
457
        if ($this->doctrineTypeMapping === null) {
458 24
            $this->initializeAllDoctrineTypeMappings();
459
        }
460
461
        $dbType = strtolower($dbType);
462
463
        return isset($this->doctrineTypeMapping[$dbType]);
464
    }
465
466 860
    /**
467
     * Initializes the Doctrine Type comments instance variable for in_array() checks.
468 860
     *
469
     * @return void
470 860
     */
471 860
    protected function initializeCommentedDoctrineTypes()
472
    {
473 860
        $this->doctrineTypeComments = [];
474 860
475
        foreach (Type::getTypesMap() as $typeName => $className) {
476
            $type = Type::getType($typeName);
477 860
478
            if ($type->requiresSQLCommentHint($this)) {
479
                $this->doctrineTypeComments[] = $typeName;
480
            }
481
        }
482
    }
483
484
    /**
485
     * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type?
486 975
     *
487
     * @param \Doctrine\DBAL\Types\Type $doctrineType
488 975
     *
489 842
     * @return bool
490
     */
491
    public function isCommentedDoctrineType(Type $doctrineType)
492 975
    {
493
        if ($this->doctrineTypeComments === null) {
494
            $this->initializeCommentedDoctrineTypes();
495
        }
496
497
        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 18
     *
503
     * @param string|\Doctrine\DBAL\Types\Type $doctrineType
504 18
     *
505 18
     * @return void
506
     */
507
    public function markDoctrineTypeCommented($doctrineType)
508 18
    {
509 18
        if ($this->doctrineTypeComments === null) {
510
            $this->initializeCommentedDoctrineTypes();
511
        }
512
513
        $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType;
514
    }
515
516
    /**
517
     * Gets the comment to append to a column comment that helps parsing this type in reverse engineering.
518 42
     *
519
     * @param \Doctrine\DBAL\Types\Type $doctrineType
520 42
     *
521
     * @return string
522
     */
523
    public function getDoctrineTypeComment(Type $doctrineType)
524
    {
525
        return '(DC2Type:' . $doctrineType->getName() . ')';
526
    }
527
528
    /**
529
     * Gets the comment of a passed column modified by potential doctrine type comment hints.
530 508
     *
531
     * @param \Doctrine\DBAL\Schema\Column $column
532 508
     *
533
     * @return string
534 508
     */
535 42
    protected function getColumnComment(Column $column)
536
    {
537
        $comment = $column->getComment();
538 508
539
        if ($this->isCommentedDoctrineType($column->getType())) {
540
            $comment .= $this->getDoctrineTypeComment($column->getType());
541
        }
542
543
        return $comment;
544
    }
545
546 310
    /**
547
     * Gets the character used for identifier quoting.
548 310
     *
549
     * @return string
550
     */
551
    public function getIdentifierQuoteCharacter()
552
    {
553
        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 178
    /**
577
     * Gets the maximum length of a varchar field.
578 178
     *
579
     * @return int
580
     */
581
    public function getVarcharMaxLength()
582
    {
583
        return 4000;
584
    }
585
586 69
    /**
587
     * Gets the default length of a varchar field.
588 69
     *
589
     * @return int
590
     */
591
    public function getVarcharDefaultLength()
592
    {
593
        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 14
    /**
607
     * Gets the default length of a binary field.
608 14
     *
609
     * @return int
610
     */
611
    public function getBinaryDefaultLength()
612
    {
613
        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 5
     *
629
     * @return string
630 5
     *
631
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
632
     */
633
    public function getRegexpExpression()
634
    {
635
        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 4
     *
819
     * @param string $str Literal string or column name.
820 4
     *
821
     * @return string
822
     */
823
    public function getRtrimExpression($str)
824
    {
825
        return 'RTRIM(' . $str . ')';
826
    }
827
828
    /**
829
     * Returns the SQL snippet to trim leading space characters from the expression.
830 4
     *
831
     * @param string $str Literal string or column name.
832 4
     *
833
     * @return string
834
     */
835
    public function getLtrimExpression($str)
836
    {
837
        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 6
     *
917
     * Accepts an arbitrary number of string parameters. Each parameter must contain an expression.
918 6
     *
919
     * @return string
920
     */
921
    public function getConcatExpression()
922
    {
923
        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 4
     *
949
     * @param string $expression The expression that should be compared to null.
950 4
     *
951
     * @return string The logical expression.
952
     */
953
    public function getIsNullExpression($expression)
954
    {
955
        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 6
     *
1059
     * @return string
1060 6
     *
1061
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1062
     */
1063
    public function getDateAddSecondsExpression($date, $seconds)
1064
    {
1065
        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 6
     *
1074
     * @return string
1075 6
     *
1076
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1077
     */
1078
    public function getDateSubSecondsExpression($date, $seconds)
1079
    {
1080
        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 6
     *
1089
     * @return string
1090 6
     *
1091
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1092
     */
1093
    public function getDateAddMinutesExpression($date, $minutes)
1094
    {
1095
        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 6
     *
1104
     * @return string
1105 6
     *
1106
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1107
     */
1108
    public function getDateSubMinutesExpression($date, $minutes)
1109
    {
1110
        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 6
     *
1119
     * @return string
1120 6
     *
1121
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1122
     */
1123
    public function getDateAddHourExpression($date, $hours)
1124
    {
1125
        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 6
     *
1134
     * @return string
1135 6
     *
1136
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1137
     */
1138
    public function getDateSubHourExpression($date, $hours)
1139
    {
1140
        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 6
     *
1149
     * @return string
1150 6
     *
1151
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1152
     */
1153
    public function getDateAddDaysExpression($date, $days)
1154
    {
1155
        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 6
     *
1164
     * @return string
1165 6
     *
1166
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1167
     */
1168
    public function getDateSubDaysExpression($date, $days)
1169
    {
1170
        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 6
     *
1179
     * @return string
1180 6
     *
1181
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1182
     */
1183
    public function getDateAddWeeksExpression($date, $weeks)
1184
    {
1185
        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 6
     *
1194
     * @return string
1195 6
     *
1196
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1197
     */
1198
    public function getDateSubWeeksExpression($date, $weeks)
1199
    {
1200
        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 6
     *
1209
     * @return string
1210 6
     *
1211
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1212
     */
1213
    public function getDateAddMonthExpression($date, $months)
1214
    {
1215
        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 6
     *
1224
     * @return string
1225 6
     *
1226
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1227
     */
1228
    public function getDateSubMonthExpression($date, $months)
1229
    {
1230
        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 6
     *
1239
     * @return string
1240 6
     *
1241
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1242
     */
1243
    public function getDateAddQuartersExpression($date, $quarters)
1244
    {
1245
        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 6
     *
1254
     * @return string
1255 6
     *
1256
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1257
     */
1258
    public function getDateSubQuartersExpression($date, $quarters)
1259
    {
1260
        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 6
     *
1269
     * @return string
1270 6
     *
1271
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1272
     */
1273
    public function getDateAddYearsExpression($date, $years)
1274
    {
1275
        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 6
     *
1284
     * @return string
1285 6
     *
1286
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1287
     */
1288
    public function getDateSubYearsExpression($date, $years)
1289
    {
1290
        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 17
     * @param string $value1
1315
     * @param string $value2
1316 17
     *
1317
     * @return string
1318
     */
1319
    public function getBitAndComparisonExpression($value1, $value2)
1320
    {
1321
        return '(' . $value1 . ' & ' . $value2 . ')';
1322
    }
1323
1324
    /**
1325
     * Returns the SQL bit OR comparison expression.
1326
     *
1327 17
     * @param string $value1
1328
     * @param string $value2
1329 17
     *
1330
     * @return string
1331
     */
1332
    public function getBitOrComparisonExpression($value1, $value2)
1333
    {
1334
        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 5
     *
1389
     * @param string $database The name of the database that should be dropped.
1390 5
     *
1391
     * @return string
1392
     */
1393
    public function getDropDatabaseSQL($database)
1394
    {
1395
        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 109
     *
1403
     * @return string
1404 109
     *
1405
     * @throws \InvalidArgumentException
1406 109
     */
1407 27
    public function getDropTableSQL($table)
1408 94
    {
1409
        $tableArg = $table;
1410
1411
        if ($table instanceof Table) {
1412 109
            $table = $table->getQuotedName($this);
1413 18
        } elseif (!is_string($table)) {
0 ignored issues
show
introduced by
The condition ! is_string($table) can never be true.
Loading history...
1414 18
            throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
1415
        }
1416 18
1417
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaDropTable)) {
1418
            $eventArgs = new SchemaDropTableEventArgs($tableArg, $this);
1419
            $this->_eventManager->dispatchEvent(Events::onSchemaDropTable, $eventArgs);
1420
1421 109
            if ($eventArgs->isDefaultPrevented()) {
1422
                return $eventArgs->getSql();
1423
            }
1424
        }
1425
1426
        return 'DROP TABLE ' . $table;
1427
    }
1428
1429
    /**
1430
     * Returns the SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction.
1431 2
     *
1432
     * @param \Doctrine\DBAL\Schema\Table|string $table
1433 2
     *
1434
     * @return string
1435
     */
1436
    public function getDropTemporaryTableSQL($table)
1437
    {
1438
        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 10
     *
1447
     * @return string
1448 10
     *
1449 9
     * @throws \InvalidArgumentException
1450 1
     */
1451
    public function getDropIndexSQL($index, $table = null)
1452
    {
1453
        if ($index instanceof Index) {
1454 10
            $index = $index->getQuotedName($this);
1455
        } elseif (!is_string($index)) {
0 ignored issues
show
introduced by
The condition ! is_string($index) can never be true.
Loading history...
1456
            throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
1457
        }
1458
1459
        return 'DROP INDEX ' . $index;
1460
    }
1461
1462
    /**
1463
     * Returns the SQL to drop a constraint.
1464
     *
1465 36
     * @param \Doctrine\DBAL\Schema\Constraint|string $constraint
1466
     * @param \Doctrine\DBAL\Schema\Table|string      $table
1467 36
     *
1468 26
     * @return string
1469
     */
1470
    public function getDropConstraintSQL($constraint, $table)
1471 36
    {
1472 36
        if (! $constraint instanceof Constraint) {
1473
            $constraint = new Identifier($constraint);
1474
        }
1475 36
1476 36
        if (! $table instanceof Table) {
1477
            $table = new Identifier($table);
1478 36
        }
1479
1480
        $constraint = $constraint->getQuotedName($this);
1481
        $table = $table->getQuotedName($this);
1482
1483
        return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint;
1484
    }
1485
1486
    /**
1487
     * Returns the SQL to drop a foreign key.
1488
     *
1489 21
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey
1490
     * @param \Doctrine\DBAL\Schema\Table|string                $table
1491 21
     *
1492 8
     * @return string
1493
     */
1494
    public function getDropForeignKeySQL($foreignKey, $table)
1495 21
    {
1496 21
        if (! $foreignKey instanceof ForeignKeyConstraint) {
1497
            $foreignKey = new Identifier($foreignKey);
1498
        }
1499 21
1500 21
        if (! $table instanceof Table) {
1501
            $table = new Identifier($table);
1502 21
        }
1503
1504
        $foreignKey = $foreignKey->getQuotedName($this);
1505
        $table = $table->getQuotedName($this);
1506
1507
        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 399
     * @return array The sequence of SQL statements.
1518
     *
1519 399
     * @throws \Doctrine\DBAL\DBALException
1520
     * @throws \InvalidArgumentException
1521
     */
1522
    public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDEXES)
1523 399
    {
1524 18
        if ( ! is_int($createFlags)) {
0 ignored issues
show
introduced by
The condition ! is_int($createFlags) can never be true.
Loading history...
1525
            throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer.");
1526
        }
1527 381
1528 381
        if (count($table->getColumns()) === 0) {
1529 381
            throw DBALException::noColumnsSpecifiedForTable($table->getName());
1530 381
        }
1531 381
1532
        $tableName = $table->getQuotedName($this);
1533 381
        $options = $table->getOptions();
1534 358
        $options['uniqueConstraints'] = [];
1535
        $options['indexes'] = [];
1536 249
        $options['primary'] = [];
1537 184
1538 184
        if (($createFlags&self::CREATE_INDEXES) > 0) {
1539
            foreach ($table->getIndexes() as $index) {
1540 249
                /* @var $index Index */
1541
                if ($index->isPrimary()) {
1542
                    $options['primary']       = $index->getQuotedColumns($this);
1543
                    $options['primary_index'] = $index;
1544
                } else {
1545 381
                    $options['indexes'][$index->getQuotedName($this)] = $index;
1546 381
                }
1547
            }
1548 381
        }
1549
1550
        $columnSql = [];
1551 381
        $columns = [];
1552 18
1553 18
        foreach ($table->getColumns() as $column) {
1554
            /* @var \Doctrine\DBAL\Schema\Column $column */
1555 18
1556
            if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) {
1557 18
                $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this);
1558
                $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
1559
1560
                $columnSql = array_merge($columnSql, $eventArgs->getSql());
1561
1562 381
                if ($eventArgs->isDefaultPrevented()) {
1563 381
                    continue;
1564 381
                }
1565 381
            }
1566
1567 381
            $columnData = $column->toArray();
1568 142
            $columnData['name'] = $column->getQuotedName($this);
1569
            $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption('version') : false;
1570
            $columnData['comment'] = $this->getColumnComment($column);
1571 381
1572 164
            if ($columnData['type'] instanceof Types\StringType && $columnData['length'] === null) {
1573
                $columnData['length'] = 255;
1574
            }
1575 381
1576
            if (in_array($column->getName(), $options['primary'])) {
1577
                $columnData['primary'] = true;
1578 381
            }
1579 174
1580 174
            $columns[$columnData['name']] = $columnData;
1581 31
        }
1582
1583
        if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) {
1584
            $options['foreignKeys'] = [];
1585 381
            foreach ($table->getForeignKeys() as $fkConstraint) {
1586 18
                $options['foreignKeys'][] = $fkConstraint;
1587 18
            }
1588
        }
1589 18
1590
        if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
1591
            $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
1592
            $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
1593
1594 381
            if ($eventArgs->isDefaultPrevented()) {
1595 381
                return array_merge($eventArgs->getSql(), $columnSql);
1596 141
            }
1597 141
        }
1598
1599 141
        $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
1600 141
        if ($this->supportsCommentOnStatement()) {
1601
            foreach ($table->getColumns() as $column) {
1602
                $comment = $this->getColumnComment($column);
1603
1604
                if (null !== $comment && '' !== $comment) {
1605 381
                    $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment);
1606
                }
1607
            }
1608
        }
1609
1610
        return array_merge($sql, $columnSql);
1611
    }
1612
1613
    /**
1614
     * @param string $tableName
1615 34
     * @param string $columnName
1616
     * @param string $comment
1617 34
     *
1618 34
     * @return string
1619 34
     */
1620
    public function getCommentOnColumnSQL($tableName, $columnName, $comment)
1621 34
    {
1622 34
        $tableName = new Identifier($tableName);
1623
        $columnName = new Identifier($columnName);
1624
        $comment = $this->quoteStringLiteral($comment);
1625
1626
        return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) .
1627
            " IS " . $comment;
1628
    }
1629
1630
    /**
1631
     * Returns the SQL to create inline comment on a column.
1632
     *
1633
     * @param string $comment
1634 41
     *
1635
     * @return string
1636 41
     *
1637 14
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1638
     */
1639
    public function getInlineColumnCommentSQL($comment)
1640 27
    {
1641
        if (! $this->supportsInlineColumnComments()) {
1642
            throw DBALException::notSupported(__METHOD__);
1643
        }
1644
1645
        return "COMMENT " . $this->quoteStringLiteral($comment);
1646
    }
1647
1648
    /**
1649
     * Returns the SQL used to create a table.
1650
     *
1651
     * @param string $tableName
1652 23
     * @param array  $columns
1653
     * @param array  $options
1654 23
     *
1655
     * @return array
1656 23
     */
1657
    protected function _getCreateTableSQL($tableName, array $columns, array $options = [])
1658
    {
1659
        $columnListSql = $this->getColumnDeclarationListSQL($columns);
1660
1661
        if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
1662 23
            foreach ($options['uniqueConstraints'] as $name => $definition) {
1663 10
                $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
1664
            }
1665
        }
1666 23
1667
        if (isset($options['primary']) && ! empty($options['primary'])) {
1668
            $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
1669
        }
1670
1671
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
1672 23
            foreach ($options['indexes'] as $index => $definition) {
1673
                $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
1674 23
            }
1675 23
        }
1676 1
1677
        $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
1678 23
1679
        $check = $this->getCheckDeclarationSQL($columns);
1680 23
        if ( ! empty($check)) {
1681
            $query .= ', ' . $check;
1682 23
        }
1683 3
        $query .= ')';
1684 3
1685
        $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
        if (isset($options['foreignKeys'])) {
1688 23
            foreach ((array) $options['foreignKeys'] as $definition) {
1689
                $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
1690
            }
1691
        }
1692
1693
        return $sql;
1694 2
    }
1695
1696 2
    /**
1697
     * @return string
1698
     */
1699
    public function getCreateTemporaryTableSnippetSQL()
1700
    {
1701
        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 16
     *
1738
     * @return string
1739 16
     *
1740
     * @throws \InvalidArgumentException
1741
     */
1742
    public function getCreateConstraintSQL(Constraint $constraint, $table)
1743 16
    {
1744
        if ($table instanceof Table) {
1745 16
            $table = $table->getQuotedName($this);
1746
        }
1747 16
1748 16
        $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this);
1749 16
1750 16
        $columnList = '('. implode(', ', $constraint->getQuotedColumns($this)) . ')';
1751 13
1752 13
        $referencesClause = '';
1753
        if ($constraint instanceof Index) {
1754
            if ($constraint->isPrimary()) {
1755 16
                $query .= ' PRIMARY KEY';
1756
            } elseif ($constraint->isUnique()) {
1757
                $query .= ' UNIQUE';
1758 13
            } else {
1759 13
                throw new \InvalidArgumentException(
1760
                    'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().'
1761 13
                );
1762 13
            }
1763
        } elseif ($constraint instanceof ForeignKeyConstraint) {
1764 16
            $query .= ' FOREIGN KEY';
1765
1766 16
            $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) .
1767
                ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')';
1768
        }
1769
        $query .= ' '.$columnList.$referencesClause;
1770
1771
        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 155
     *
1780
     * @return string
1781 155
     *
1782 1
     * @throws \InvalidArgumentException
1783
     */
1784 155
    public function getCreateIndexSQL(Index $index, $table)
1785 155
    {
1786
        if ($table instanceof Table) {
1787 155
            $table = $table->getQuotedName($this);
1788
        }
1789
        $name = $index->getQuotedName($this);
1790
        $columns = $index->getQuotedColumns($this);
1791 155
1792 21
        if (count($columns) == 0) {
1793
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
1794
        }
1795 136
1796 136
        if ($index->isPrimary()) {
1797
            return $this->getCreatePrimaryKeySQL($index, $table);
1798 136
        }
1799
1800
        $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table;
1801
        $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index);
1802
1803
        return $query;
1804
    }
1805
1806
    /**
1807
     * Adds condition for partial index.
1808 183
     *
1809
     * @param \Doctrine\DBAL\Schema\Index $index
1810 183
     *
1811 5
     * @return string
1812
     */
1813
    protected function getPartialIndexSQL(Index $index)
1814 178
    {
1815
        if ($this->supportsPartialIndexes() && $index->hasOption('where')) {
1816
            return  ' WHERE ' . $index->getOption('where');
1817
        }
1818
1819
        return '';
1820
    }
1821
1822
    /**
1823
     * Adds additional flags for index generation.
1824 67
     *
1825
     * @param \Doctrine\DBAL\Schema\Index $index
1826 67
     *
1827
     * @return string
1828
     */
1829
    protected function getCreateIndexSQLFlags(Index $index)
1830
    {
1831
        return $index->isUnique() ? 'UNIQUE ' : '';
1832
    }
1833
1834
    /**
1835
     * Returns the SQL to create an unnamed primary key constraint.
1836
     *
1837 17
     * @param \Doctrine\DBAL\Schema\Index        $index
1838
     * @param \Doctrine\DBAL\Schema\Table|string $table
1839 17
     *
1840
     * @return string
1841
     */
1842
    public function getCreatePrimaryKeySQL(Index $index, $table)
1843
    {
1844
        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 10
     * @param string $schemaName
1851
     *
1852 10
     * @return string
1853
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1854
     */
1855
    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
        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 392
     *
1869
     * @param string $str The identifier name to be quoted.
1870 392
     *
1871 18
     * @return string The quoted identifier string.
1872
     */
1873 18
    public function quoteIdentifier($str)
1874
    {
1875
        if (strpos($str, ".") !== false) {
1876 392
            $parts = array_map([$this, "quoteSingleIdentifier"], explode(".", $str));
1877
1878
            return implode(".", $parts);
1879
        }
1880
1881
        return $this->quoteSingleIdentifier($str);
1882
    }
1883
1884
    /**
1885
     * Quotes a single identifier (no dot chain separation).
1886 378
     *
1887
     * @param string $str The identifier name to be quoted.
1888 378
     *
1889
     * @return string The quoted identifier string.
1890 378
     */
1891
    public function quoteSingleIdentifier($str)
1892
    {
1893
        $c = $this->getIdentifierQuoteCharacter();
1894
1895
        return $c . str_replace($c, $c.$c, $str) . $c;
1896
    }
1897
1898
    /**
1899
     * Returns the SQL to create a new foreign key.
1900
     *
1901 78
     * @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 78
     *
1904 1
     * @return string
1905
     */
1906
    public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
1907 78
    {
1908
        if ($table instanceof Table) {
1909 78
            $table = $table->getQuotedName($this);
1910
        }
1911
1912
        $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey);
1913
1914
        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 96
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
1936
     * @param array                           $columnSql
1937 96
     *
1938 77
     * @return bool
1939
     */
1940
    protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql)
1941 19
    {
1942 1
        if (null === $this->_eventManager) {
1943
            return false;
1944
        }
1945 18
1946 18
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) {
1947
            return false;
1948 18
        }
1949
1950 18
        $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this);
1951
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableAddColumn, $eventArgs);
1952
1953
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
1954
1955
        return $eventArgs->isDefaultPrevented();
1956
    }
1957
1958
    /**
1959
     * @param \Doctrine\DBAL\Schema\Column    $column
1960 76
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
1961
     * @param array                           $columnSql
1962 76
     *
1963 57
     * @return bool
1964
     */
1965
    protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql)
1966 19
    {
1967 1
        if (null === $this->_eventManager) {
1968
            return false;
1969
        }
1970 18
1971 18
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) {
1972
            return false;
1973 18
        }
1974
1975 18
        $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this);
1976
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRemoveColumn, $eventArgs);
1977
1978
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
1979
1980
        return $eventArgs->isDefaultPrevented();
1981
    }
1982
1983
    /**
1984
     * @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff
1985 185
     * @param \Doctrine\DBAL\Schema\TableDiff  $diff
1986
     * @param array                            $columnSql
1987 185
     *
1988 155
     * @return bool
1989
     */
1990
    protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql)
1991 30
    {
1992 12
        if (null === $this->_eventManager) {
1993
            return false;
1994
        }
1995 18
1996 18
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) {
1997
            return false;
1998 18
        }
1999
2000 18
        $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this);
2001
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs);
2002
2003
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
2004
2005
        return $eventArgs->isDefaultPrevented();
2006
    }
2007
2008
    /**
2009
     * @param string                          $oldColumnName
2010
     * @param \Doctrine\DBAL\Schema\Column    $column
2011 76
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2012
     * @param array                           $columnSql
2013 76
     *
2014 58
     * @return bool
2015
     */
2016
    protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql)
2017 18
    {
2018
        if (null === $this->_eventManager) {
2019
            return false;
2020
        }
2021 18
2022 18
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) {
2023
            return false;
2024 18
        }
2025
2026 18
        $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this);
2027
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRenameColumn, $eventArgs);
2028
2029
        $columnSql = array_merge($columnSql, $eventArgs->getSql());
2030
2031
        return $eventArgs->isDefaultPrevented();
2032
    }
2033
2034
    /**
2035 358
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2036
     * @param array                           $sql
2037 358
     *
2038 321
     * @return bool
2039
     */
2040
    protected function onSchemaAlterTable(TableDiff $diff, &$sql)
2041 37
    {
2042 19
        if (null === $this->_eventManager) {
2043
            return false;
2044
        }
2045 18
2046 18
        if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) {
2047
            return false;
2048 18
        }
2049
2050 18
        $eventArgs = new SchemaAlterTableEventArgs($diff, $this);
2051
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTable, $eventArgs);
2052
2053
        $sql = array_merge($sql, $eventArgs->getSql());
2054
2055
        return $eventArgs->isDefaultPrevented();
2056
    }
2057
2058 326
    /**
2059
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2060 326
     *
2061
     * @return array
2062 326
     */
2063 326
    protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
2064 326
    {
2065 25
        $tableName = $diff->getName($this)->getQuotedName($this);
2066
2067 326
        $sql = [];
2068 20
        if ($this->supportsForeignKeyConstraints()) {
2069
            foreach ($diff->removedForeignKeys as $foreignKey) {
2070
                $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
2071
            }
2072 326
            foreach ($diff->changedForeignKeys as $foreignKey) {
2073 11
                $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
2074
            }
2075 326
        }
2076 16
2077
        foreach ($diff->removedIndexes as $index) {
2078
            $sql[] = $this->getDropIndexSQL($index, $tableName);
2079 326
        }
2080
        foreach ($diff->changedIndexes as $index) {
2081
            if ($index->isPrimary()) {
2082
                $sql[] = $this->getDropPrimaryKeySQL($tableName);
2083
                continue;
2084
            }
2085
2086
            $sql[] = $this->getDropIndexSQL($index, $tableName);
2087 326
        }
2088
2089 326
        return $sql;
2090 34
    }
2091 326
2092
    /**
2093 326
     * @param \Doctrine\DBAL\Schema\TableDiff $diff
2094
     *
2095 326
     * @return array
2096 326
     */
2097 20
    protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
2098
    {
2099
        $tableName = (false !== $diff->newName)
2100 326
            ? $diff->getNewName()->getQuotedName($this)
2101 20
            : $diff->getName($this)->getQuotedName($this);
2102
2103
        $sql = [];
2104
2105 326
        if ($this->supportsForeignKeyConstraints()) {
2106 3
            foreach ($diff->addedForeignKeys as $foreignKey) {
2107
                $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
2108
            }
2109 326
2110 16
            foreach ($diff->changedForeignKeys as $foreignKey) {
2111
                $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
2112
            }
2113 326
        }
2114 85
2115 85
        foreach ($diff->addedIndexes as $index) {
2116 85
            $sql[] = $this->getCreateIndexSQL($index, $tableName);
2117 85
        }
2118
2119
        foreach ($diff->changedIndexes as $index) {
2120
            $sql[] = $this->getCreateIndexSQL($index, $tableName);
2121 326
        }
2122
2123
        foreach ($diff->renamedIndexes as $oldIndexName => $index) {
2124
            $oldIndexName = new Identifier($oldIndexName);
2125
            $sql          = array_merge(
2126
                $sql,
2127
                $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName)
2128
            );
2129
        }
2130
2131
        return $sql;
2132
    }
2133 10
2134
    /**
2135
     * Returns the SQL for renaming an index on a table.
2136 10
     *
2137 10
     * @param string                      $oldIndexName The name of the index to rename from.
2138
     * @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
     * @return array The sequence of SQL statements for renaming the given index.
2142
     */
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 381
     *          to not be set to null.
2183
     *      charset
2184 381
     *          Text value with the default CHARACTER SET for this field.
2185
     *      collation
2186 381
     *          Text value with the default COLLATION for this field.
2187 381
     *      unique
2188
     *          unique constraint
2189
     *
2190 381
     * @return string
2191
     */
2192
    public function getColumnDeclarationListSQL(array $fields)
2193
    {
2194
        $queryFields = [];
2195
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 432
     *          Text value with the default COLLATION for this field.
2227
     *      unique
2228 432
     *          unique constraint
2229 15
     *      check
2230
     *          column check constraint
2231 418
     *      columnDefinition
2232
     *          a string that defines the complete column
2233 418
     *
2234 418
     * @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 418
    {
2238
        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 418
2246
            $collation = (isset($field['collation']) && $field['collation']) ?
2247 418
                ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : '';
2248 418
2249
            $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
2250 418
2251 53
            $unique = (isset($field['unique']) && $field['unique']) ?
2252
                ' ' . $this->getUniqueFieldDeclarationSQL() : '';
2253
2254
            $check = (isset($field['check']) && $field['check']) ?
2255 432
                ' ' . $field['check'] : '';
2256
2257
            $typeDecl = $field['type']->getSQLDeclaration($field, $this);
2258
            $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
2259
2260
            if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') {
2261
                $columnDef .= ' ' . $this->getInlineColumnCommentSQL($field['comment']);
2262
            }
2263
        }
2264
2265 133
        return $name . ' ' . $columnDef;
2266
    }
2267 133
2268 133
    /**
2269 133
     * Returns the SQL snippet that declares a floating point column of arbitrary precision.
2270 133
     *
2271
     * @param array $columnDef
2272 133
     *
2273
     * @return string
2274
     */
2275
    public function getDecimalTypeDeclarationSQL(array $columnDef)
2276
    {
2277
        $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 472
    }
2284
2285 472
    /**
2286 405
     * Obtains DBMS specific SQL code portion needed to set a default value
2287
     * declaration to be used in statements like CREATE TABLE.
2288
     *
2289 88
     * @param array $field The field definition array.
2290
     *
2291 88
     * @return string DBMS specific SQL code portion needed to set a default value.
2292
     */
2293
    public function getDefaultValueDeclarationSQL($field)
2294
    {
2295 88
        if ( ! isset($field['default'])) {
2296
            return empty($field['notnull']) ? ' DEFAULT NULL' : '';
2297 88
        }
2298 23
2299
        $default = $field['default'];
2300
2301 67
        if ( ! isset($field['type'])) {
2302 15
            return " DEFAULT '" . $default . "'";
2303
        }
2304
2305 52
        $type = $field['type'];
2306
2307
        if ($type instanceof Types\PhpIntegerMappingType) {
2308
            return ' DEFAULT ' . $default;
2309 52
        }
2310 15
2311
        if ($type instanceof Types\PhpDateTimeMappingType && $default === $this->getCurrentTimestampSQL()) {
2312
            return ' DEFAULT ' . $this->getCurrentTimestampSQL();
2313 37
        }
2314 15
2315
        if ($type instanceof Types\TimeType && $default === $this->getCurrentTimeSQL()) {
2316
            return ' DEFAULT ' . $this->getCurrentTimeSQL();
2317 37
        }
2318
2319
        if ($type instanceof Types\DateType && $default === $this->getCurrentDateSQL()) {
2320
            return ' DEFAULT ' . $this->getCurrentDateSQL();
2321
        }
2322
2323
        if ($type instanceof Types\BooleanType) {
2324
            return " DEFAULT '" . $this->convertBooleans($default) . "'";
2325
        }
2326
2327
        return " DEFAULT '" . $default . "'";
2328 117
    }
2329
2330 117
    /**
2331 117
     * Obtains DBMS specific SQL code portion needed to set a CHECK constraint
2332 117
     * declaration to be used in statements like CREATE TABLE.
2333
     *
2334
     * @param array $definition The check definition.
2335 117
     *
2336 5
     * @return string DBMS specific SQL code portion needed to set a CHECK constraint.
2337
     */
2338
    public function getCheckDeclarationSQL(array $definition)
2339 117
    {
2340 117
        $constraints = [];
2341
        foreach ($definition as $field => $def) {
2342
            if (is_string($def)) {
2343
                $constraints[] = 'CHECK (' . $def . ')';
2344
            } else {
2345 117
                if (isset($def['min'])) {
2346
                    $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')';
2347
                }
2348
2349
                if (isset($def['max'])) {
2350
                    $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')';
2351
                }
2352
            }
2353
        }
2354
2355
        return implode(', ', $constraints);
2356
    }
2357
2358
    /**
2359 28
     * Obtains DBMS specific SQL code portion needed to set a unique
2360
     * constraint declaration to be used in statements like CREATE TABLE.
2361 28
     *
2362 28
     * @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
     *
2367
     * @throws \InvalidArgumentException
2368 28
     */
2369 28
    public function getUniqueConstraintDeclarationSQL($name, Index $index)
2370 28
    {
2371
        $columns = $index->getQuotedColumns($this);
2372
        $name = new Identifier($name);
2373
2374
        if (count($columns) === 0) {
2375
            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 46
     * Obtains DBMS specific SQL code portion needed to set an index
2385
     * declaration to be used in statements like CREATE TABLE.
2386 46
     *
2387 46
     * @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
     *
2392
     * @throws \InvalidArgumentException
2393 46
     */
2394 46
    public function getIndexDeclarationSQL($name, Index $index)
2395 46
    {
2396
        $columns = $index->getQuotedColumns($this);
2397
        $name = new Identifier($name);
2398
2399
        if (count($columns) === 0) {
2400
            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 19
2408
    /**
2409 19
     * 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
     *
2413
     * @param array $columnDef
2414
     *
2415
     * @return string
2416
     */
2417
    public function getCustomTypeDeclarationSQL(array $columnDef)
2418
    {
2419
        return $columnDef['columnDefinition'];
2420 253
    }
2421
2422 253
    /**
2423
     * Obtains DBMS specific SQL code portion needed to set an index
2424 253
     * declaration to be used in statements like CREATE TABLE.
2425 253
     *
2426
     * @param array $fields
2427
     *
2428 253
     * @return string
2429
     */
2430
    public function getIndexFieldDeclarationListSQL(array $fields)
2431
    {
2432 253
        $ret = [];
2433
2434
        foreach ($fields as $field => $definition) {
2435
            if (is_array($definition)) {
2436
                $ret[] = $field;
2437
            } 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 113
2476
    /**
2477 113
     * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2478 101
     * of a field declaration to be used in statements like CREATE TABLE.
2479
     *
2480 101
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey
2481
     *
2482
     * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2483
     *                of a field declaration.
2484
     */
2485
    public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey)
2486
    {
2487
        $sql  = $this->getForeignKeyBaseDeclarationSQL($foreignKey);
2488
        $sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey);
2489
2490
        return $sql;
2491 97
    }
2492
2493 97
    /**
2494 97
     * Returns the FOREIGN KEY query section dealing with non-standard options
2495 4
     * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
2496
     *
2497 97
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key definition.
2498 9
     *
2499
     * @return string
2500
     */
2501 97
    public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
2502
    {
2503
        $query = '';
2504
        if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) {
2505
            $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate'));
2506
        }
2507
        if ($foreignKey->hasOption('onDelete')) {
2508
            $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
2509
        }
2510
2511
        return $query;
2512
    }
2513 121
2514
    /**
2515 121
     * Returns the given referential action in uppercase if valid, otherwise throws an exception.
2516
     *
2517 121
     * @param string $action The foreign key referential action.
2518 82
     *
2519 61
     * @return string
2520 48
     *
2521 34
     * @throws \InvalidArgumentException if unknown referential action given
2522 104
     */
2523
    public function getForeignKeyReferentialActionSQL($action)
2524 17
    {
2525
        $upper = strtoupper($action);
2526
        switch ($upper) {
2527
            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
            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 73
    /**
2539
     * Obtains DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2540 73
     * of a field declaration to be used in statements like CREATE TABLE.
2541 73
     *
2542 59
     * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey
2543
     *
2544 73
     * @return string
2545
     *
2546 73
     * @throws \InvalidArgumentException
2547
     */
2548
    public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey)
2549 73
    {
2550
        $sql = '';
2551
        if (strlen($foreignKey->getName())) {
2552 73
            $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' ';
2553
        }
2554
        $sql .= 'FOREIGN KEY (';
2555
2556 73
        if (count($foreignKey->getLocalColumns()) === 0) {
2557 73
            throw new \InvalidArgumentException("Incomplete definition. 'local' required.");
2558 73
        }
2559 73
        if (count($foreignKey->getForeignColumns()) === 0) {
2560
            throw new \InvalidArgumentException("Incomplete definition. 'foreign' required.");
2561 73
        }
2562
        if (strlen($foreignKey->getForeignTableName()) === 0) {
2563
            throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required.");
2564
        }
2565
2566
        $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 1
2600
    /**
2601 1
     * 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
     * @param string $collation The name of the collation.
2605
     *
2606
     * @return string DBMS specific SQL code portion needed to set the COLLATION
2607
     *                of a field declaration.
2608
     */
2609
    public function getColumnCollationDeclarationSQL($collation)
2610 5
    {
2611
        return $this->supportsColumnCollation() ? 'COLLATE ' . $collation : '';
2612 5
    }
2613
2614
    /**
2615
     * Whether the platform prefers sequences for ID generation.
2616
     * Subclasses should override this method to return TRUE if they prefer sequences.
2617
     *
2618
     * @return bool
2619
     */
2620
    public function prefersSequences()
2621 6
    {
2622
        return false;
2623 6
    }
2624
2625
    /**
2626
     * 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
     *
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 23
     *
2641
     * Note: if the input is not a boolean the original input might be returned.
2642 23
     *
2643
     * There are two contexts when converting booleans: Literals and Prepared Statements.
2644
     * This method should handle the literal case
2645
     *
2646
     * @param mixed $item A boolean or an array of them.
2647
     *
2648 23
     * @return mixed A boolean database value or an array of them.
2649 22
     */
2650
    public function convertBooleans($item)
2651
    {
2652 23
        if (is_array($item)) {
2653
            foreach ($item as $k => $value) {
2654
                if (is_bool($value)) {
2655
                    $item[$k] = (int) $value;
2656
                }
2657
            }
2658
        } elseif (is_bool($item)) {
2659
            $item = (int) $item;
2660
        }
2661
2662
        return $item;
2663
    }
2664 49
2665
    /**
2666 49
     * 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
     *
2670
     * @param mixed $item
2671
     *
2672
     * @return bool|null
2673
     */
2674
    public function convertFromBoolean($item)
2675
    {
2676
        return null === $item ? null: (bool) $item ;
2677
    }
2678
2679 8
    /**
2680
     * This method should handle the prepared statements case. When there is no
2681 8
     * 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
     *
2685
     * @param mixed $item A boolean or an array of them.
2686
     *
2687
     * @return mixed A boolean database value or an array of them.
2688
     */
2689 11
    public function convertBooleansToDatabaseValue($item)
2690
    {
2691 11
        return $this->convertBooleans($item);
2692
    }
2693
2694
    /**
2695
     * Returns the SQL specific for the platform to get the current date.
2696
     *
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 17
    public function getCurrentTimeSQL()
2710
    {
2711 17
        return 'CURRENT_TIME';
2712
    }
2713
2714
    /**
2715
     * Returns the SQL specific for the platform to get the current timestamp
2716
     *
2717
     * @return string
2718
     */
2719
    public function getCurrentTimestampSQL()
2720
    {
2721
        return 'CURRENT_TIMESTAMP';
2722
    }
2723 11
2724
    /**
2725
     * Returns the SQL for a given transaction isolation level Connection constant.
2726 11
     *
2727 11
     * @param int $level
2728 11
     *
2729 11
     * @return string
2730 11
     *
2731 11
     * @throws \InvalidArgumentException
2732 11
     */
2733 11
    protected function _getTransactionIsolationLevelSQL($level)
2734
    {
2735
        switch ($level) {
2736
            case TransactionIsolationLevel::READ_UNCOMMITTED:
2737
                return 'READ UNCOMMITTED';
2738
            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 1
            default:
2745
                throw new \InvalidArgumentException('Invalid isolation level:' . $level);
2746 1
        }
2747
    }
2748
2749
    /**
2750
     * @return string
2751
     *
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 1
2927
    /**
2928 1
     * Returns the SQL to create a new database.
2929
     *
2930
     * @param string $database The name of the database that should be created.
2931
     *
2932
     * @return string
2933
     *
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 15
        throw DBALException::notSupported(__METHOD__);
2968
    }
2969 15
2970
    /**
2971
     * Obtains DBMS specific SQL to be used to create datetime with timezone offset fields.
2972
     *
2973
     * @param array $fieldDeclaration
2974
     *
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 105
    public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
3009
    {
3010 105
        throw DBALException::notSupported(__METHOD__);
3011
    }
3012
3013
    /**
3014
     * @param array $fieldDeclaration
3015
     *
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 6
        return TransactionIsolationLevel::READ_COMMITTED;
3033
    }
3034 6
3035
    /* supports*() methods */
3036
3037
    /**
3038
     * Whether the platform supports sequences.
3039
     *
3040
     * @return bool
3041
     */
3042
    public function supportsSequences()
3043
    {
3044
        return false;
3045 1
    }
3046
3047 1
    /**
3048
     * Whether the platform supports identity columns.
3049
     *
3050
     * Identity columns are columns that receive an auto-generated value from the
3051
     * database on insert of a row.
3052
     *
3053
     * @return bool
3054
     */
3055
    public function supportsIdentityColumns()
3056
    {
3057
        return false;
3058
    }
3059 13
3060
    /**
3061 13
     * Whether the platform emulates identity columns through sequences.
3062
     *
3063
     * Some platforms that do not support identity columns natively
3064
     * but support sequences can emulate identity columns by using
3065
     * sequences.
3066
     *
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 12
     *
3077
     * @param string $tableName  The name of the table to return the sequence name for.
3078 12
     * @param string $columnName The name of the identity column in the table to return the sequence name for.
3079
     *
3080
     * @return string
3081
     *
3082
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3083
     *
3084
     * @see    usesSequenceEmulatedIdentityColumns
3085
     */
3086 4
    public function getIdentitySequenceName($tableName, $columnName)
3087
    {
3088 4
        throw DBALException::notSupported(__METHOD__);
3089
    }
3090
3091
    /**
3092
     * Whether the platform supports indexes.
3093
     *
3094
     * @return bool
3095
     */
3096 143
    public function supportsIndexes()
3097
    {
3098 143
        return true;
3099
    }
3100
3101
    /**
3102
     * Whether the platform supports partial indexes.
3103
     *
3104
     * @return bool
3105
     */
3106 5
    public function supportsPartialIndexes()
3107
    {
3108 5
        return false;
3109
    }
3110
3111
    /**
3112
     * Whether the platform supports altering tables.
3113
     *
3114
     * @return bool
3115
     */
3116 4
    public function supportsAlterTable()
3117
    {
3118 4
        return true;
3119
    }
3120
3121
    /**
3122
     * Whether the platform supports transactions.
3123
     *
3124
     * @return bool
3125
     */
3126 22
    public function supportsTransactions()
3127
    {
3128 22
        return true;
3129
    }
3130
3131
    /**
3132
     * Whether the platform supports savepoints.
3133
     *
3134
     * @return bool
3135
     */
3136 5
    public function supportsSavepoints()
3137
    {
3138 5
        return true;
3139
    }
3140
3141
    /**
3142
     * Whether the platform supports releasing savepoints.
3143
     *
3144
     * @return bool
3145
     */
3146 4
    public function supportsReleaseSavepoints()
3147
    {
3148 4
        return $this->supportsSavepoints();
3149
    }
3150
3151
    /**
3152
     * Whether the platform supports primary key constraints.
3153
     *
3154
     * @return bool
3155
     */
3156 423
    public function supportsPrimaryConstraints()
3157
    {
3158 423
        return true;
3159
    }
3160
3161
    /**
3162
     * Whether the platform supports foreign key constraints.
3163
     *
3164
     * @return bool
3165
     */
3166 101
    public function supportsForeignKeyConstraints()
3167
    {
3168 101
        return true;
3169
    }
3170
3171
    /**
3172
     * Whether this platform supports onUpdate in foreign key constraints.
3173
     *
3174
     * @return bool
3175
     */
3176 10
    public function supportsForeignKeyOnUpdate()
3177
    {
3178 10
        return ($this->supportsForeignKeyConstraints() && true);
3179
    }
3180
3181
    /**
3182
     * Whether the platform supports database schemas.
3183
     *
3184
     * @return bool
3185
     */
3186
    public function supportsSchemas()
3187
    {
3188
        return false;
3189
    }
3190 4
3191
    /**
3192 4
     * Whether this platform can emulate schemas.
3193
     *
3194
     * Platforms that either support or emulate schemas don't automatically
3195
     * filter a schema for the namespaced elements in {@link
3196
     * AbstractManager#createSchema}.
3197
     *
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 4
        throw DBALException::notSupported(__METHOD__);
3215
    }
3216 4
3217
    /**
3218
     * Whether this platform supports create database.
3219
     *
3220
     * Some databases don't allow to create and drop databases at all or only with certain tools.
3221
     *
3222
     * @return bool
3223
     */
3224 4
    public function supportsCreateDropDatabase()
3225
    {
3226 4
        return true;
3227
    }
3228
3229
    /**
3230
     * Whether the platform supports getting the affected rows of a recent update/delete type query.
3231
     *
3232
     * @return bool
3233
     */
3234 196
    public function supportsGettingAffectedRows()
3235
    {
3236 196
        return true;
3237
    }
3238
3239
    /**
3240
     * Whether this platform support to add inline column comments as postfix.
3241
     *
3242
     * @return bool
3243
     */
3244 247
    public function supportsInlineColumnComments()
3245
    {
3246 247
        return false;
3247
    }
3248
3249
    /**
3250
     * Whether this platform support the proprietary syntax "COMMENT ON asset".
3251
     *
3252
     * @return bool
3253
     */
3254 300
    public function supportsCommentOnStatement()
3255
    {
3256 300
        return false;
3257
    }
3258
3259
    /**
3260
     * Does this platform have native guid type.
3261
     *
3262
     * @return bool
3263
     */
3264 626
    public function hasNativeGuidType()
3265
    {
3266 626
        return false;
3267
    }
3268
3269
    /**
3270
     * Does this platform have native JSON type.
3271
     *
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 1
    public function getIdentityColumnNullInsertSQL()
3284
    {
3285 1
        return "";
3286
    }
3287
3288
    /**
3289
     * Whether this platform supports views.
3290
     *
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 18
    {
3305
        return false;
3306 18
    }
3307
3308
    /**
3309
     * Gets the format string, as accepted by the date() function, that describes
3310
     * the format of a stored datetime value of this platform.
3311
     *
3312
     * @return string The format string.
3313
     */
3314
    public function getDateTimeFormatString()
3315 8
    {
3316
        return 'Y-m-d H:i:s';
3317 8
    }
3318
3319
    /**
3320
     * 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
     *
3323
     * @return string The format string.
3324
     */
3325
    public function getDateTimeTzFormatString()
3326 7
    {
3327
        return 'Y-m-d H:i:s';
3328 7
    }
3329
3330
    /**
3331
     * Gets the format string, as accepted by the date() function, that describes
3332
     * the format of a stored date value of this platform.
3333
     *
3334
     * @return string The format string.
3335
     */
3336
    public function getDateFormatString()
3337 6
    {
3338
        return 'Y-m-d';
3339 6
    }
3340
3341
    /**
3342
     * Gets the format string, as accepted by the date() function, that describes
3343
     * the format of a stored time value of this platform.
3344
     *
3345
     * @return string The format string.
3346
     */
3347
    public function getTimeFormatString()
3348
    {
3349
        return 'H:i:s';
3350
    }
3351
3352
    /**
3353 118
     * Adds an driver-specific LIMIT clause to the query.
3354
     *
3355 118
     * @param string   $query
3356 112
     * @param int|null $limit
3357
     * @param int|null $offset
3358
     *
3359 118
     * @return string
3360 47
     *
3361
     * @throws DBALException
3362 47
     */
3363
    final public function modifyLimitQuery($query, $limit, $offset = null)
3364
    {
3365 47
        if ($limit !== null) {
3366
            $limit = (int) $limit;
3367
        }
3368
3369
        if ($offset !== null) {
3370 118
            $offset = (int) $offset;
3371
3372
            if ($offset < 0) {
3373
                throw new DBALException("LIMIT argument offset=$offset is not valid");
3374
            }
3375
            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 19
3383
    /**
3384 19
     * Adds an driver-specific LIMIT clause to the query.
3385 19
     *
3386
     * @param string   $query
3387
     * @param int|null $limit
3388 19
     * @param int|null $offset
3389 13
     *
3390
     * @return string
3391
     */
3392 19
    protected function doModifyLimitQuery($query, $limit, $offset)
3393
    {
3394
        if ($limit !== null) {
3395
            $query .= ' LIMIT ' . $limit;
3396
        }
3397
3398
        if ($offset !== null) {
3399
            $query .= ' OFFSET ' . $offset;
3400 18
        }
3401
3402 18
        return $query;
3403
    }
3404
3405
    /**
3406
     * Whether the database platform support offsets in modify limit clauses.
3407
     *
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 14
    public function fixSchemaElementName($schemaElementName)
3436
    {
3437 14
        return $schemaElementName;
3438
    }
3439
3440
    /**
3441
     * Maximum length of any given database identifier, like tables or column names.
3442
     *
3443
     * @return int
3444
     */
3445
    public function getMaxIdentifierLength()
3446
    {
3447
        return 63;
3448 1
    }
3449
3450 1
    /**
3451
     * Returns the insert SQL for an empty insert statement.
3452
     *
3453
     * @param string $tableName
3454
     * @param string $identifierColumnName
3455
     *
3456
     * @return string
3457
     */
3458
    public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
3459
    {
3460
        return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)';
3461
    }
3462
3463
    /**
3464 3
     * Generates a Truncate Table SQL statement for a given table.
3465
     *
3466 3
     * Cascade is not supported on many platforms but would optionally cascade the truncate by
3467
     * following the foreign keys.
3468 3
     *
3469
     * @param string $tableName
3470
     * @param bool   $cascade
3471
     *
3472
     * @return string
3473
     */
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 7
        $tableIdentifier = new Identifier($tableName);
3477
3478 7
        return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this);
3479
    }
3480
3481
    /**
3482
     * This is for test reasons, many vendors have special requirements for dummy statements.
3483
     *
3484
     * @return string
3485
     */
3486
    public function getDummySelectSQL()
3487
    {
3488 1
        return 'SELECT 1';
3489
    }
3490 1
3491
    /**
3492
     * Returns the SQL to create a new savepoint.
3493
     *
3494
     * @param string $savepoint
3495
     *
3496
     * @return string
3497
     */
3498
    public function createSavePoint($savepoint)
3499
    {
3500 1
        return 'SAVEPOINT ' . $savepoint;
3501
    }
3502 1
3503
    /**
3504
     * Returns the SQL to release a savepoint.
3505
     *
3506
     * @param string $savepoint
3507
     *
3508
     * @return string
3509
     */
3510
    public function releaseSavePoint($savepoint)
3511
    {
3512 1
        return 'RELEASE SAVEPOINT ' . $savepoint;
3513
    }
3514 1
3515
    /**
3516
     * Returns the SQL to rollback a savepoint.
3517
     *
3518
     * @param string $savepoint
3519
     *
3520
     * @return string
3521
     */
3522
    public function rollbackSavePoint($savepoint)
3523
    {
3524 1078
        return 'ROLLBACK TO SAVEPOINT ' . $savepoint;
3525
    }
3526
3527 1078
    /**
3528 1011
     * Returns the keyword list instance of this platform.
3529
     *
3530
     * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList
3531 954
     *
3532 954
     * @throws \Doctrine\DBAL\DBALException If no keyword list is specified.
3533 954
     */
3534
    final public function getReservedKeywordsList()
3535
    {
3536
        // Check for an existing instantiation of the keywords class.
3537
        if ($this->_keywords) {
3538 954
            return $this->_keywords;
3539
        }
3540 954
3541
        $class = $this->getReservedKeywordsClass();
3542
        $keywords = new $class;
3543
        if ( ! $keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList) {
3544
            throw DBALException::notSupported(__METHOD__);
3545
        }
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 334
    /**
3566
     * Quotes a literal string.
3567 334
     * This method is NOT meant to fix SQL injections!
3568
     * It is only meant to escape this platform's string literal
3569 334
     * quote character inside the given literal string.
3570
     *
3571
     * @param string $str The literal string to be quoted.
3572
     *
3573
     * @return string The quoted literal string.
3574
     */
3575
    public function quoteStringLiteral($str)
3576
    {
3577 352
        $c = $this->getStringLiteralQuoteCharacter();
3578
3579 352
        return $c . str_replace($c, $c . $c, $str) . $c;
3580
    }
3581
3582
    /**
3583
     * Gets the character used for string literal quoting.
3584
     *
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
     *
3596
     * @param string $inputString a literal, unquoted string
3597
     * @param string $escapeChar  should be reused by the caller in the LIKE
3598
     *                            expression.
3599
     */
3600
    final public function escapeStringForLike(string $inputString, string $escapeChar) : string
3601
    {
3602
        return preg_replace(
3603
            '~([' . preg_quote($this->getLikeWildcardCharacters() . $escapeChar, '~') . '])~u',
3604
            addcslashes($escapeChar, '\\') . '$1',
3605
            $inputString
3606
        );
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