Passed
Push — travis-db2 ( df5cf0...797aa0 )
by Sergei
03:42
created

AbstractPlatform::getCharMaxLength()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

372
    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...
373
    {
374
        throw DBALException::notSupported('VARCHARs not supported by Platform.');
375
    }
376
377
    /**
378
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
379
     *
380
     * @param int  $length The length of the column.
381
     * @param bool $fixed  Whether the column length is fixed.
382
     *
383
     * @return string
384
     *
385
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
386
     */
387
    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

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

835
            $expression .= /** @scrutinizer ignore-type */ $char . ' ';
Loading history...
836
        }
837
838
        if ($mode || $char !== false) {
839
            $expression .= 'FROM ';
840
        }
841
842
        return 'TRIM(' . $expression . $str . ')';
843
    }
844
845
    /**
846
     * Returns the SQL snippet to trim trailing space characters from the expression.
847
     *
848
     * @param string $str Literal string or column name.
849
     *
850
     * @return string
851
     */
852
    public function getRtrimExpression($str)
853
    {
854
        return 'RTRIM(' . $str . ')';
855
    }
856
857
    /**
858
     * Returns the SQL snippet to trim leading space characters from the expression.
859
     *
860
     * @param string $str Literal string or column name.
861
     *
862
     * @return string
863
     */
864
    public function getLtrimExpression($str)
865
    {
866
        return 'LTRIM(' . $str . ')';
867
    }
868
869
    /**
870
     * Returns the SQL snippet to change all characters from the expression to uppercase,
871
     * according to the current character set mapping.
872
     *
873
     * @param string $str Literal string or column name.
874
     *
875
     * @return string
876
     */
877
    public function getUpperExpression($str)
878
    {
879
        return 'UPPER(' . $str . ')';
880
    }
881
882
    /**
883
     * Returns the SQL snippet to change all characters from the expression to lowercase,
884
     * according to the current character set mapping.
885
     *
886
     * @param string $str Literal string or column name.
887
     *
888
     * @return string
889
     */
890
    public function getLowerExpression($str)
891
    {
892
        return 'LOWER(' . $str . ')';
893
    }
894
895
    /**
896
     * Returns the SQL snippet to get the position of the first occurrence of substring $substr in string $str.
897
     *
898
     * @param string   $str      Literal string.
899
     * @param string   $substr   Literal string to find.
900
     * @param int|bool $startPos Position to start at, beginning of string by default.
901
     *
902
     * @return string
903
     *
904
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
905
     */
906
    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

906
    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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1335
    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...
1336
    {
1337
        throw DBALException::notSupported(__METHOD__);
1338
    }
1339
1340
    /**
1341
     * Returns the SQL bit AND comparison expression.
1342
     *
1343
     * @param string $value1
1344
     * @param string $value2
1345
     *
1346
     * @return string
1347
     */
1348
    public function getBitAndComparisonExpression($value1, $value2)
1349
    {
1350
        return '(' . $value1 . ' & ' . $value2 . ')';
1351
    }
1352
1353
    /**
1354
     * Returns the SQL bit OR comparison expression.
1355
     *
1356
     * @param string $value1
1357
     * @param string $value2
1358
     *
1359
     * @return string
1360
     */
1361
    public function getBitOrComparisonExpression($value1, $value2)
1362
    {
1363
        return '(' . $value1 . ' | ' . $value2 . ')';
1364
    }
1365
1366
    /**
1367
     * Returns the FOR UPDATE expression.
1368
     *
1369
     * @return string
1370
     */
1371
    public function getForUpdateSQL()
1372
    {
1373
        return 'FOR UPDATE';
1374
    }
1375
1376
    /**
1377
     * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification.
1378
     *
1379
     * @param string   $fromClause The FROM clause to append the hint for the given lock mode to.
1380
     * @param int|null $lockMode   One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will
1381
     *                             be appended to the FROM clause.
1382
     *
1383
     * @return string
1384
     */
1385
    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

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

1742
    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...
1743
    {
1744
        throw DBALException::notSupported(__METHOD__);
1745
    }
1746
1747
    /**
1748
     * Returns the SQL to change a sequence on this platform.
1749
     *
1750
     * @param \Doctrine\DBAL\Schema\Sequence $sequence
1751
     *
1752
     * @return string
1753
     *
1754
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1755
     */
1756
    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

1756
    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...
1757
    {
1758
        throw DBALException::notSupported(__METHOD__);
1759
    }
1760
1761
    /**
1762
     * Returns the SQL to create a constraint on a table on this platform.
1763
     *
1764
     * @param \Doctrine\DBAL\Schema\Constraint   $constraint
1765
     * @param \Doctrine\DBAL\Schema\Table|string $table
1766
     *
1767
     * @return string
1768
     *
1769
     * @throws \InvalidArgumentException
1770
     */
1771
    public function getCreateConstraintSQL(Constraint $constraint, $table)
1772
    {
1773
        if ($table instanceof Table) {
1774
            $table = $table->getQuotedName($this);
1775
        }
1776
1777
        $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this);
1778
1779
        $columnList = '('. implode(', ', $constraint->getQuotedColumns($this)) . ')';
1780
1781
        $referencesClause = '';
1782
        if ($constraint instanceof Index) {
1783
            if ($constraint->isPrimary()) {
1784
                $query .= ' PRIMARY KEY';
1785
            } elseif ($constraint->isUnique()) {
1786
                $query .= ' UNIQUE';
1787
            } else {
1788
                throw new \InvalidArgumentException(
1789
                    'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().'
1790
                );
1791
            }
1792
        } elseif ($constraint instanceof ForeignKeyConstraint) {
1793
            $query .= ' FOREIGN KEY';
1794
1795
            $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) .
1796
                ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')';
1797
        }
1798
        $query .= ' '.$columnList.$referencesClause;
1799
1800
        return $query;
1801
    }
1802
1803
    /**
1804
     * Returns the SQL to create an index on a table on this platform.
1805
     *
1806
     * @param \Doctrine\DBAL\Schema\Index        $index
1807
     * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created.
1808
     *
1809
     * @return string
1810
     *
1811
     * @throws \InvalidArgumentException
1812
     */
1813
    public function getCreateIndexSQL(Index $index, $table)
1814
    {
1815
        if ($table instanceof Table) {
1816
            $table = $table->getQuotedName($this);
1817
        }
1818
        $name = $index->getQuotedName($this);
1819
        $columns = $index->getQuotedColumns($this);
1820
1821
        if (count($columns) == 0) {
1822
            throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
1823
        }
1824
1825
        if ($index->isPrimary()) {
1826
            return $this->getCreatePrimaryKeySQL($index, $table);
1827
        }
1828
1829
        $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table;
1830
        $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index);
1831
1832
        return $query;
1833
    }
1834
1835
    /**
1836
     * Adds condition for partial index.
1837
     *
1838
     * @param \Doctrine\DBAL\Schema\Index $index
1839
     *
1840
     * @return string
1841
     */
1842
    protected function getPartialIndexSQL(Index $index)
1843
    {
1844
        if ($this->supportsPartialIndexes() && $index->hasOption('where')) {
1845
            return  ' WHERE ' . $index->getOption('where');
1846
        }
1847
1848
        return '';
1849
    }
1850
1851
    /**
1852
     * Adds additional flags for index generation.
1853
     *
1854
     * @param \Doctrine\DBAL\Schema\Index $index
1855
     *
1856
     * @return string
1857
     */
1858
    protected function getCreateIndexSQLFlags(Index $index)
1859
    {
1860
        return $index->isUnique() ? 'UNIQUE ' : '';
1861
    }
1862
1863
    /**
1864
     * Returns the SQL to create an unnamed primary key constraint.
1865
     *
1866
     * @param \Doctrine\DBAL\Schema\Index        $index
1867
     * @param \Doctrine\DBAL\Schema\Table|string $table
1868
     *
1869
     * @return string
1870
     */
1871
    public function getCreatePrimaryKeySQL(Index $index, $table)
1872
    {
1873
        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

1873
        return 'ALTER TABLE ' . /** @scrutinizer ignore-type */ $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
Loading history...
1874
    }
1875
1876
    /**
1877
     * Returns the SQL to create a named schema.
1878
     *
1879
     * @param string $schemaName
1880
     *
1881
     * @return string
1882
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1883
     */
1884
    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

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

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

2934
    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...
2935
    {
2936
        throw DBALException::notSupported(__METHOD__);
2937
    }
2938
2939
    /**
2940
     * @param string $sequenceName
2941
     *
2942
     * @return string
2943
     *
2944
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2945
     */
2946
    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

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

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