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

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

351
    protected function getVarcharTypeDeclarationSQLSnippet($length, /** @scrutinizer ignore-unused */ $fixed)

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

Loading history...
352
    {
353
        throw DBALException::notSupported('VARCHARs not supported by Platform.');
354
    }
355
356
    /**
357
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
358
     *
359
     * @param int  $length The length of the column.
360
     * @param bool $fixed  Whether the column length is fixed.
361
     *
362
     * @return string
363
     *
364
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
365
     */
366
    protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
0 ignored issues
show
Unused Code introduced by
The parameter $fixed is not used and could be removed. ( Ignorable by Annotation )

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

366
    protected function getBinaryTypeDeclarationSQLSnippet($length, /** @scrutinizer ignore-unused */ $fixed)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
801
                $expression = 'BOTH ';
802
                break;
803
        }
804
805
        if ($char !== false) {
806
            $expression .= $char . ' ';
0 ignored issues
show
Bug introduced by
Are you sure $char of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1356
    public function appendLockHint($fromClause, /** @scrutinizer ignore-unused */ $lockMode)

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

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

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

1713
    public function getCreateSequenceSQL(/** @scrutinizer ignore-unused */ Sequence $sequence)

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

Loading history...
1714
    {
1715
        throw DBALException::notSupported(__METHOD__);
1716
    }
1717
1718
    /**
1719
     * Returns the SQL to change a sequence on this platform.
1720
     *
1721
     * @param \Doctrine\DBAL\Schema\Sequence $sequence
1722
     *
1723
     * @return string
1724
     *
1725
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1726
     */
1727
    public function getAlterSequenceSQL(Sequence $sequence)
0 ignored issues
show
Unused Code introduced by
The parameter $sequence is not used and could be removed. ( Ignorable by Annotation )

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

1727
    public function getAlterSequenceSQL(/** @scrutinizer ignore-unused */ Sequence $sequence)

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

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

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

1855
    public function getCreateSchemaSQL(/** @scrutinizer ignore-unused */ $schemaName)

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

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

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

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

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

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