Failed Conditions
Pull Request — master (#2825)
by Sébastien
12:27
created

getPreAlterTableAlterIndexForeignKeySQL()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 30
Code Lines 13

Duplication

Lines 17
Ratio 56.67 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 0
Metric Value
dl 17
loc 30
ccs 13
cts 13
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 13
nc 5
nop 1
crap 7
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\DBAL\Connection;
23
use Doctrine\DBAL\Schema\Identifier;
24
use Doctrine\DBAL\Schema\Index;
25
use Doctrine\DBAL\Schema\Table;
26
use Doctrine\DBAL\Schema\TableDiff;
27
use Doctrine\DBAL\Types\BlobType;
28
use Doctrine\DBAL\Types\TextType;
29
use Doctrine\DBAL\Types\Type;
30
31
/**
32
 * The MySqlPlatform provides the behavior, features and SQL dialect of the
33
 * MySQL database platform. This platform represents a MySQL 5.0 or greater platform that
34
 * uses the InnoDB storage engine.
35
 *
36
 * @since  2.0
37
 * @author Roman Borschel <[email protected]>
38
 * @author Benjamin Eberlei <[email protected]>
39
 * @todo   Rename: MySQLPlatform
40
 */
41
class MySqlPlatform extends AbstractPlatform
42
{
43
    const LENGTH_LIMIT_TINYTEXT   = 255;
44
    const LENGTH_LIMIT_TEXT       = 65535;
45
    const LENGTH_LIMIT_MEDIUMTEXT = 16777215;
46
47
    const LENGTH_LIMIT_TINYBLOB   = 255;
48
    const LENGTH_LIMIT_BLOB       = 65535;
49
    const LENGTH_LIMIT_MEDIUMBLOB = 16777215;
50
51
    /**
52
     * Adds MySQL-specific LIMIT clause to the query
53
     * 18446744073709551615 is 2^64-1 maximum of unsigned BIGINT the biggest limit possible
54
     *
55
     * @param string  $query
56
     * @param integer $limit
57
     * @param integer $offset
58
     *
59
     * @return string
60
     */
61 9
    protected function doModifyLimitQuery($query, $limit, $offset)
62
    {
63 9
        if ($limit !== null) {
64 6
            $query .= ' LIMIT ' . $limit;
65 6
            if ($offset !== null) {
66 6
                $query .= ' OFFSET ' . $offset;
67
            }
68 3
        } elseif ($offset !== null) {
69 3
            $query .= ' LIMIT 18446744073709551615 OFFSET ' . $offset;
70
        }
71
72 9
        return $query;
73
    }
74
75
    /**
76
     * {@inheritDoc}
77
     */
78 82
    public function getIdentifierQuoteCharacter()
79
    {
80 82
        return '`';
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86 3
    public function getRegexpExpression()
87
    {
88 3
        return 'RLIKE';
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94
    public function getGuidExpression()
95
    {
96
        return 'UUID()';
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     */
102 View Code Duplication
    public function getLocateExpression($str, $substr, $startPos = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103
    {
104
        if ($startPos == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
105
            return 'LOCATE(' . $substr . ', ' . $str . ')';
106
        }
107
108
        return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     */
114 3
    public function getConcatExpression()
115
    {
116 3
        $args = func_get_args();
117
118 3
        return 'CONCAT(' . join(', ', (array) $args) . ')';
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit)
125
    {
126
        $function = '+' === $operator ? 'DATE_ADD' : 'DATE_SUB';
127
128
        return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')';
129
    }
130
131
    /**
132
     * {@inheritDoc}
133
     */
134
    public function getDateDiffExpression($date1, $date2)
135
    {
136
        return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')';
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142 3
    public function getListDatabasesSQL()
143
    {
144 3
        return 'SHOW DATABASES';
145
    }
146
147
    /**
148
     * {@inheritDoc}
149
     */
150
    public function getListTableConstraintsSQL($table)
151
    {
152
        return 'SHOW INDEX FROM ' . $table;
153
    }
154
155
    /**
156
     * {@inheritDoc}
157
     *
158
     * Two approaches to listing the table indexes. The information_schema is
159
     * preferred, because it doesn't cause problems with SQL keywords such as "order" or "table".
160
     */
161 6 View Code Duplication
    public function getListTableIndexesSQL($table, $currentDatabase = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162
    {
163 6
        if ($currentDatabase) {
164 6
            $currentDatabase = $this->quoteStringLiteral($currentDatabase);
165 6
            $table = $this->quoteStringLiteral($table);
166
167
            return "SELECT TABLE_NAME AS `Table`, NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, ".
168
                   "SEQ_IN_INDEX AS Seq_in_index, COLUMN_NAME AS Column_Name, COLLATION AS Collation, ".
169
                   "CARDINALITY AS Cardinality, SUB_PART AS Sub_Part, PACKED AS Packed, " .
170
                   "NULLABLE AS `Null`, INDEX_TYPE AS Index_Type, COMMENT AS Comment " .
171 6
                   "FROM information_schema.STATISTICS WHERE TABLE_NAME = " . $table . " AND TABLE_SCHEMA = " . $currentDatabase;
172
        }
173
174
        return 'SHOW INDEX FROM ' . $table;
175
    }
176
177
    /**
178
     * {@inheritDoc}
179
     */
180 3
    public function getListViewsSQL($database)
181
    {
182 3
        $database = $this->quoteStringLiteral($database);
183
184 3
        return "SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = " . $database;
185
    }
186
187
    /**
188
     * {@inheritDoc}
189
     */
190 9
    public function getListTableForeignKeysSQL($table, $database = null)
191
    {
192 9
        $table = $this->quoteStringLiteral($table);
193
194 9
        if (null !== $database) {
195 6
            $database = $this->quoteStringLiteral($database);
196
        }
197
198
        $sql = "SELECT DISTINCT k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, ".
199
               "k.`REFERENCED_COLUMN_NAME` /*!50116 , c.update_rule, c.delete_rule */ ".
200
               "FROM information_schema.key_column_usage k /*!50116 ".
201
               "INNER JOIN information_schema.referential_constraints c ON ".
202
               "  c.constraint_name = k.constraint_name AND ".
203 9
               "  c.table_name = $table */ WHERE k.table_name = $table";
204
205 9
        $databaseNameSql = null === $database ? 'DATABASE()' : $database;
206
207 9
        $sql .= " AND k.table_schema = $databaseNameSql /*!50116 AND c.constraint_schema = $databaseNameSql */";
208 9
        $sql .= " AND k.`REFERENCED_COLUMN_NAME` is not NULL";
209
210 9
        return $sql;
211
    }
212
213
    /**
214
     * {@inheritDoc}
215
     */
216
    public function getCreateViewSQL($name, $sql)
217
    {
218
        return 'CREATE VIEW ' . $name . ' AS ' . $sql;
219
    }
220
221
    /**
222
     * {@inheritDoc}
223
     */
224
    public function getDropViewSQL($name)
225
    {
226
        return 'DROP VIEW '. $name;
227
    }
228
229
    /**
230
     * {@inheritDoc}
231
     */
232 45
    protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
233
    {
234 45
        return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
235 45
                : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241 3
    protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
242
    {
243 3
        return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')';
244
    }
245
246
    /**
247
     * Gets the SQL snippet used to declare a CLOB column type.
248
     *     TINYTEXT   : 2 ^  8 - 1 = 255
249
     *     TEXT       : 2 ^ 16 - 1 = 65535
250
     *     MEDIUMTEXT : 2 ^ 24 - 1 = 16777215
251
     *     LONGTEXT   : 2 ^ 32 - 1 = 4294967295
252
     *
253
     * @param array $field
254
     *
255
     * @return string
256
     */
257 17 View Code Duplication
    public function getClobTypeDeclarationSQL(array $field)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
258
    {
259 17
        if ( ! empty($field['length']) && is_numeric($field['length'])) {
260 4
            $length = $field['length'];
261
262 4
            if ($length <= static::LENGTH_LIMIT_TINYTEXT) {
263 3
                return 'TINYTEXT';
264
            }
265
266 4
            if ($length <= static::LENGTH_LIMIT_TEXT) {
267 4
                return 'TEXT';
268
            }
269
270 3
            if ($length <= static::LENGTH_LIMIT_MEDIUMTEXT) {
271 3
                return 'MEDIUMTEXT';
272
            }
273
        }
274
275 16
        return 'LONGTEXT';
276
    }
277
278
    /**
279
     * {@inheritDoc}
280
     */
281 3 View Code Duplication
    public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
282
    {
283 3
        if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
284 3
            return 'TIMESTAMP';
285
        }
286
287 3
        return 'DATETIME';
288
    }
289
290
    /**
291
     * {@inheritDoc}
292
     */
293
    public function getDateTypeDeclarationSQL(array $fieldDeclaration)
294
    {
295
        return 'DATE';
296
    }
297
298
    /**
299
     * {@inheritDoc}
300
     */
301
    public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
302
    {
303
        return 'TIME';
304
    }
305
306
    /**
307
     * {@inheritDoc}
308
     */
309 3
    public function getBooleanTypeDeclarationSQL(array $field)
310
    {
311 3
        return 'TINYINT(1)';
312
    }
313
314
    /**
315
     * Obtain DBMS specific SQL code portion needed to set the COLLATION
316
     * of a field declaration to be used in statements like CREATE TABLE.
317
     *
318
     * @deprecated Deprecated since version 2.5, Use {@link self::getColumnCollationDeclarationSQL()} instead.
319
     *
320
     * @param string $collation name of the collation
321
     *
322
     * @return string  DBMS specific SQL code portion needed to set the COLLATION
323
     *                 of a field declaration.
324
     */
325
    public function getCollationFieldDeclaration($collation)
326
    {
327
        return $this->getColumnCollationDeclarationSQL($collation);
328
    }
329
330
    /**
331
     * {@inheritDoc}
332
     *
333
     * MySql prefers "autoincrement" identity columns since sequences can only
334
     * be emulated with a table.
335
     */
336 3
    public function prefersIdentityColumns()
337
    {
338 3
        return true;
339
    }
340
341
    /**
342
     * {@inheritDoc}
343
     *
344
     * MySql supports this through AUTO_INCREMENT columns.
345
     */
346 3
    public function supportsIdentityColumns()
347
    {
348 3
        return true;
349
    }
350
351
    /**
352
     * {@inheritDoc}
353
     */
354 99
    public function supportsInlineColumnComments()
355
    {
356 99
        return true;
357
    }
358
359
    /**
360
     * {@inheritDoc}
361
     */
362
    public function supportsColumnCollation()
363
    {
364
        return true;
365
    }
366
367
    /**
368
     * {@inheritDoc}
369
     */
370
    public function getListTablesSQL()
371
    {
372
        return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
373
    }
374
375
    /**
376
     * {@inheritDoc}
377
     */
378 6 View Code Duplication
    public function getListTableColumnsSQL($table, $database = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
379
    {
380 6
        $table = $this->quoteStringLiteral($table);
381
382 6
        if ($database) {
383 3
            $database = $this->quoteStringLiteral($database);
384
        } else {
385 3
            $database = 'DATABASE()';
386
        }
387
388
        return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ".
389
               "COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " .
390
               "CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation ".
391 6
               "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = " . $database . " AND TABLE_NAME = " . $table;
392
    }
393
394
    /**
395
     * {@inheritDoc}
396
     */
397 3
    public function getCreateDatabaseSQL($name)
398
    {
399 3
        return 'CREATE DATABASE ' . $name;
400
    }
401
402
    /**
403
     * {@inheritDoc}
404
     */
405 3
    public function getDropDatabaseSQL($name)
406
    {
407 3
        return 'DROP DATABASE ' . $name;
408
    }
409
410
    /**
411
     * {@inheritDoc}
412
     */
413 45
    protected function _getCreateTableSQL($tableName, array $columns, array $options = [])
414
    {
415 45
        $queryFields = $this->getColumnDeclarationListSQL($columns);
416
417 45
        if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
418
            foreach ($options['uniqueConstraints'] as $index => $definition) {
419
                $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition);
420
            }
421
        }
422
423
        // add all indexes
424 45
        if (isset($options['indexes']) && ! empty($options['indexes'])) {
425 20
            foreach ($options['indexes'] as $index => $definition) {
426 20
                $queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
427
            }
428
        }
429
430
        // attach all primary keys
431 45 View Code Duplication
        if (isset($options['primary']) && ! empty($options['primary'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
432 15
            $keyColumns = array_unique(array_values($options['primary']));
433 15
            $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
434
        }
435
436 45
        $query = 'CREATE ';
437
438 45
        if (!empty($options['temporary'])) {
439
            $query .= 'TEMPORARY ';
440
        }
441
442 45
        $query .= 'TABLE ' . $tableName . ' (' . $queryFields . ') ';
443 45
        $query .= $this->buildTableOptions($options);
444 45
        $query .= $this->buildPartitionOptions($options);
445
446 45
        $sql[]  = $query;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$sql was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sql = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
447 45
        $engine = 'INNODB';
448
449 45
        if (isset($options['engine'])) {
450 9
            $engine = strtoupper(trim($options['engine']));
451
        }
452
453
        // Propagate foreign key constraints only for InnoDB.
454 45 View Code Duplication
        if (isset($options['foreignKeys']) && $engine === 'INNODB') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
455 6
            foreach ((array) $options['foreignKeys'] as $definition) {
456 6
                $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
457
            }
458
        }
459
460 45
        return $sql;
461
    }
462
463
    /**
464
     * Tells whether a field type supports declaration of a default value.
465
     *
466
     * MySQL (as of 5.7.19) does not support default values for Blob and Text
467
     * columns while MariaDB 10.2.1 does.
468
     */
469 68
    protected function isDefaultValueSupportedForType(Type $field) : bool
470
    {
471 68
        return !($field instanceof TextType || $field instanceof BlobType);
472
    }
473
474
    /**
475
     * {@inheritdoc}
476
     */
477 102
    public function getDefaultValueDeclarationSQL($field)
478
    {
479
        // Unset the default value if the given field type does not allow default values.
480 102
        if (! $this->isDefaultValueSupportedForType($field['type'])) {
481 6
            $field['default'] = null;
482
        }
483
484 102
        return parent::getDefaultValueDeclarationSQL($field);
485
    }
486
487
    /**
488
     * Build SQL for table options
489
     *
490
     * @param array $options
491
     *
492
     * @return string
493
     */
494 45
    private function buildTableOptions(array $options)
495
    {
496 45
        if (isset($options['table_options'])) {
497
            return $options['table_options'];
498
        }
499
500 45
        $tableOptions = [];
501
502
        // Charset
503 45
        if ( ! isset($options['charset'])) {
504 45
            $options['charset'] = 'utf8';
505
        }
506
507 45
        $tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']);
508
509
        // Collate
510 45
        if ( ! isset($options['collate'])) {
511 45
            $options['collate'] = 'utf8_unicode_ci';
512
        }
513
514 45
        $tableOptions[] = sprintf('COLLATE %s', $options['collate']);
515
516
        // Engine
517 45
        if ( ! isset($options['engine'])) {
518 36
            $options['engine'] = 'InnoDB';
519
        }
520
521 45
        $tableOptions[] = sprintf('ENGINE = %s', $options['engine']);
522
523
        // Auto increment
524 45
        if (isset($options['auto_increment'])) {
525
            $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']);
526
        }
527
528
        // Comment
529 45 View Code Duplication
        if (isset($options['comment'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
530
            $comment = trim($options['comment'], " '");
531
532
            $tableOptions[] = sprintf("COMMENT = %s ", $this->quoteStringLiteral($comment));
533
        }
534
535
        // Row format
536 45
        if (isset($options['row_format'])) {
537
            $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']);
538
        }
539
540 45
        return implode(' ', $tableOptions);
541
    }
542
543
    /**
544
     * Build SQL for partition options.
545
     *
546
     * @param array $options
547
     *
548
     * @return string
549
     */
550 45
    private function buildPartitionOptions(array $options)
551
    {
552 45
        return (isset($options['partition_options']))
553
            ? ' ' . $options['partition_options']
554 45
            : '';
555
    }
556
557
    /**
558
     * {@inheritDoc}
559
     */
560 79
    public function getAlterTableSQL(TableDiff $diff)
561
    {
562 79
        $columnSql = [];
563 79
        $queryParts = [];
564 79
        if ($diff->newName !== false) {
565 6
            $queryParts[] = 'RENAME TO ' . $diff->getNewName()->getQuotedName($this);
566
        }
567
568 79 View Code Duplication
        foreach ($diff->addedColumns as $column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
569 18
            if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
570
                continue;
571
            }
572
573 18
            $columnArray = $column->toArray();
574 18
            $columnArray['comment'] = $this->getColumnComment($column);
575 18
            $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
576
        }
577
578 79 View Code Duplication
        foreach ($diff->removedColumns as $column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
579 9
            if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
580
                continue;
581
            }
582
583 9
            $queryParts[] =  'DROP ' . $column->getQuotedName($this);
584
        }
585
586 79 View Code Duplication
        foreach ($diff->changedColumns as $columnDiff) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
587 23
            if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
588
                continue;
589
            }
590
591
            /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */
592 23
            $column = $columnDiff->column;
593 23
            $columnArray = $column->toArray();
594
595
            // Don't propagate default value changes for unsupported column types.
596 23
            if ($columnDiff->hasChanged('default') &&
597 23
                count($columnDiff->changedProperties) === 1 &&
598 23
                ! $this->isDefaultValueSupportedForType($columnArray['type'])
599
            ) {
600 2
                continue;
601
            }
602
603 21
            $columnArray['comment'] = $this->getColumnComment($column);
604 21
            $queryParts[] =  'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' '
605 21
                    . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
606
        }
607
608 79 View Code Duplication
        foreach ($diff->renamedColumns as $oldColumnName => $column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
609 12
            if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
610
                continue;
611
            }
612
613 12
            $oldColumnName = new Identifier($oldColumnName);
614 12
            $columnArray = $column->toArray();
615 12
            $columnArray['comment'] = $this->getColumnComment($column);
616 12
            $queryParts[] =  'CHANGE ' . $oldColumnName->getQuotedName($this) . ' '
617 12
                    . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
618
        }
619
620 79
        if (isset($diff->addedIndexes['primary'])) {
621 10
            $keyColumns = array_unique(array_values($diff->addedIndexes['primary']->getColumns()));
622 10
            $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')';
623 10
            unset($diff->addedIndexes['primary']);
624
        }
625
626 79
        $sql = [];
627 79
        $tableSql = [];
628
629 79 View Code Duplication
        if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
630 79
            if (count($queryParts) > 0) {
631 40
                $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts);
632
            }
633 79
            $sql = array_merge(
634 79
                $this->getPreAlterTableIndexForeignKeySQL($diff),
635 79
                $sql,
636 79
                $this->getPostAlterTableIndexForeignKeySQL($diff)
637
            );
638
        }
639
640 79
        return array_merge($sql, $tableSql, $columnSql);
641
    }
642
643
    /**
644
     * {@inheritDoc}
645
     */
646 79
    protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
647
    {
648 79
        $sql = [];
649 79
        $table = $diff->getName($this)->getQuotedName($this);
650
651 79
        foreach ($diff->changedIndexes as $changedIndex) {
652 16
            $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $changedIndex));
653
        }
654
655 79
        foreach ($diff->removedIndexes as $remKey => $remIndex) {
656 9
            $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $remIndex));
657
658 9
            foreach ($diff->addedIndexes as $addKey => $addIndex) {
659 3
                if ($remIndex->getColumns() == $addIndex->getColumns()) {
660
661 3
                    $indexClause = 'INDEX ' . $addIndex->getName();
662
663 3
                    if ($addIndex->isPrimary()) {
664
                        $indexClause = 'PRIMARY KEY';
665 3
                    } elseif ($addIndex->isUnique()) {
666 3
                        $indexClause = 'UNIQUE INDEX ' . $addIndex->getName();
667
                    }
668
669 3
                    $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', ';
670 3
                    $query .= 'ADD ' . $indexClause;
671 3
                    $query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex->getQuotedColumns($this)) . ')';
672
673 3
                    $sql[] = $query;
674
675 3
                    unset($diff->removedIndexes[$remKey]);
676 3
                    unset($diff->addedIndexes[$addKey]);
677
678 9
                    break;
679
                }
680
            }
681
        }
682
683 79
        $engine = 'INNODB';
684
685 79
        if ($diff->fromTable instanceof Table && $diff->fromTable->hasOption('engine')) {
686 3
            $engine = strtoupper(trim($diff->fromTable->getOption('engine')));
687
        }
688
689
        // Suppress foreign key constraint propagation on non-supporting engines.
690 79
        if ('INNODB' !== $engine) {
691 3
            $diff->addedForeignKeys   = [];
692 3
            $diff->changedForeignKeys = [];
693 3
            $diff->removedForeignKeys = [];
694
        }
695
696 79
        $sql = array_merge(
697 79
            $sql,
698 79
            $this->getPreAlterTableAlterIndexForeignKeySQL($diff),
699 79
            parent::getPreAlterTableIndexForeignKeySQL($diff),
700 79
            $this->getPreAlterTableRenameIndexForeignKeySQL($diff)
701
        );
702
703 79
        return $sql;
704
    }
705
706
    /**
707
     * @param TableDiff $diff
708
     * @param Index     $index
709
     *
710
     * @return string[]
711
     */
712 25
    private function getPreAlterTableAlterPrimaryKeySQL(TableDiff $diff, Index $index)
713
    {
714 25
        $sql = [];
715
716 25
        if (! $index->isPrimary() || ! $diff->fromTable instanceof Table) {
717 9
            return $sql;
718
        }
719
720 16
        $tableName = $diff->getName($this)->getQuotedName($this);
721
722
        // Dropping primary keys requires to unset autoincrement attribute on the particular column first.
723 16 View Code Duplication
        foreach ($index->getColumns() as $columnName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
724 16
            if (! $diff->fromTable->hasColumn($columnName)) {
725 3
                continue;
726
            }
727
728 16
            $column = $diff->fromTable->getColumn($columnName);
729
730 16
            if ($column->getAutoincrement() === true) {
731 9
                $column->setAutoincrement(false);
732
733 9
                $sql[] = 'ALTER TABLE ' . $tableName . ' MODIFY ' .
734 9
                    $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
735
736
                // original autoincrement information might be needed later on by other parts of the table alteration
737 16
                $column->setAutoincrement(true);
738
            }
739
        }
740
741 16
        return $sql;
742
    }
743
744
    /**
745
     * @param TableDiff $diff The table diff to gather the SQL for.
746
     *
747
     * @return array
748
     */
749 79
    private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff)
750
    {
751 79
        $sql = [];
752 79
        $table = $diff->getName($this)->getQuotedName($this);
753
754 79
        foreach ($diff->changedIndexes as $changedIndex) {
755
            // Changed primary key
756 16
            if ($changedIndex->isPrimary() && $diff->fromTable instanceof Table) {
757 13 View Code Duplication
                foreach ($diff->fromTable->getPrimaryKeyColumns() as $columnName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
758 13
                    $column = $diff->fromTable->getColumn($columnName);
759
760
                    // Check if an autoincrement column was dropped from the primary key.
761 13
                    if ($column->getAutoincrement() && ! in_array($columnName, $changedIndex->getColumns())) {
762
                        // The autoincrement attribute needs to be removed from the dropped column
763
                        // before we can drop and recreate the primary key.
764 3
                        $column->setAutoincrement(false);
765
766 3
                        $sql[] = 'ALTER TABLE ' . $table . ' MODIFY ' .
767 3
                            $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
768
769
                        // Restore the autoincrement attribute as it might be needed later on
770
                        // by other parts of the table alteration.
771 16
                        $column->setAutoincrement(true);
772
                    }
773
                }
774
            }
775
        }
776
777 79
        return $sql;
778
    }
779
780
    /**
781
     * @param TableDiff $diff The table diff to gather the SQL for.
782
     *
783
     * @return array
784
     */
785 53
    protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff)
786
    {
787 53
        $sql = [];
788 53
        $tableName = $diff->getName($this)->getQuotedName($this);
789
790 53 View Code Duplication
        foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
791 2
            if (! in_array($foreignKey, $diff->changedForeignKeys, true)) {
792 2
                $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
793
            }
794
        }
795
796 53
        return $sql;
797
    }
798
799
    /**
800
     * Returns the remaining foreign key constraints that require one of the renamed indexes.
801
     *
802
     * "Remaining" here refers to the diff between the foreign keys currently defined in the associated
803
     * table and the foreign keys to be removed.
804
     *
805
     * @param TableDiff $diff The table diff to evaluate.
806
     *
807
     * @return array
808
     */
809 53
    private function getRemainingForeignKeyConstraintsRequiringRenamedIndexes(TableDiff $diff)
810
    {
811 53
        if (empty($diff->renamedIndexes) || ! $diff->fromTable instanceof Table) {
812 43
            return [];
813
        }
814
815 10
        $foreignKeys = [];
816
        /** @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] $remainingForeignKeys */
817 10
        $remainingForeignKeys = array_diff_key(
818 10
            $diff->fromTable->getForeignKeys(),
819 10
            $diff->removedForeignKeys
820
        );
821
822 10
        foreach ($remainingForeignKeys as $foreignKey) {
823 2
            foreach ($diff->renamedIndexes as $index) {
824 2
                if ($foreignKey->intersectsIndexColumns($index)) {
825 2
                    $foreignKeys[] = $foreignKey;
826
827 2
                    break;
828
                }
829
            }
830
        }
831
832 10
        return $foreignKeys;
833
    }
834
835
    /**
836
     * {@inheritdoc}
837
     */
838 79
    protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
839
    {
840 79
        return array_merge(
841 79
            parent::getPostAlterTableIndexForeignKeySQL($diff),
842 79
            $this->getPostAlterTableRenameIndexForeignKeySQL($diff)
843
        );
844
    }
845
846
    /**
847
     * @param TableDiff $diff The table diff to gather the SQL for.
848
     *
849
     * @return array
850
     */
851 53
    protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff)
852
    {
853 53
        $sql = [];
854 53
        $tableName = (false !== $diff->newName)
855 4
            ? $diff->getNewName()->getQuotedName($this)
856 53
            : $diff->getName($this)->getQuotedName($this);
857
858 53 View Code Duplication
        foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
859 2
            if (! in_array($foreignKey, $diff->changedForeignKeys, true)) {
860 2
                $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
861
            }
862
        }
863
864 53
        return $sql;
865
    }
866
867
    /**
868
     * {@inheritDoc}
869
     */
870 45 View Code Duplication
    protected function getCreateIndexSQLFlags(Index $index)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
871
    {
872 45
        $type = '';
873 45
        if ($index->isUnique()) {
874 9
            $type .= 'UNIQUE ';
875 36
        } elseif ($index->hasFlag('fulltext')) {
876 3
            $type .= 'FULLTEXT ';
877 33
        } elseif ($index->hasFlag('spatial')) {
878 3
            $type .= 'SPATIAL ';
879
        }
880
881 45
        return $type;
882
    }
883
884
    /**
885
     * {@inheritDoc}
886
     */
887 56
    public function getIntegerTypeDeclarationSQL(array $field)
888
    {
889 56
        return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
890
    }
891
892
    /**
893
     * {@inheritDoc}
894
     */
895
    public function getBigIntTypeDeclarationSQL(array $field)
896
    {
897
        return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
898
    }
899
900
    /**
901
     * {@inheritDoc}
902
     */
903
    public function getSmallIntTypeDeclarationSQL(array $field)
904
    {
905
        return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
906
    }
907
908
    /**
909
     * {@inheritdoc}
910
     */
911 18
    public function getFloatDeclarationSQL(array $field)
912
    {
913 18
        return 'DOUBLE PRECISION' . $this->getUnsignedDeclaration($field);
914
    }
915
916
    /**
917
     * {@inheritdoc}
918
     */
919 18
    public function getDecimalTypeDeclarationSQL(array $columnDef)
920
    {
921 18
        return parent::getDecimalTypeDeclarationSQL($columnDef) . $this->getUnsignedDeclaration($columnDef);
922
    }
923
924
    /**
925
     * Get unsigned declaration for a column.
926
     *
927
     * @param array $columnDef
928
     *
929
     * @return string
930
     */
931 92
    private function getUnsignedDeclaration(array $columnDef)
932
    {
933 92
        return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : '';
934
    }
935
936
    /**
937
     * {@inheritDoc}
938
     */
939 56
    protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
940
    {
941 56
        $autoinc = '';
942 56
        if ( ! empty($columnDef['autoincrement'])) {
943 9
            $autoinc = ' AUTO_INCREMENT';
944
        }
945
946 56
        return $this->getUnsignedDeclaration($columnDef) . $autoinc;
947
    }
948
949
    /**
950
     * {@inheritDoc}
951
     */
952 21
    public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey)
953
    {
954 21
        $query = '';
955 21
        if ($foreignKey->hasOption('match')) {
956
            $query .= ' MATCH ' . $foreignKey->getOption('match');
957
        }
958 21
        $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
959
960 21
        return $query;
961
    }
962
963
    /**
964
     * {@inheritDoc}
965
     */
966 32 View Code Duplication
    public function getDropIndexSQL($index, $table=null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
967
    {
968 32
        if ($index instanceof Index) {
969 22
            $indexName = $index->getQuotedName($this);
970 10
        } elseif (is_string($index)) {
971 10
            $indexName = $index;
972
        } else {
973
            throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
974
        }
975
976 32
        if ($table instanceof Table) {
977
            $table = $table->getQuotedName($this);
978 32
        } elseif (!is_string($table)) {
979
            throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
980
        }
981
982 32
        if ($index instanceof Index && $index->isPrimary()) {
983
            // mysql primary keys are always named "PRIMARY",
984
            // so we cannot use them in statements because of them being keyword.
985 19
            return $this->getDropPrimaryKeySQL($table);
986
        }
987
988 13
        return 'DROP INDEX ' . $indexName . ' ON ' . $table;
989
    }
990
991
    /**
992
     * @param string $table
993
     *
994
     * @return string
995
     */
996 19
    protected function getDropPrimaryKeySQL($table)
997
    {
998 19
        return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
999
    }
1000
1001
    /**
1002
     * {@inheritDoc}
1003
     */
1004 3
    public function getSetTransactionIsolationSQL($level)
1005
    {
1006 3
        return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
1007
    }
1008
1009
    /**
1010
     * {@inheritDoc}
1011
     */
1012 6
    public function getName()
1013
    {
1014 6
        return 'mysql';
1015
    }
1016
1017
    /**
1018
     * {@inheritDoc}
1019
     */
1020
    public function getReadLockSQL()
1021
    {
1022
        return 'LOCK IN SHARE MODE';
1023
    }
1024
1025
    /**
1026
     * {@inheritDoc}
1027
     */
1028 17
    protected function initializeDoctrineTypeMappings()
1029
    {
1030 17
        $this->doctrineTypeMapping = [
1031
            'tinyint'       => 'boolean',
1032
            'smallint'      => 'smallint',
1033
            'mediumint'     => 'integer',
1034
            'int'           => 'integer',
1035
            'integer'       => 'integer',
1036
            'bigint'        => 'bigint',
1037
            'tinytext'      => 'text',
1038
            'mediumtext'    => 'text',
1039
            'longtext'      => 'text',
1040
            'text'          => 'text',
1041
            'varchar'       => 'string',
1042
            'string'        => 'string',
1043
            'char'          => 'string',
1044
            'date'          => 'date',
1045
            'datetime'      => 'datetime',
1046
            'timestamp'     => 'datetime',
1047
            'time'          => 'time',
1048
            'float'         => 'float',
1049
            'double'        => 'float',
1050
            'real'          => 'float',
1051
            'decimal'       => 'decimal',
1052
            'numeric'       => 'decimal',
1053
            'year'          => 'date',
1054
            'longblob'      => 'blob',
1055
            'blob'          => 'blob',
1056
            'mediumblob'    => 'blob',
1057
            'tinyblob'      => 'blob',
1058
            'binary'        => 'binary',
1059
            'varbinary'     => 'binary',
1060
            'set'           => 'simple_array',
1061
        ];
1062 17
    }
1063
1064
    /**
1065
     * {@inheritDoc}
1066
     */
1067 45
    public function getVarcharMaxLength()
1068
    {
1069 45
        return 65535;
1070
    }
1071
1072
    /**
1073
     * {@inheritdoc}
1074
     */
1075 6
    public function getBinaryMaxLength()
1076
    {
1077 6
        return 65535;
1078
    }
1079
1080
    /**
1081
     * {@inheritDoc}
1082
     */
1083 62
    protected function getReservedKeywordsClass()
1084
    {
1085 62
        return Keywords\MySQLKeywords::class;
1086
    }
1087
1088
    /**
1089
     * {@inheritDoc}
1090
     *
1091
     * MySQL commits a transaction implicitly when DROP TABLE is executed, however not
1092
     * if DROP TEMPORARY TABLE is executed.
1093
     */
1094 View Code Duplication
    public function getDropTemporaryTableSQL($table)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1095
    {
1096
        if ($table instanceof Table) {
1097
            $table = $table->getQuotedName($this);
1098
        } elseif (!is_string($table)) {
1099
            throw new \InvalidArgumentException('getDropTemporaryTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
1100
        }
1101
1102
        return 'DROP TEMPORARY TABLE ' . $table;
1103
    }
1104
1105
    /**
1106
     * Gets the SQL Snippet used to declare a BLOB column type.
1107
     *     TINYBLOB   : 2 ^  8 - 1 = 255
1108
     *     BLOB       : 2 ^ 16 - 1 = 65535
1109
     *     MEDIUMBLOB : 2 ^ 24 - 1 = 16777215
1110
     *     LONGBLOB   : 2 ^ 32 - 1 = 4294967295
1111
     *
1112
     * @param array $field
1113
     *
1114
     * @return string
1115
     */
1116 9 View Code Duplication
    public function getBlobTypeDeclarationSQL(array $field)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1117
    {
1118 9
        if ( ! empty($field['length']) && is_numeric($field['length'])) {
1119 6
            $length = $field['length'];
1120
1121 6
            if ($length <= static::LENGTH_LIMIT_TINYBLOB) {
1122 3
                return 'TINYBLOB';
1123
            }
1124
1125 6
            if ($length <= static::LENGTH_LIMIT_BLOB) {
1126 3
                return 'BLOB';
1127
            }
1128
1129 6
            if ($length <= static::LENGTH_LIMIT_MEDIUMBLOB) {
1130 6
                return 'MEDIUMBLOB';
1131
            }
1132
        }
1133
1134 9
        return 'LONGBLOB';
1135
    }
1136
1137
    /**
1138
     * {@inheritdoc}
1139
     */
1140 80
    public function quoteStringLiteral($str)
1141
    {
1142 80
        $str = str_replace('\\', '\\\\', $str); // MySQL requires backslashes to be escaped aswell.
1143
1144 80
        return parent::quoteStringLiteral($str);
1145
    }
1146
1147
    /**
1148
     * {@inheritdoc}
1149
     */
1150 1
    public function getDefaultTransactionIsolationLevel()
1151
    {
1152 1
        return Connection::TRANSACTION_REPEATABLE_READ;
1153
    }
1154
}
1155