Passed
Pull Request — master (#3013)
by Grégoire
15:40
created

AbstractPlatform::getLikeWildcardCharacters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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