Failed Conditions
Pull Request — master (#2929)
by Alexander
61:50
created

AbstractPlatform::supportsIdentityColumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

338
    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...
339
    {
340
        throw DBALException::notSupported('VARCHARs not supported by Platform.');
341
    }
342
343
    /**
344
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
345
     *
346
     * @param integer $length The length of the column.
347
     * @param boolean $fixed  Whether the column length is fixed.
348
     *
349
     * @return string
350
     *
351
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
352
     */
353
    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

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

793
            $expression .= /** @scrutinizer ignore-type */ $char . ' ';
Loading history...
794
        }
795
796
        if ($pos || false !== $char) {
797
            $expression .= 'FROM ';
798
        }
799
800
        return 'TRIM(' . $expression . $str . ')';
801
    }
802
803
    /**
804
     * Returns the SQL snippet to trim trailing space characters from the expression.
805
     *
806
     * @param string $str Literal string or column name.
807
     *
808
     * @return string
809
     */
810 4
    public function getRtrimExpression($str)
811
    {
812 4
        return 'RTRIM(' . $str . ')';
813
    }
814
815
    /**
816
     * Returns the SQL snippet to trim leading space characters from the expression.
817
     *
818
     * @param string $str Literal string or column name.
819
     *
820
     * @return string
821
     */
822 4
    public function getLtrimExpression($str)
823
    {
824 4
        return 'LTRIM(' . $str . ')';
825
    }
826
827
    /**
828
     * Returns the SQL snippet to change all characters from the expression to uppercase,
829
     * according to the current character set mapping.
830
     *
831
     * @param string $str Literal string or column name.
832
     *
833
     * @return string
834
     */
835
    public function getUpperExpression($str)
836
    {
837
        return 'UPPER(' . $str . ')';
838
    }
839
840
    /**
841
     * Returns the SQL snippet to change all characters from the expression to lowercase,
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 getLowerExpression($str)
849
    {
850
        return 'LOWER(' . $str . ')';
851
    }
852
853
    /**
854
     * Returns the SQL snippet to get the position of the first occurrence of substring $substr in string $str.
855
     *
856
     * @param string          $str      Literal string.
857
     * @param string          $substr   Literal string to find.
858
     * @param integer|boolean $startPos Position to start at, beginning of string by default.
859
     *
860
     * @return string
861
     *
862
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
863
     */
864
    public function getLocateExpression($str, $substr, $startPos = false)
0 ignored issues
show
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

864
    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...
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

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

1035
    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

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

1293
    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

1293
    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

1293
    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...
1294
    {
1295
        throw DBALException::notSupported(__METHOD__);
1296
    }
1297
1298
    /**
1299
     * Returns the SQL bit AND comparison expression.
1300
     *
1301
     * @param string $value1
1302
     * @param string $value2
1303
     *
1304
     * @return string
1305
     */
1306 17
    public function getBitAndComparisonExpression($value1, $value2)
1307
    {
1308 17
        return '(' . $value1 . ' & ' . $value2 . ')';
1309
    }
1310
1311
    /**
1312
     * Returns the SQL bit OR comparison expression.
1313
     *
1314
     * @param string $value1
1315
     * @param string $value2
1316
     *
1317
     * @return string
1318
     */
1319 17
    public function getBitOrComparisonExpression($value1, $value2)
1320
    {
1321 17
        return '(' . $value1 . ' | ' . $value2 . ')';
1322
    }
1323
1324
    /**
1325
     * Returns the FOR UPDATE expression.
1326
     *
1327
     * @return string
1328
     */
1329
    public function getForUpdateSQL()
1330
    {
1331
        return 'FOR UPDATE';
1332
    }
1333
1334
    /**
1335
     * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification.
1336
     *
1337
     * @param string       $fromClause The FROM clause to append the hint for the given lock mode to.
1338
     * @param integer|null $lockMode   One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will
1339
     *                                 be appended to the FROM clause.
1340
     *
1341
     * @return string
1342
     */
1343
    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

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

1700
    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...
1701
    {
1702
        throw DBALException::notSupported(__METHOD__);
1703
    }
1704
1705
    /**
1706
     * Returns the SQL to change a sequence on this platform.
1707
     *
1708
     * @param \Doctrine\DBAL\Schema\Sequence $sequence
1709
     *
1710
     * @return string
1711
     *
1712
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1713
     */
1714
    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

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

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

1831
        return 'ALTER TABLE ' . /** @scrutinizer ignore-type */ $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
Loading history...
1832
    }
1833
1834
    /**
1835
     * Returns the SQL to create a named schema.
1836
     *
1837
     * @param string $schemaName
1838
     *
1839
     * @return string
1840
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1841
     */
1842 10
    public function getCreateSchemaSQL($schemaName)
0 ignored issues
show
Unused Code introduced by
The parameter $schemaName is not used and could be removed. ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

2897
    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...
2898
    {
2899
        throw DBALException::notSupported(__METHOD__);
2900
    }
2901
2902
    /**
2903
     * @param string $sequenceName
2904
     *
2905
     * @return string
2906
     *
2907
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2908
     */
2909
    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

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

3461
    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...
3462
    {
3463
        $tableIdentifier = new Identifier($tableName);
3464
3465
        return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this);
3466
    }
3467
3468 7
    /**
3469
     * This is for test reasons, many vendors have special requirements for dummy statements.
3470 7
     *
3471
     * @return string
3472
     */
3473
    public function getDummySelectSQL()
3474
    {
3475
        return 'SELECT 1';
3476
    }
3477
3478
    /**
3479
     * Returns the SQL to create a new savepoint.
3480 1
     *
3481
     * @param string $savepoint
3482 1
     *
3483
     * @return string
3484
     */
3485
    public function createSavePoint($savepoint)
3486
    {
3487
        return 'SAVEPOINT ' . $savepoint;
3488
    }
3489
3490
    /**
3491
     * Returns the SQL to release a savepoint.
3492 1
     *
3493
     * @param string $savepoint
3494 1
     *
3495
     * @return string
3496
     */
3497
    public function releaseSavePoint($savepoint)
3498
    {
3499
        return 'RELEASE SAVEPOINT ' . $savepoint;
3500
    }
3501
3502
    /**
3503
     * Returns the SQL to rollback a savepoint.
3504 1
     *
3505
     * @param string $savepoint
3506 1
     *
3507
     * @return string
3508
     */
3509
    public function rollbackSavePoint($savepoint)
3510
    {
3511
        return 'ROLLBACK TO SAVEPOINT ' . $savepoint;
3512
    }
3513
3514
    /**
3515
     * Returns the keyword list instance of this platform.
3516 1077
     *
3517
     * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList
3518
     *
3519 1077
     * @throws \Doctrine\DBAL\DBALException If no keyword list is specified.
3520 1010
     */
3521
    final public function getReservedKeywordsList()
3522
    {
3523 953
        // Check for an existing instantiation of the keywords class.
3524 953
        if ($this->_keywords) {
3525 953
            return $this->_keywords;
3526
        }
3527
3528
        $class = $this->getReservedKeywordsClass();
3529
        $keywords = new $class;
3530 953
        if ( ! $keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList) {
3531
            throw DBALException::notSupported(__METHOD__);
3532 953
        }
3533
3534
        // Store the instance so it doesn't need to be generated on every request.
3535
        $this->_keywords = $keywords;
3536
3537
        return $keywords;
3538
    }
3539
3540
    /**
3541
     * Returns the class name of the reserved keywords list.
3542
     *
3543
     * @return string
3544
     *
3545
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3546
     */
3547
    protected function getReservedKeywordsClass()
3548
    {
3549
        throw DBALException::notSupported(__METHOD__);
3550
    }
3551
3552
    /**
3553
     * Quotes a literal string.
3554
     * This method is NOT meant to fix SQL injections!
3555
     * It is only meant to escape this platform's string literal
3556
     * quote character inside the given literal string.
3557 334
     *
3558
     * @param string $str The literal string to be quoted.
3559 334
     *
3560
     * @return string The quoted literal string.
3561 334
     */
3562
    public function quoteStringLiteral($str)
3563
    {
3564
        $c = $this->getStringLiteralQuoteCharacter();
3565
3566
        return $c . str_replace($c, $c . $c, $str) . $c;
3567
    }
3568
3569 352
    /**
3570
     * Gets the character used for string literal quoting.
3571 352
     *
3572
     * @return string
3573
     */
3574
    public function getStringLiteralQuoteCharacter()
3575
    {
3576
        return "'";
3577
    }
3578
3579
    protected function getDropPrimaryKeySQL(string $table) : string
3580
    {
3581
        return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
3582
    }
3583
}
3584