Passed
Pull Request — master (#3013)
by Grégoire
14:17
created

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
800
                $expression = 'BOTH ';
801
                break;
802
        }
803
804
        if ($char !== false) {
805
            $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

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

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

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

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $startPos is not used and could be removed. ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

1712
    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...
1713
    {
1714
        throw DBALException::notSupported(__METHOD__);
1715
    }
1716
1717
    /**
1718
     * Returns the SQL to change a sequence on this platform.
1719
     *
1720
     * @param \Doctrine\DBAL\Schema\Sequence $sequence
1721
     *
1722
     * @return string
1723
     *
1724
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1725
     */
1726
    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

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

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

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

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

2904
    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...
2905
    {
2906
        throw DBALException::notSupported(__METHOD__);
2907
    }
2908
2909
    /**
2910
     * @param string $sequenceName
2911
     *
2912
     * @return string
2913
     *
2914
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2915
     */
2916
    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

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

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