Passed
Push — travis-db2 ( e41f38...b6ffa6 )
by Sergei
24:09
created

AbstractPlatform   F

Complexity

Total Complexity 385

Size/Duplication

Total Lines 3556
Duplicated Lines 0 %

Test Coverage

Coverage 80.67%

Importance

Changes 0
Metric Value
wmc 385
dl 0
loc 3556
ccs 655
cts 812
cp 0.8067
rs 0.6314
c 0
b 0
f 0

208 Methods

Rating   Name   Duplication   Size   Complexity  
A supportsAlterTable() 0 3 1
A getEventManager() 0 3 1
A supportsForeignKeyOnUpdate() 0 3 2
B getCheckDeclarationSQL() 0 18 5
A getWriteLockSQL() 0 3 1
A getCharMaxLength() 0 3 1
A getCreateSchemaSQL() 0 3 1
A getLtrimExpression() 0 3 1
A getFloatDeclarationSQL() 0 3 1
A getDefaultSchemaName() 0 3 1
A supportsCreateDropDatabase() 0 3 1
A onSchemaAlterTableRenameColumn() 0 16 3
A getCreateDatabaseSQL() 0 3 1
A getListTableColumnsSQL() 0 3 1
A initializeCommentedDoctrineTypes() 0 9 3
A supportsLimitOffset() 0 3 1
A getListDatabasesSQL() 0 3 1
A supportsSavepoints() 0 3 1
A getDateTimeTzTypeDeclarationSQL() 0 3 1
A getCosExpression() 0 3 1
F getCreateTableSQL() 0 89 23
A supportsTransactions() 0 3 1
A getForUpdateSQL() 0 3 1
B getPreAlterTableIndexForeignKeySQL() 0 22 6
A hasNativeGuidType() 0 3 1
A getRenameIndexSQL() 0 5 1
A fixSchemaElementName() 0 3 1
A getVarcharMaxLength() 0 3 1
A getDateTimeTypeDeclarationSQL() 0 3 1
A supportsCommentOnStatement() 0 3 1
A convertFromBoolean() 0 3 2
A getSqrtExpression() 0 3 1
A getDateSubMonthExpression() 0 3 1
A _getAlterTableIndexForeignKeySQL() 0 3 1
A getTemporaryTableSQL() 0 3 1
A getDateAddYearsExpression() 0 3 1
A getIdentityColumnNullInsertSQL() 0 3 1
A getGuidExpression() 0 3 1
A getCreateIndexSQL() 0 20 4
A getDropSequenceSQL() 0 3 1
A getDefaultTransactionIsolationLevel() 0 3 1
A getBetweenExpression() 0 3 1
A getMaxIdentifierLength() 0 3 1
A getIsNullExpression() 0 3 1
A getSqlCommentStartString() 0 3 1
A getUpperExpression() 0 3 1
B _getTransactionIsolationLevelSQL() 0 13 5
A getForeignKeyDeclarationSQL() 0 6 1
A prefersIdentityColumns() 0 3 1
A getDropForeignKeySQL() 0 14 3
A getBinaryDefaultLength() 0 3 1
A getListNamespacesSQL() 0 3 1
A getSumExpression() 0 3 1
A registerDoctrineTypeMapping() 0 17 4
A appendLockHint() 0 3 1
A markDoctrineTypeCommented() 0 7 3
A getSqlCommentEndString() 0 3 1
A getUniqueConstraintDeclarationSQL() 0 12 2
A getDateDiffExpression() 0 3 1
A supportsViews() 0 3 1
A getCreatePrimaryKeySQL() 0 3 1
A canEmulateSchemas() 0 3 1
A getAlterTableSQL() 0 3 1
A getCreateViewSQL() 0 3 1
A getColumnCharsetDeclarationSQL() 0 3 1
A getGuidTypeDeclarationSQL() 0 6 1
A getDateFormatString() 0 3 1
A getListUsersSQL() 0 3 1
A getPiExpression() 0 3 1
A getListSequencesSQL() 0 3 1
B convertBooleans() 0 13 5
A createSavePoint() 0 3 1
A getAvgExpression() 0 3 1
A getCreateForeignKeySQL() 0 9 2
A convertBooleansToDatabaseValue() 0 3 1
A supportsIdentityColumns() 0 3 1
A getIdentitySequenceName() 0 3 1
A getBinaryMaxLength() 0 3 1
A getReadLockSQL() 0 3 1
A getAcosExpression() 0 3 1
B getForeignKeyReferentialActionSQL() 0 12 6
A getSequenceNextValSQL() 0 3 1
A getDoctrineTypeComment() 0 3 1
A getMd5Expression() 0 3 1
A getCurrentDateSQL() 0 3 1
A getCustomTypeDeclarationSQL() 0 3 1
A supportsPartialIndexes() 0 3 1
A getCountExpression() 0 3 1
A prefersSequences() 0 3 1
A getMinExpression() 0 3 1
A getReservedKeywordsClass() 0 3 1
A getReservedKeywordsList() 0 17 3
A getVarcharTypeDeclarationSQLSnippet() 0 3 1
A getModExpression() 0 3 1
A getStringLiteralQuoteCharacter() 0 3 1
A getColumnCollationDeclarationSQL() 0 3 2
F getColumnDeclarationSQL() 0 30 15
A getDropConstraintSQL() 0 14 3
A getCommentOnColumnSQL() 0 8 1
A getDateSubQuartersExpression() 0 3 1
C getDefaultValueDeclarationSQL() 0 35 12
A supportsSchemas() 0 3 1
A getSQLResultCasing() 0 3 1
A getDropViewSQL() 0 3 1
A getDateAddMonthExpression() 0 3 1
A getMaxExpression() 0 3 1
A getBitAndComparisonExpression() 0 3 1
A onSchemaAlterTableAddColumn() 0 16 3
B getDropTableSQL() 0 20 6
A getDateTimeFormatString() 0 3 1
A quoteSingleIdentifier() 0 5 1
A supportsSequences() 0 3 1
A getCurrentTimeSQL() 0 3 1
A getDateAddWeeksExpression() 0 3 1
A supportsReleaseSavepoints() 0 3 1
A getDummySelectSQL() 0 5 2
A getDropIndexSQL() 0 9 3
A supportsIndexes() 0 3 1
A getIndexFieldDeclarationListSQL() 0 13 3
A hasDoctrineTypeMappingFor() 0 9 2
A getDateSubMinutesExpression() 0 3 1
A getDateSubHourExpression() 0 3 1
A getDateTypeDeclarationSQL() 0 3 1
A getCreateIndexSQLFlags() 0 3 2
A getAdvancedForeignKeyOptionsSQL() 0 11 4
A getLengthExpression() 0 3 1
A supportsColumnCollation() 0 3 1
A getVarcharDefaultLength() 0 3 1
B getDecimalTypeDeclarationSQL() 0 8 5
A quoteStringLiteral() 0 5 1
A hasNativeJsonType() 0 3 1
A getTruncateTableSQL() 0 5 1
A getDateSubWeeksExpression() 0 3 1
A getLikeWildcardCharacters() 0 3 1
A usesSequenceEmulatedIdentityColumns() 0 3 1
A getSetTransactionIsolationSQL() 0 3 1
A getDateAddDaysExpression() 0 3 1
A getIdentifierQuoteCharacter() 0 3 1
A getDateSubDaysExpression() 0 3 1
A getListTableForeignKeysSQL() 0 3 1
A __construct() 0 2 1
C getPostAlterTableIndexForeignKeySQL() 0 35 8
C _getCreateTableSQL() 0 37 12
A onSchemaAlterTable() 0 16 3
A getListViewsSQL() 0 3 1
A getUniqueFieldDeclarationSQL() 0 3 1
A initializeAllDoctrineTypeMappings() 0 7 3
A isCommentedDoctrineType() 0 7 2
A getRegexpExpression() 0 3 1
A getDoctrineTypeMapping() 0 13 3
A supportsForeignKeyConstraints() 0 3 1
B modifyLimitQuery() 0 18 6
A getTimeFormatString() 0 3 1
A getBitOrComparisonExpression() 0 3 1
A getTimeTypeDeclarationSQL() 0 3 1
A getSinExpression() 0 3 1
A getLowerExpression() 0 3 1
A getTemporaryTableName() 0 3 1
B getForeignKeyBaseDeclarationSQL() 0 24 5
A getCreateTemporaryTableSnippetSQL() 0 3 1
A getNowExpression() 0 3 1
A getCreateSequenceSQL() 0 3 1
A getVarcharTypeDeclarationSQL() 0 17 4
A getDateSubSecondsExpression() 0 3 1
A getDateTimeTzFormatString() 0 3 1
A setEventManager() 0 3 1
A supportsGettingAffectedRows() 0 3 1
A getRoundExpression() 0 3 1
A getCurrentTimestampSQL() 0 3 1
A releaseSavePoint() 0 3 1
A getIsNotNullExpression() 0 3 1
A getRtrimExpression() 0 3 1
B getCreateConstraintSQL() 0 30 6
A rollbackSavePoint() 0 3 1
A getInlineColumnCommentSQL() 0 7 2
A getSubstringExpression() 0 7 2
A getListTableConstraintsSQL() 0 3 1
A getAlterSequenceSQL() 0 3 1
A getDateArithmeticIntervalExpression() 0 3 1
A getDateAddMinutesExpression() 0 3 1
A getBinaryTypeDeclarationSQL() 0 13 3
A getIndexDeclarationSQL() 0 12 2
A getJsonTypeDeclarationSQL() 0 3 1
A getListTableIndexesSQL() 0 3 1
A getConcatExpression() 0 3 1
A getLocateExpression() 0 3 1
A getWildcards() 0 3 1
A getListTablesSQL() 0 3 1
A getEmptyIdentityInsertSQL() 0 3 1
A supportsInlineColumnComments() 0 3 1
A quoteIdentifier() 0 9 2
C getTrimExpression() 0 27 7
A getDateAddQuartersExpression() 0 3 1
A getDropTemporaryTableSQL() 0 3 1
A doModifyLimitQuery() 0 11 3
A getPartialIndexSQL() 0 7 3
A getNotExpression() 0 3 1
A onSchemaAlterTableRemoveColumn() 0 16 3
A getDateSubYearsExpression() 0 3 1
A escapeStringForLike() 0 6 1
A getDropDatabaseSQL() 0 3 1
A getColumnDeclarationListSQL() 0 9 2
A onSchemaAlterTableChangeColumn() 0 16 3
A getColumnComment() 0 9 2
A getDateAddSecondsExpression() 0 3 1
A supportsPrimaryConstraints() 0 3 1
A getDateAddHourExpression() 0 3 1
A getBinaryTypeDeclarationSQLSnippet() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractPlatform often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AbstractPlatform, and based on these observations, apply Extract Interface, too.

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 62874
    public function __construct()
195
    {
196 62874
    }
197
198
    /**
199
     * Sets the EventManager used by the Platform.
200
     *
201
     * @param \Doctrine\Common\EventManager $eventManager
202
     */
203 1620
    public function setEventManager(EventManager $eventManager)
204
    {
205 1620
        $this->_eventManager = $eventManager;
206 1620
    }
207
208
    /**
209
     * Gets the EventManager used by the Platform.
210
     *
211
     * @return \Doctrine\Common\EventManager
212
     */
213 981
    public function getEventManager()
214
    {
215 981
        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 1782
    private function initializeAllDoctrineTypeMappings()
277
    {
278 1782
        $this->initializeDoctrineTypeMappings();
279
280 1782
        foreach (Type::getTypesMap() as $typeName => $className) {
281 1782
            foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) {
282 1782
                $this->doctrineTypeMapping[$dbType] = $typeName;
283
            }
284
        }
285 1782
    }
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 6248
    public function getVarcharTypeDeclarationSQL(array $field)
295
    {
296 6248
        if ( !isset($field['length'])) {
297 1488
            $field['length'] = $this->getVarcharDefaultLength();
298
        }
299
300 6248
        $fixed = $field['fixed'] ?? false;
301
302 6248
        $maxLength = $fixed
303 890
            ? $this->getCharMaxLength()
304 6248
            : $this->getVarcharMaxLength();
305
306 6248
        if ($field['length'] > $maxLength) {
307
            return $this->getClobTypeDeclarationSQL($field);
308
        }
309
310 6248
        return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed);
311
    }
312
313
    /**
314
     * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
315
     *
316
     * @param array $field The column definition.
317
     *
318
     * @return string
319
     */
320 359
    public function getBinaryTypeDeclarationSQL(array $field)
321
    {
322 359
        if ( ! isset($field['length'])) {
323 341
            $field['length'] = $this->getBinaryDefaultLength();
324
        }
325
326 359
        $fixed = $field['fixed'] ?? false;
327
328 359
        if ($field['length'] > $this->getBinaryMaxLength()) {
329 331
            return $this->getBlobTypeDeclarationSQL($field);
330
        }
331
332 352
        return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed);
333
    }
334
335
    /**
336
     * Returns the SQL snippet to declare a GUID/UUID field.
337
     *
338
     * By default this maps directly to a CHAR(36) and only maps to more
339
     * special datatypes when the underlying databases support this datatype.
340
     *
341
     * @param array $field
342
     *
343
     * @return string
344
     */
345 116
    public function getGuidTypeDeclarationSQL(array $field)
346
    {
347 116
        $field['length'] = 36;
348 116
        $field['fixed']  = true;
349
350 116
        return $this->getVarcharTypeDeclarationSQL($field);
351
    }
352
353
    /**
354
     * Returns the SQL snippet to declare a JSON field.
355
     *
356
     * By default this maps directly to a CLOB and only maps to more
357
     * special datatypes when the underlying databases support this datatype.
358
     *
359
     * @param array $field
360
     *
361
     * @return string
362
     */
363 374
    public function getJsonTypeDeclarationSQL(array $field)
364
    {
365 374
        return $this->getClobTypeDeclarationSQL($field);
366
    }
367
368
    /**
369
     * @param int  $length
370
     * @param bool $fixed
371
     *
372
     * @return string
373
     *
374
     * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
375
     */
376
    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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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