Passed
Pull Request — master (#3013)
by Grégoire
28:10
created

AbstractPlatform::escapeStringForLike()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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

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

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

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

878
    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

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

1049
    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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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