AbstractPlatformTestCase   F
last analyzed

Complexity

Total Complexity 133

Size/Duplication

Total Lines 1596
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 642
dl 0
loc 1596
rs 1.958
c 0
b 0
f 0
wmc 133

119 Methods

Rating   Name   Duplication   Size   Complexity  
A testQuotedNameInIndexSQL() 0 8 1
A supportsInlineIndexDeclaration() 0 3 1
A supportsCommentOnStatement() 0 3 1
A testSupportsCommentOnStatement() 0 3 1
A testQuotedColumnInPrimaryKeyPropagation() 0 8 1
A testGetCreateSchemaSQL() 0 5 1
A testQuotesReservedKeywordInIndexDeclarationSQL() 0 11 2
A testQuotesReservedKeywordInUniqueConstraintDeclarationSQL() 0 7 1
A testQuotedColumnInForeignKeyPropagation() 0 33 1
A testQuotedColumnInIndexPropagation() 0 8 1
A testQuotesReservedKeywordInTruncateTableSQL() 0 5 1
A getReturnsForeignKeyReferentialActionSQL() 0 9 1
A testReturnsForeignKeyReferentialActionSQL() 0 3 1
A testGeneratesIndexCreationSql() 0 7 1
A testGeneratesForeignKeyCreationSql() 0 6 1
A getIsCommentedDoctrineType() 0 16 2
A testGeneratesPartialIndexesSqlOnlyWhenSupportingPartialIndexes() 0 22 3
A testRegisterDoctrineMappingType() 0 4 1
A testCreateWithNoColumns() 0 6 1
A testGeneratesTableCreationSql() 0 9 1
A testIsCommentedDoctrineType() 0 3 1
A testGenerateTableWithMultiColumnUniqueIndex() 0 9 1
A setUp() 0 3 1
A testRegisterUnknownDoctrineMappingType() 0 4 1
A testGetUnknownDoctrineMappingType() 0 4 1
A testQuoteSingleIdentifier() 0 10 2
A testGeneratesUniqueIndexCreationSql() 0 6 1
A testRegistersCommentedDoctrineMappingTypeImplicitly() 0 6 1
A testGetInvalidForeignKeyReferentialActionSQL() 0 4 1
A testQuoteIdentifier() 0 10 2
A testGeneratesFloatDeclarationSQL() 0 3 1
A testQuotesTableIdentifiersInAlterTableSQL() 0 31 1
A testGetVariableLengthStringTypeDeclarationSQLWithLength() 0 5 1
A getInlineColumnCommentRequiringEscapingSQL() 0 3 1
A testAlterTableRenameIndex() 0 13 1
A testUsesSequenceEmulatedIdentityColumns() 0 3 1
A testGetFixedLengthStringTypeDeclarationSQLWithLength() 0 7 1
A getGenerateConstraintForeignKeySql() 0 7 1
A testKeywordList() 0 5 1
A testAlterTableRenameIndexInSchema() 0 13 1
A getInlineColumnCommentDelimiter() 0 3 1
A testGetDropTableSqlDispatchEvent() 0 15 1
A testQuotesAlterTableRenameColumn() 0 39 1
A testQuotesAlterTableChangeColumnLength() 0 31 1
A getExpectedFixedLengthStringTypeDeclarationSQLWithLength() 0 3 1
A testQuoteStringLiteral() 0 15 1
A testQuotesDropForeignKeySQL() 0 16 2
A testReturnsIdentitySequenceName() 0 5 1
A getGenerateConstraintUniqueIndexSql() 0 3 1
A testReturnsGuidTypeDeclarationSQL() 0 5 1
A testGetCommentOnColumnSQL() 0 8 1
A getGenerateConstraintPrimaryIndexSql() 0 3 1
A testGetStringLiteralQuoteCharacter() 0 3 1
A getCreateTableColumnTypeCommentsSQL() 0 3 1
A getInlineColumnRegularCommentSQL() 0 3 1
A getQuotedAlterTableRenameIndexSQL() 0 7 1
A getExpectedFixedLengthStringTypeDeclarationSQLNoLength() 0 3 1
A testGetCommentOnColumnSQLWithoutQuoteCharacter() 0 5 1
A getQuotedAlterTableRenameIndexInSchemaSQL() 0 7 1
A testAlterTableColumnComments() 0 19 1
A getBitAndComparisonExpressionSql() 0 3 1
A testGetCustomColumnDeclarationSql() 0 4 1
A getQuotesDropForeignKeySQL() 0 3 1
A testQuotesDropConstraintSQL() 0 10 1
A getQuotedStringLiteralQuoteCharacter() 0 3 1
A testGetDefaultValueDeclarationSQLForIntegerTypes() 0 11 2
A getStringLiteralQuoteCharacter() 0 3 1
A getGeneratesInlineColumnCommentSQL() 0 12 1
A testItEscapesStringsForLike() 0 5 1
A testQuotesAlterTableRenameIndexInSchema() 0 14 1
A testGetVariableLengthBinaryTypeDeclarationSQLNoLength() 0 5 1
A testGeneratesBitOrComparisonExpressionSql() 0 4 1
A testGetFixedLengthBinaryTypeDeclarationSQLWithLength() 0 7 1
A getExpectedVariableLengthStringTypeDeclarationSQLNoLength() 0 3 1
A testGeneratesBitAndComparisonExpressionSql() 0 4 1
A getQuotedStringLiteralWithQuoteCharacter() 0 3 1
A testGeneratesForeignKeySqlOnlyWhenSupportingForeignKeys() 0 10 2
A testGetCommentOnColumnSQLWithQuoteCharacter() 0 7 1
A testGeneratesConstraintCreationSql() 0 17 2
A getInlineColumnEmptyCommentSQL() 0 3 1
A getExpectedFixedLengthBinaryTypeDeclarationSQLWithLength() 0 3 1
A testGetDefaultValueDeclarationSQL() 0 9 1
A getBitOrComparisonExpressionSql() 0 3 1
A getExpectedVariableLengthBinaryTypeDeclarationSQLNoLength() 0 3 1
A testCreateTableColumnComments() 0 7 1
A getGeneratesFloatDeclarationSQL() 0 9 1
A getQuotesDropConstraintSQL() 0 3 1
A testGetDefaultValueDeclarationSQLDateTime() 0 12 2
A testGetVariableLengthBinaryTypeDeclarationSQLWithLength() 0 5 1
A testGetVariableLengthStringTypeDeclarationSQLNoLength() 0 5 1
A testGetAlterTableSqlDispatchEvent() 0 57 1
A testReturnsJsonTypeDeclarationSQL() 0 11 1
A testThrowsExceptionOnGeneratingInlineColumnCommentSQLIfUnsupported() 0 11 2
A testGeneratesTableAlterationSql() 0 42 1
A getAlterTableColumnCommentsSQL() 0 3 1
A getQuotedCommentOnColumnSQLWithQuoteCharacter() 0 3 1
A testGetCreateTableSqlDispatchEvent() 0 22 1
A getQuotedStringLiteralWithoutQuoteCharacter() 0 3 1
A testZeroOffsetWithoutLimitIsIgnored() 0 7 1
A testAlterStringToFixedString() 0 23 1
A getExpectedVariableLengthStringTypeDeclarationSQLWithLength() 0 3 1
A getAlterTableRenameIndexSQL() 0 5 1
A testGeneratesDecimalTypeDeclarationSQL() 0 3 1
A testGeneratesAlterTableRenameColumnSQL() 0 18 1
A getExpectedVariableLengthBinaryTypeDeclarationSQLWithLength() 0 3 1
A getQuotedCommentOnColumnSQLWithoutQuoteCharacter() 0 3 1
A hasNativeJsonType() 0 3 1
A getAlterTableRenameIndexInSchemaSQL() 0 5 1
A testAlterTableChangeQuotedColumn() 0 17 1
A getExpectedFixedLengthBinaryTypeDeclarationSQLNoLength() 0 3 1
A testGetFixedLengthStringTypeDeclarationSQLNoLength() 0 5 1
A testGetDefaultValueDeclarationSQLForDateType() 0 12 2
A getCreateTableColumnCommentsSQL() 0 3 1
A getGeneratesDecimalTypeDeclarationSQL() 0 9 1
A testQuotesAlterTableRenameIndex() 0 14 1
A testGeneratesAlterTableRenameIndexUsedByForeignKeySQL() 0 22 1
A testGeneratesInlineColumnCommentSQL() 0 7 2
A testGetFixedLengthBinaryTypeDeclarationSQLNoLength() 0 5 1
A testCreateTableColumnTypeComments() 0 8 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractPlatformTestCase 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 AbstractPlatformTestCase, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Tests\Platforms;
6
7
use Doctrine\Common\EventManager;
8
use Doctrine\DBAL\DBALException;
9
use Doctrine\DBAL\Events;
10
use Doctrine\DBAL\Platforms\AbstractPlatform;
11
use Doctrine\DBAL\Schema\Column;
12
use Doctrine\DBAL\Schema\ColumnDiff;
13
use Doctrine\DBAL\Schema\Comparator;
14
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
15
use Doctrine\DBAL\Schema\Index;
16
use Doctrine\DBAL\Schema\Table;
17
use Doctrine\DBAL\Schema\TableDiff;
18
use Doctrine\DBAL\Schema\UniqueConstraint;
19
use Doctrine\DBAL\Types\Type;
20
use PHPUnit\Framework\TestCase;
21
use function get_class;
22
use function implode;
23
use function sprintf;
24
use function str_repeat;
25
26
abstract class AbstractPlatformTestCase extends TestCase
27
{
28
    /** @var AbstractPlatform */
29
    protected $platform;
30
31
    abstract public function createPlatform() : AbstractPlatform;
32
33
    protected function setUp() : void
34
    {
35
        $this->platform = $this->createPlatform();
36
    }
37
38
    /**
39
     * @group DDC-1360
40
     */
41
    public function testQuoteIdentifier() : void
42
    {
43
        if ($this->platform->getName() === 'mssql') {
44
            self::markTestSkipped('Not working this way on mssql.');
45
        }
46
47
        $c = $this->platform->getIdentifierQuoteCharacter();
48
        self::assertEquals($c . 'test' . $c, $this->platform->quoteIdentifier('test'));
49
        self::assertEquals($c . 'test' . $c . '.' . $c . 'test' . $c, $this->platform->quoteIdentifier('test.test'));
50
        self::assertEquals(str_repeat($c, 4), $this->platform->quoteIdentifier($c));
51
    }
52
53
    /**
54
     * @group DDC-1360
55
     */
56
    public function testQuoteSingleIdentifier() : void
57
    {
58
        if ($this->platform->getName() === 'mssql') {
59
            self::markTestSkipped('Not working this way on mssql.');
60
        }
61
62
        $c = $this->platform->getIdentifierQuoteCharacter();
63
        self::assertEquals($c . 'test' . $c, $this->platform->quoteSingleIdentifier('test'));
64
        self::assertEquals($c . 'test.test' . $c, $this->platform->quoteSingleIdentifier('test.test'));
65
        self::assertEquals(str_repeat($c, 4), $this->platform->quoteSingleIdentifier($c));
66
    }
67
68
    /**
69
     * @group DBAL-1029
70
     * @dataProvider getReturnsForeignKeyReferentialActionSQL
71
     */
72
    public function testReturnsForeignKeyReferentialActionSQL(string $action, string $expectedSQL) : void
73
    {
74
        self::assertSame($expectedSQL, $this->platform->getForeignKeyReferentialActionSQL($action));
75
    }
76
77
    /**
78
     * @return mixed[][]
79
     */
80
    public static function getReturnsForeignKeyReferentialActionSQL() : iterable
81
    {
82
        return [
83
            ['CASCADE', 'CASCADE'],
84
            ['SET NULL', 'SET NULL'],
85
            ['NO ACTION', 'NO ACTION'],
86
            ['RESTRICT', 'RESTRICT'],
87
            ['SET DEFAULT', 'SET DEFAULT'],
88
            ['CaScAdE', 'CASCADE'],
89
        ];
90
    }
91
92
    public function testGetInvalidForeignKeyReferentialActionSQL() : void
93
    {
94
        $this->expectException('InvalidArgumentException');
95
        $this->platform->getForeignKeyReferentialActionSQL('unknown');
96
    }
97
98
    public function testGetUnknownDoctrineMappingType() : void
99
    {
100
        $this->expectException(DBALException::class);
101
        $this->platform->getDoctrineTypeMapping('foobar');
102
    }
103
104
    public function testRegisterDoctrineMappingType() : void
105
    {
106
        $this->platform->registerDoctrineTypeMapping('foo', 'integer');
107
        self::assertEquals('integer', $this->platform->getDoctrineTypeMapping('foo'));
108
    }
109
110
    public function testRegisterUnknownDoctrineMappingType() : void
111
    {
112
        $this->expectException(DBALException::class);
113
        $this->platform->registerDoctrineTypeMapping('foo', 'bar');
114
    }
115
116
    /**
117
     * @group DBAL-2594
118
     */
119
    public function testRegistersCommentedDoctrineMappingTypeImplicitly() : void
120
    {
121
        $type = Type::getType('array');
122
        $this->platform->registerDoctrineTypeMapping('foo', 'array');
123
124
        self::assertTrue($this->platform->isCommentedDoctrineType($type));
125
    }
126
127
    /**
128
     * @group DBAL-939
129
     * @dataProvider getIsCommentedDoctrineType
130
     */
131
    public function testIsCommentedDoctrineType(Type $type, bool $commented) : void
132
    {
133
        self::assertSame($commented, $this->platform->isCommentedDoctrineType($type));
134
    }
135
136
    /**
137
     * @return mixed[]
138
     */
139
    public function getIsCommentedDoctrineType() : iterable
140
    {
141
        $this->setUp();
142
143
        $data = [];
144
145
        foreach (Type::getTypesMap() as $typeName => $className) {
146
            $type = Type::getType($typeName);
147
148
            $data[$typeName] = [
149
                $type,
150
                $type->requiresSQLCommentHint($this->platform),
151
            ];
152
        }
153
154
        return $data;
155
    }
156
157
    public function testCreateWithNoColumns() : void
158
    {
159
        $table = new Table('test');
160
161
        $this->expectException(DBALException::class);
162
        $this->platform->getCreateTableSQL($table);
163
    }
164
165
    public function testGeneratesTableCreationSql() : void
166
    {
167
        $table = new Table('test');
168
        $table->addColumn('id', 'integer', ['notnull' => true, 'autoincrement' => true]);
169
        $table->addColumn('test', 'string', ['notnull' => false, 'length' => 255]);
170
        $table->setPrimaryKey(['id']);
171
172
        $sql = $this->platform->getCreateTableSQL($table);
173
        self::assertEquals($this->getGenerateTableSql(), $sql[0]);
174
    }
175
176
    abstract public function getGenerateTableSql() : string;
177
178
    public function testGenerateTableWithMultiColumnUniqueIndex() : void
179
    {
180
        $table = new Table('test');
181
        $table->addColumn('foo', 'string', ['notnull' => false, 'length' => 255]);
182
        $table->addColumn('bar', 'string', ['notnull' => false, 'length' => 255]);
183
        $table->addUniqueIndex(['foo', 'bar']);
184
185
        $sql = $this->platform->getCreateTableSQL($table);
186
        self::assertEquals($this->getGenerateTableWithMultiColumnUniqueIndexSql(), $sql);
187
    }
188
189
    /**
190
     * @return string[]
191
     */
192
    abstract public function getGenerateTableWithMultiColumnUniqueIndexSql() : array;
193
194
    public function testGeneratesIndexCreationSql() : void
195
    {
196
        $indexDef = new Index('my_idx', ['user_name', 'last_login']);
197
198
        self::assertEquals(
199
            $this->getGenerateIndexSql(),
200
            $this->platform->getCreateIndexSQL($indexDef, 'mytable')
201
        );
202
    }
203
204
    abstract public function getGenerateIndexSql() : string;
205
206
    public function testGeneratesUniqueIndexCreationSql() : void
207
    {
208
        $indexDef = new Index('index_name', ['test', 'test2'], true);
209
210
        $sql = $this->platform->getCreateIndexSQL($indexDef, 'test');
211
        self::assertEquals($this->getGenerateUniqueIndexSql(), $sql);
212
    }
213
214
    abstract public function getGenerateUniqueIndexSql() : string;
215
216
    public function testGeneratesPartialIndexesSqlOnlyWhenSupportingPartialIndexes() : void
217
    {
218
        $where            = 'test IS NULL AND test2 IS NOT NULL';
219
        $indexDef         = new Index('name', ['test', 'test2'], false, false, [], ['where' => $where]);
220
        $uniqueConstraint = new UniqueConstraint('name', ['test', 'test2'], [], []);
221
222
        $expected = ' WHERE ' . $where;
223
224
        $actuals = [];
225
226
        if ($this->supportsInlineIndexDeclaration()) {
227
            $actuals[] = $this->platform->getIndexDeclarationSQL('name', $indexDef);
228
        }
229
230
        $uniqueConstraintSQL = $this->platform->getUniqueConstraintDeclarationSQL('name', $uniqueConstraint);
231
        $indexSQL            = $this->platform->getCreateIndexSQL($indexDef, 'table');
232
233
        self::assertStringEndsNotWith($expected, $uniqueConstraintSQL, 'WHERE clause should NOT be present');
234
        if ($this->platform->supportsPartialIndexes()) {
235
            self::assertStringEndsWith($expected, $indexSQL, 'WHERE clause should be present');
236
        } else {
237
            self::assertStringEndsNotWith($expected, $indexSQL, 'WHERE clause should NOT be present');
238
        }
239
    }
240
241
    public function testGeneratesForeignKeyCreationSql() : void
242
    {
243
        $fk = new ForeignKeyConstraint(['fk_name_id'], 'other_table', ['id']);
244
245
        $sql = $this->platform->getCreateForeignKeySQL($fk, 'test');
246
        self::assertEquals($this->getGenerateForeignKeySql(), $sql);
247
    }
248
249
    abstract public function getGenerateForeignKeySql() : string;
250
251
    public function testGeneratesConstraintCreationSql() : void
252
    {
253
        if (! $this->platform->supportsCreateDropForeignKeyConstraints()) {
254
            self::markTestSkipped('Platform does not support creating or dropping foreign key constraints.');
255
        }
256
257
        $idx = new Index('constraint_name', ['test'], true, false);
258
        $sql = $this->platform->getCreateConstraintSQL($idx, 'test');
259
        self::assertEquals($this->getGenerateConstraintUniqueIndexSql(), $sql);
260
261
        $pk  = new Index('constraint_name', ['test'], true, true);
262
        $sql = $this->platform->getCreateConstraintSQL($pk, 'test');
263
        self::assertEquals($this->getGenerateConstraintPrimaryIndexSql(), $sql);
264
265
        $fk  = new ForeignKeyConstraint(['fk_name'], 'foreign', ['id'], 'constraint_fk');
266
        $sql = $this->platform->getCreateConstraintSQL($fk, 'test');
267
        self::assertEquals($this->getGenerateConstraintForeignKeySql($fk), $sql);
268
    }
269
270
    public function testGeneratesForeignKeySqlOnlyWhenSupportingForeignKeys() : void
271
    {
272
        if ($this->platform->supportsForeignKeyConstraints()) {
273
            self::markTestSkipped('The platform supports foreign key constraints');
274
        }
275
276
        $this->expectException(DBALException::class);
277
        $this->platform->getCreateForeignKeySQL(
278
            new ForeignKeyConstraint(['fk_name'], 'foreign', ['id'], 'constraint_fk'),
279
            'test'
280
        );
281
    }
282
283
    protected function getBitAndComparisonExpressionSql(string $value1, string $value2) : string
284
    {
285
        return '(' . $value1 . ' & ' . $value2 . ')';
286
    }
287
288
    /**
289
     * @group DDC-1213
290
     */
291
    public function testGeneratesBitAndComparisonExpressionSql() : void
292
    {
293
        $sql = $this->platform->getBitAndComparisonExpression('2', '4');
294
        self::assertEquals($this->getBitAndComparisonExpressionSql('2', '4'), $sql);
295
    }
296
297
    protected function getBitOrComparisonExpressionSql(string $value1, string $value2) : string
298
    {
299
        return '(' . $value1 . ' | ' . $value2 . ')';
300
    }
301
302
    /**
303
     * @group DDC-1213
304
     */
305
    public function testGeneratesBitOrComparisonExpressionSql() : void
306
    {
307
        $sql = $this->platform->getBitOrComparisonExpression('2', '4');
308
        self::assertEquals($this->getBitOrComparisonExpressionSql('2', '4'), $sql);
309
    }
310
311
    public function getGenerateConstraintUniqueIndexSql() : string
312
    {
313
        return 'ALTER TABLE test ADD CONSTRAINT constraint_name UNIQUE (test)';
314
    }
315
316
    public function getGenerateConstraintPrimaryIndexSql() : string
317
    {
318
        return 'ALTER TABLE test ADD CONSTRAINT constraint_name PRIMARY KEY (test)';
319
    }
320
321
    public function getGenerateConstraintForeignKeySql(ForeignKeyConstraint $fk) : string
322
    {
323
        $quotedForeignTable = $fk->getQuotedForeignTableName($this->platform);
324
325
        return sprintf(
326
            'ALTER TABLE test ADD CONSTRAINT constraint_fk FOREIGN KEY (fk_name) REFERENCES %s (id)',
327
            $quotedForeignTable
328
        );
329
    }
330
331
    /**
332
     * @return string[]
333
     */
334
    abstract public function getGenerateAlterTableSql() : array;
335
336
    public function testGeneratesTableAlterationSql() : void
337
    {
338
        $expectedSql = $this->getGenerateAlterTableSql();
339
340
        $table = new Table('mytable');
341
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
342
        $table->addColumn('foo', 'integer');
343
        $table->addColumn('bar', 'string');
344
        $table->addColumn('bloo', 'boolean');
345
        $table->setPrimaryKey(['id']);
346
347
        $tableDiff                        = new TableDiff('mytable');
348
        $tableDiff->fromTable             = $table;
349
        $tableDiff->newName               = 'userlist';
350
        $tableDiff->addedColumns['quota'] = new Column('quota', Type::getType('integer'), ['notnull' => false]);
351
        $tableDiff->removedColumns['foo'] = new Column('foo', Type::getType('integer'));
352
        $tableDiff->changedColumns['bar'] = new ColumnDiff(
353
            'bar',
354
            new Column(
355
                'baz',
356
                Type::getType('string'),
357
                [
358
                    'length' => 255,
359
                    'default' => 'def',
360
                ]
361
            ),
362
            ['type', 'notnull', 'default']
363
        );
364
365
        $tableDiff->changedColumns['bloo'] = new ColumnDiff(
366
            'bloo',
367
            new Column(
368
                'bloo',
369
                Type::getType('boolean'),
370
                ['default' => false]
371
            ),
372
            ['type', 'notnull', 'default']
373
        );
374
375
        $sql = $this->platform->getAlterTableSQL($tableDiff);
376
377
        self::assertEquals($expectedSql, $sql);
378
    }
379
380
    public function testGetCustomColumnDeclarationSql() : void
381
    {
382
        $field = ['columnDefinition' => 'MEDIUMINT(6) UNSIGNED'];
383
        self::assertEquals('foo MEDIUMINT(6) UNSIGNED', $this->platform->getColumnDeclarationSQL('foo', $field));
384
    }
385
386
    public function testGetCreateTableSqlDispatchEvent() : void
387
    {
388
        $listenerMock = $this->getMockBuilder($this->getMockClass('GetCreateTableSqlDispatchEvenListener'))
389
            ->addMethods(['onSchemaCreateTable', 'onSchemaCreateTableColumn'])
390
            ->getMock();
391
        $listenerMock
392
            ->expects(self::once())
393
            ->method('onSchemaCreateTable');
394
        $listenerMock
395
            ->expects(self::exactly(2))
396
            ->method('onSchemaCreateTableColumn');
397
398
        $eventManager = new EventManager();
399
        $eventManager->addEventListener([Events::onSchemaCreateTable, Events::onSchemaCreateTableColumn], $listenerMock);
400
401
        $this->platform->setEventManager($eventManager);
402
403
        $table = new Table('test');
404
        $table->addColumn('foo', 'string', ['notnull' => false, 'length' => 255]);
405
        $table->addColumn('bar', 'string', ['notnull' => false, 'length' => 255]);
406
407
        $this->platform->getCreateTableSQL($table);
408
    }
409
410
    public function testGetDropTableSqlDispatchEvent() : void
411
    {
412
        $listenerMock = $this->getMockBuilder($this->getMockClass('GetDropTableSqlDispatchEventListener'))
413
            ->addMethods(['onSchemaDropTable'])
414
            ->getMock();
415
        $listenerMock
416
            ->expects(self::once())
417
            ->method('onSchemaDropTable');
418
419
        $eventManager = new EventManager();
420
        $eventManager->addEventListener([Events::onSchemaDropTable], $listenerMock);
421
422
        $this->platform->setEventManager($eventManager);
423
424
        $this->platform->getDropTableSQL('TABLE');
425
    }
426
427
    public function testGetAlterTableSqlDispatchEvent() : void
428
    {
429
        $events = [
430
            'onSchemaAlterTable',
431
            'onSchemaAlterTableAddColumn',
432
            'onSchemaAlterTableRemoveColumn',
433
            'onSchemaAlterTableChangeColumn',
434
            'onSchemaAlterTableRenameColumn',
435
        ];
436
437
        $listenerMock = $this->getMockBuilder($this->getMockClass('GetAlterTableSqlDispatchEvenListener'))
438
            ->addMethods($events)
439
            ->getMock();
440
        $listenerMock
441
            ->expects(self::once())
442
            ->method('onSchemaAlterTable');
443
        $listenerMock
444
            ->expects(self::once())
445
            ->method('onSchemaAlterTableAddColumn');
446
        $listenerMock
447
            ->expects(self::once())
448
            ->method('onSchemaAlterTableRemoveColumn');
449
        $listenerMock
450
            ->expects(self::once())
451
            ->method('onSchemaAlterTableChangeColumn');
452
        $listenerMock
453
            ->expects(self::once())
454
            ->method('onSchemaAlterTableRenameColumn');
455
456
        $eventManager = new EventManager();
457
        $events       = [
458
            Events::onSchemaAlterTable,
459
            Events::onSchemaAlterTableAddColumn,
460
            Events::onSchemaAlterTableRemoveColumn,
461
            Events::onSchemaAlterTableChangeColumn,
462
            Events::onSchemaAlterTableRenameColumn,
463
        ];
464
        $eventManager->addEventListener($events, $listenerMock);
465
466
        $this->platform->setEventManager($eventManager);
467
468
        $table = new Table('mytable');
469
        $table->addColumn('removed', 'integer');
470
        $table->addColumn('changed', 'integer');
471
        $table->addColumn('renamed', 'integer');
472
473
        $tableDiff                            = new TableDiff('mytable');
474
        $tableDiff->fromTable                 = $table;
475
        $tableDiff->addedColumns['added']     = new Column('added', Type::getType('integer'), []);
476
        $tableDiff->removedColumns['removed'] = new Column('removed', Type::getType('integer'), []);
477
        $tableDiff->changedColumns['changed'] = new ColumnDiff(
478
            'changed',
479
            new Column('changed2', Type::getType('string'), ['length' => 255])
480
        );
481
        $tableDiff->renamedColumns['renamed'] = new Column('renamed2', Type::getType('integer'));
482
483
        $this->platform->getAlterTableSQL($tableDiff);
484
    }
485
486
    /**
487
     * @group DBAL-42
488
     */
489
    public function testCreateTableColumnComments() : void
490
    {
491
        $table = new Table('test');
492
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
493
        $table->setPrimaryKey(['id']);
494
495
        self::assertEquals($this->getCreateTableColumnCommentsSQL(), $this->platform->getCreateTableSQL($table));
496
    }
497
498
    /**
499
     * @group DBAL-42
500
     */
501
    public function testAlterTableColumnComments() : void
502
    {
503
        $tableDiff                        = new TableDiff('mytable');
504
        $tableDiff->addedColumns['quota'] = new Column('quota', Type::getType('integer'), ['comment' => 'A comment']);
505
        $tableDiff->changedColumns['foo'] = new ColumnDiff(
506
            'foo',
507
            new Column('foo', Type::getType('string'), ['length' => 255]),
508
            ['comment']
509
        );
510
        $tableDiff->changedColumns['bar'] = new ColumnDiff(
511
            'bar',
512
            new Column('baz', Type::getType('string'), [
513
                'length'  => 255,
514
                'comment' => 'B comment',
515
            ]),
516
            ['comment']
517
        );
518
519
        self::assertEquals($this->getAlterTableColumnCommentsSQL(), $this->platform->getAlterTableSQL($tableDiff));
520
    }
521
522
    public function testCreateTableColumnTypeComments() : void
523
    {
524
        $table = new Table('test');
525
        $table->addColumn('id', 'integer');
526
        $table->addColumn('data', 'array');
527
        $table->setPrimaryKey(['id']);
528
529
        self::assertEquals($this->getCreateTableColumnTypeCommentsSQL(), $this->platform->getCreateTableSQL($table));
530
    }
531
532
    /**
533
     * @return string[]
534
     */
535
    public function getCreateTableColumnCommentsSQL() : array
536
    {
537
        self::markTestSkipped('Platform does not support Column comments.');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
538
    }
539
540
    /**
541
     * @return string[]
542
     */
543
    public function getAlterTableColumnCommentsSQL() : array
544
    {
545
        self::markTestSkipped('Platform does not support Column comments.');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
546
    }
547
548
    /**
549
     * @return string[]
550
     */
551
    public function getCreateTableColumnTypeCommentsSQL() : array
552
    {
553
        self::markTestSkipped('Platform does not support Column comments.');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
554
    }
555
556
    public function testGetDefaultValueDeclarationSQL() : void
557
    {
558
        // non-timestamp value will get single quotes
559
        $field = [
560
            'type' => Type::getType('string'),
561
            'default' => 'non_timestamp',
562
        ];
563
564
        self::assertEquals(" DEFAULT 'non_timestamp'", $this->platform->getDefaultValueDeclarationSQL($field));
565
    }
566
567
    /**
568
     * @group 2859
569
     */
570
    public function testGetDefaultValueDeclarationSQLDateTime() : void
571
    {
572
        // timestamps on datetime types should not be quoted
573
        foreach (['datetime', 'datetimetz', 'datetime_immutable', 'datetimetz_immutable'] as $type) {
574
            $field = [
575
                'type'    => Type::getType($type),
576
                'default' => $this->platform->getCurrentTimestampSQL(),
577
            ];
578
579
            self::assertSame(
580
                ' DEFAULT ' . $this->platform->getCurrentTimestampSQL(),
581
                $this->platform->getDefaultValueDeclarationSQL($field)
582
            );
583
        }
584
    }
585
586
    public function testGetDefaultValueDeclarationSQLForIntegerTypes() : void
587
    {
588
        foreach (['bigint', 'integer', 'smallint'] as $type) {
589
            $field = [
590
                'type'    => Type::getType($type),
591
                'default' => 1,
592
            ];
593
594
            self::assertEquals(
595
                ' DEFAULT 1',
596
                $this->platform->getDefaultValueDeclarationSQL($field)
597
            );
598
        }
599
    }
600
601
    /**
602
     * @group 2859
603
     */
604
    public function testGetDefaultValueDeclarationSQLForDateType() : void
605
    {
606
        $currentDateSql = $this->platform->getCurrentDateSQL();
607
        foreach (['date', 'date_immutable'] as $type) {
608
            $field = [
609
                'type'    => Type::getType($type),
610
                'default' => $currentDateSql,
611
            ];
612
613
            self::assertSame(
614
                ' DEFAULT ' . $currentDateSql,
615
                $this->platform->getDefaultValueDeclarationSQL($field)
616
            );
617
        }
618
    }
619
620
    /**
621
     * @group DBAL-45
622
     */
623
    public function testKeywordList() : void
624
    {
625
        $keywordList = $this->platform->getReservedKeywordsList();
626
627
        self::assertTrue($keywordList->isKeyword('table'));
628
    }
629
630
    /**
631
     * @group DBAL-374
632
     */
633
    public function testQuotedColumnInPrimaryKeyPropagation() : void
634
    {
635
        $table = new Table('`quoted`');
636
        $table->addColumn('create', 'string', ['length' => 255]);
637
        $table->setPrimaryKey(['create']);
638
639
        $sql = $this->platform->getCreateTableSQL($table);
640
        self::assertEquals($this->getQuotedColumnInPrimaryKeySQL(), $sql);
641
    }
642
643
    /**
644
     * @return string[]
645
     */
646
    abstract protected function getQuotedColumnInPrimaryKeySQL() : array;
647
648
    /**
649
     * @return string[]
650
     */
651
    abstract protected function getQuotedColumnInIndexSQL() : array;
652
653
    /**
654
     * @return string[]
655
     */
656
    abstract protected function getQuotedNameInIndexSQL() : array;
657
658
    /**
659
     * @return string[]
660
     */
661
    abstract protected function getQuotedColumnInForeignKeySQL() : array;
662
663
    /**
664
     * @group DBAL-374
665
     */
666
    public function testQuotedColumnInIndexPropagation() : void
667
    {
668
        $table = new Table('`quoted`');
669
        $table->addColumn('create', 'string', ['length' => 255]);
670
        $table->addIndex(['create']);
671
672
        $sql = $this->platform->getCreateTableSQL($table);
673
        self::assertEquals($this->getQuotedColumnInIndexSQL(), $sql);
674
    }
675
676
    public function testQuotedNameInIndexSQL() : void
677
    {
678
        $table = new Table('test');
679
        $table->addColumn('column1', 'string', ['length' => 255]);
680
        $table->addIndex(['column1'], '`key`');
681
682
        $sql = $this->platform->getCreateTableSQL($table);
683
        self::assertEquals($this->getQuotedNameInIndexSQL(), $sql);
684
    }
685
686
    /**
687
     * @group DBAL-374
688
     */
689
    public function testQuotedColumnInForeignKeyPropagation() : void
690
    {
691
        $table = new Table('`quoted`');
692
        $table->addColumn('create', 'string', ['length' => 255]);
693
        $table->addColumn('foo', 'string', ['length' => 255]);
694
        $table->addColumn('`bar`', 'string', ['length' => 255]);
695
696
        // Foreign table with reserved keyword as name (needs quotation).
697
        $foreignTable = new Table('foreign');
698
        $foreignTable->addColumn('create', 'string');    // Foreign column with reserved keyword as name (needs quotation).
699
        $foreignTable->addColumn('bar', 'string');       // Foreign column with non-reserved keyword as name (does not need quotation).
700
        $foreignTable->addColumn('`foo-bar`', 'string'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite).
701
702
        $table->addForeignKeyConstraint($foreignTable, ['create', 'foo', '`bar`'], ['create', 'bar', '`foo-bar`'], [], 'FK_WITH_RESERVED_KEYWORD');
703
704
        // Foreign table with non-reserved keyword as name (does not need quotation).
705
        $foreignTable = new Table('foo');
706
        $foreignTable->addColumn('create', 'string');    // Foreign column with reserved keyword as name (needs quotation).
707
        $foreignTable->addColumn('bar', 'string');       // Foreign column with non-reserved keyword as name (does not need quotation).
708
        $foreignTable->addColumn('`foo-bar`', 'string'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite).
709
710
        $table->addForeignKeyConstraint($foreignTable, ['create', 'foo', '`bar`'], ['create', 'bar', '`foo-bar`'], [], 'FK_WITH_NON_RESERVED_KEYWORD');
711
712
        // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite).
713
        $foreignTable = new Table('`foo-bar`');
714
        $foreignTable->addColumn('create', 'string');    // Foreign column with reserved keyword as name (needs quotation).
715
        $foreignTable->addColumn('bar', 'string');       // Foreign column with non-reserved keyword as name (does not need quotation).
716
        $foreignTable->addColumn('`foo-bar`', 'string'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite).
717
718
        $table->addForeignKeyConstraint($foreignTable, ['create', 'foo', '`bar`'], ['create', 'bar', '`foo-bar`'], [], 'FK_WITH_INTENDED_QUOTATION');
719
720
        $sql = $this->platform->getCreateTableSQL($table, AbstractPlatform::CREATE_FOREIGNKEYS);
721
        self::assertEquals($this->getQuotedColumnInForeignKeySQL(), $sql);
722
    }
723
724
    /**
725
     * @group DBAL-1051
726
     */
727
    public function testQuotesReservedKeywordInUniqueConstraintDeclarationSQL() : void
728
    {
729
        $constraint = new UniqueConstraint('select', ['foo'], [], []);
730
731
        self::assertSame(
732
            $this->getQuotesReservedKeywordInUniqueConstraintDeclarationSQL(),
733
            $this->platform->getUniqueConstraintDeclarationSQL('select', $constraint)
734
        );
735
    }
736
737
    abstract protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL() : string;
738
739
    /**
740
     * @group DBAL-2270
741
     */
742
    public function testQuotesReservedKeywordInTruncateTableSQL() : void
743
    {
744
        self::assertSame(
745
            $this->getQuotesReservedKeywordInTruncateTableSQL(),
746
            $this->platform->getTruncateTableSQL('select')
747
        );
748
    }
749
750
    abstract protected function getQuotesReservedKeywordInTruncateTableSQL() : string;
751
752
    /**
753
     * @group DBAL-1051
754
     */
755
    public function testQuotesReservedKeywordInIndexDeclarationSQL() : void
756
    {
757
        $index = new Index('select', ['foo']);
758
759
        if (! $this->supportsInlineIndexDeclaration()) {
760
            $this->expectException(DBALException::class);
761
        }
762
763
        self::assertSame(
764
            $this->getQuotesReservedKeywordInIndexDeclarationSQL(),
765
            $this->platform->getIndexDeclarationSQL('select', $index)
766
        );
767
    }
768
769
    abstract protected function getQuotesReservedKeywordInIndexDeclarationSQL() : string;
770
771
    protected function supportsInlineIndexDeclaration() : bool
772
    {
773
        return true;
774
    }
775
776
    public function testSupportsCommentOnStatement() : void
777
    {
778
        self::assertSame($this->supportsCommentOnStatement(), $this->platform->supportsCommentOnStatement());
779
    }
780
781
    protected function supportsCommentOnStatement() : bool
782
    {
783
        return false;
784
    }
785
786
    public function testGetCreateSchemaSQL() : void
787
    {
788
        $this->expectException(DBALException::class);
789
790
        $this->platform->getCreateSchemaSQL('schema');
791
    }
792
793
    /**
794
     * @group DBAL-585
795
     */
796
    public function testAlterTableChangeQuotedColumn() : void
797
    {
798
        $tableDiff                        = new TableDiff('mytable');
799
        $tableDiff->fromTable             = new Table('mytable');
800
        $tableDiff->changedColumns['foo'] = new ColumnDiff(
801
            'select',
802
            new Column(
803
                'select',
804
                Type::getType('string'),
805
                ['length' => 255]
806
            ),
807
            ['type']
808
        );
809
810
        self::assertStringContainsString(
811
            $this->platform->quoteIdentifier('select'),
812
            implode(';', $this->platform->getAlterTableSQL($tableDiff))
813
        );
814
    }
815
816
    /**
817
     * @group DBAL-563
818
     */
819
    public function testUsesSequenceEmulatedIdentityColumns() : void
820
    {
821
        self::assertFalse($this->platform->usesSequenceEmulatedIdentityColumns());
822
    }
823
824
    /**
825
     * @group DBAL-563
826
     */
827
    public function testReturnsIdentitySequenceName() : void
828
    {
829
        $this->expectException(DBALException::class);
830
831
        $this->platform->getIdentitySequenceName('mytable', 'mycolumn');
832
    }
833
834
    public function testGetFixedLengthStringTypeDeclarationSQLNoLength() : void
835
    {
836
        self::assertSame(
837
            $this->getExpectedFixedLengthStringTypeDeclarationSQLNoLength(),
838
            $this->platform->getStringTypeDeclarationSQL(['fixed' => true])
839
        );
840
    }
841
842
    protected function getExpectedFixedLengthStringTypeDeclarationSQLNoLength() : string
843
    {
844
        return 'CHAR';
845
    }
846
847
    public function testGetFixedLengthStringTypeDeclarationSQLWithLength() : void
848
    {
849
        self::assertSame(
850
            $this->getExpectedFixedLengthStringTypeDeclarationSQLWithLength(),
851
            $this->platform->getStringTypeDeclarationSQL([
852
                'fixed' => true,
853
                'length' => 16,
854
            ])
855
        );
856
    }
857
858
    protected function getExpectedFixedLengthStringTypeDeclarationSQLWithLength() : string
859
    {
860
        return 'CHAR(16)';
861
    }
862
863
    public function testGetVariableLengthStringTypeDeclarationSQLNoLength() : void
864
    {
865
        self::assertSame(
866
            $this->getExpectedVariableLengthStringTypeDeclarationSQLNoLength(),
867
            $this->platform->getStringTypeDeclarationSQL([])
868
        );
869
    }
870
871
    protected function getExpectedVariableLengthStringTypeDeclarationSQLNoLength() : string
872
    {
873
        return 'VARCHAR';
874
    }
875
876
    public function testGetVariableLengthStringTypeDeclarationSQLWithLength() : void
877
    {
878
        self::assertSame(
879
            $this->getExpectedVariableLengthStringTypeDeclarationSQLWithLength(),
880
            $this->platform->getStringTypeDeclarationSQL(['length' => 16])
881
        );
882
    }
883
884
    protected function getExpectedVariableLengthStringTypeDeclarationSQLWithLength() : string
885
    {
886
        return 'VARCHAR(16)';
887
    }
888
889
    public function testGetFixedLengthBinaryTypeDeclarationSQLNoLength() : void
890
    {
891
        self::assertSame(
892
            $this->getExpectedFixedLengthBinaryTypeDeclarationSQLNoLength(),
893
            $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true])
894
        );
895
    }
896
897
    public function getExpectedFixedLengthBinaryTypeDeclarationSQLNoLength() : string
898
    {
899
        return 'BINARY';
900
    }
901
902
    public function testGetFixedLengthBinaryTypeDeclarationSQLWithLength() : void
903
    {
904
        self::assertSame(
905
            $this->getExpectedFixedLengthBinaryTypeDeclarationSQLWithLength(),
906
            $this->platform->getBinaryTypeDeclarationSQL([
907
                'fixed' => true,
908
                'length' => 16,
909
            ])
910
        );
911
    }
912
913
    public function getExpectedFixedLengthBinaryTypeDeclarationSQLWithLength() : string
914
    {
915
        return 'BINARY(16)';
916
    }
917
918
    public function testGetVariableLengthBinaryTypeDeclarationSQLNoLength() : void
919
    {
920
        self::assertSame(
921
            $this->getExpectedVariableLengthBinaryTypeDeclarationSQLNoLength(),
922
            $this->platform->getBinaryTypeDeclarationSQL([])
923
        );
924
    }
925
926
    public function getExpectedVariableLengthBinaryTypeDeclarationSQLNoLength() : string
927
    {
928
        return 'VARBINARY';
929
    }
930
931
    public function testGetVariableLengthBinaryTypeDeclarationSQLWithLength() : void
932
    {
933
        self::assertSame(
934
            $this->getExpectedVariableLengthBinaryTypeDeclarationSQLWithLength(),
935
            $this->platform->getBinaryTypeDeclarationSQL(['length' => 16])
936
        );
937
    }
938
939
    public function getExpectedVariableLengthBinaryTypeDeclarationSQLWithLength() : string
940
    {
941
        return 'VARBINARY(16)';
942
    }
943
944
    /**
945
     * @group DBAL-553
946
     */
947
    public function hasNativeJsonType() : void
948
    {
949
        self::assertFalse($this->platform->hasNativeJsonType());
950
    }
951
952
    /**
953
     * @group DBAL-553
954
     */
955
    public function testReturnsJsonTypeDeclarationSQL() : void
956
    {
957
        $column = [
958
            'length'  => 666,
959
            'notnull' => true,
960
            'type'    => Type::getType('json'),
961
        ];
962
963
        self::assertSame(
964
            $this->platform->getClobTypeDeclarationSQL($column),
965
            $this->platform->getJsonTypeDeclarationSQL($column)
966
        );
967
    }
968
969
    /**
970
     * @group DBAL-234
971
     */
972
    public function testAlterTableRenameIndex() : void
973
    {
974
        $tableDiff            = new TableDiff('mytable');
975
        $tableDiff->fromTable = new Table('mytable');
976
        $tableDiff->fromTable->addColumn('id', 'integer');
977
        $tableDiff->fromTable->setPrimaryKey(['id']);
978
        $tableDiff->renamedIndexes = [
979
            'idx_foo' => new Index('idx_bar', ['id']),
980
        ];
981
982
        self::assertSame(
983
            $this->getAlterTableRenameIndexSQL(),
984
            $this->platform->getAlterTableSQL($tableDiff)
985
        );
986
    }
987
988
    /**
989
     * @return string[]
990
     *
991
     * @group DBAL-234
992
     */
993
    protected function getAlterTableRenameIndexSQL() : array
994
    {
995
        return [
996
            'DROP INDEX idx_foo',
997
            'CREATE INDEX idx_bar ON mytable (id)',
998
        ];
999
    }
1000
1001
    /**
1002
     * @group DBAL-234
1003
     */
1004
    public function testQuotesAlterTableRenameIndex() : void
1005
    {
1006
        $tableDiff            = new TableDiff('table');
1007
        $tableDiff->fromTable = new Table('table');
1008
        $tableDiff->fromTable->addColumn('id', 'integer');
1009
        $tableDiff->fromTable->setPrimaryKey(['id']);
1010
        $tableDiff->renamedIndexes = [
1011
            'create' => new Index('select', ['id']),
1012
            '`foo`'  => new Index('`bar`', ['id']),
1013
        ];
1014
1015
        self::assertSame(
1016
            $this->getQuotedAlterTableRenameIndexSQL(),
1017
            $this->platform->getAlterTableSQL($tableDiff)
1018
        );
1019
    }
1020
1021
    /**
1022
     * @return string[]
1023
     *
1024
     * @group DBAL-234
1025
     */
1026
    protected function getQuotedAlterTableRenameIndexSQL() : array
1027
    {
1028
        return [
1029
            'DROP INDEX "create"',
1030
            'CREATE INDEX "select" ON "table" (id)',
1031
            'DROP INDEX "foo"',
1032
            'CREATE INDEX "bar" ON "table" (id)',
1033
        ];
1034
    }
1035
1036
    /**
1037
     * @group DBAL-835
1038
     */
1039
    public function testQuotesAlterTableRenameColumn() : void
1040
    {
1041
        $fromTable = new Table('mytable');
1042
1043
        $fromTable->addColumn('unquoted1', 'integer', ['comment' => 'Unquoted 1']);
1044
        $fromTable->addColumn('unquoted2', 'integer', ['comment' => 'Unquoted 2']);
1045
        $fromTable->addColumn('unquoted3', 'integer', ['comment' => 'Unquoted 3']);
1046
1047
        $fromTable->addColumn('create', 'integer', ['comment' => 'Reserved keyword 1']);
1048
        $fromTable->addColumn('table', 'integer', ['comment' => 'Reserved keyword 2']);
1049
        $fromTable->addColumn('select', 'integer', ['comment' => 'Reserved keyword 3']);
1050
1051
        $fromTable->addColumn('`quoted1`', 'integer', ['comment' => 'Quoted 1']);
1052
        $fromTable->addColumn('`quoted2`', 'integer', ['comment' => 'Quoted 2']);
1053
        $fromTable->addColumn('`quoted3`', 'integer', ['comment' => 'Quoted 3']);
1054
1055
        $toTable = new Table('mytable');
1056
1057
        $toTable->addColumn('unquoted', 'integer', ['comment' => 'Unquoted 1']); // unquoted -> unquoted
1058
        $toTable->addColumn('where', 'integer', ['comment' => 'Unquoted 2']); // unquoted -> reserved keyword
1059
        $toTable->addColumn('`foo`', 'integer', ['comment' => 'Unquoted 3']); // unquoted -> quoted
1060
1061
        $toTable->addColumn('reserved_keyword', 'integer', ['comment' => 'Reserved keyword 1']); // reserved keyword -> unquoted
1062
        $toTable->addColumn('from', 'integer', ['comment' => 'Reserved keyword 2']); // reserved keyword -> reserved keyword
1063
        $toTable->addColumn('`bar`', 'integer', ['comment' => 'Reserved keyword 3']); // reserved keyword -> quoted
1064
1065
        $toTable->addColumn('quoted', 'integer', ['comment' => 'Quoted 1']); // quoted -> unquoted
1066
        $toTable->addColumn('and', 'integer', ['comment' => 'Quoted 2']); // quoted -> reserved keyword
1067
        $toTable->addColumn('`baz`', 'integer', ['comment' => 'Quoted 3']); // quoted -> quoted
1068
1069
        $comparator = new Comparator();
1070
1071
        $diff = $comparator->diffTable($fromTable, $toTable);
1072
1073
        self::assertNotNull($diff);
1074
1075
        self::assertEquals(
1076
            $this->getQuotedAlterTableRenameColumnSQL(),
1077
            $this->platform->getAlterTableSQL($diff)
1078
        );
1079
    }
1080
1081
    /**
1082
     * Returns SQL statements for {@link testQuotesAlterTableRenameColumn}.
1083
     *
1084
     * @return string[]
1085
     *
1086
     * @group DBAL-835
1087
     */
1088
    abstract protected function getQuotedAlterTableRenameColumnSQL() : array;
1089
1090
    /**
1091
     * @group DBAL-835
1092
     */
1093
    public function testQuotesAlterTableChangeColumnLength() : void
1094
    {
1095
        $fromTable = new Table('mytable');
1096
1097
        $fromTable->addColumn('unquoted1', 'string', ['comment' => 'Unquoted 1', 'length' => 10]);
1098
        $fromTable->addColumn('unquoted2', 'string', ['comment' => 'Unquoted 2', 'length' => 10]);
1099
        $fromTable->addColumn('unquoted3', 'string', ['comment' => 'Unquoted 3', 'length' => 10]);
1100
1101
        $fromTable->addColumn('create', 'string', ['comment' => 'Reserved keyword 1', 'length' => 10]);
1102
        $fromTable->addColumn('table', 'string', ['comment' => 'Reserved keyword 2', 'length' => 10]);
1103
        $fromTable->addColumn('select', 'string', ['comment' => 'Reserved keyword 3', 'length' => 10]);
1104
1105
        $toTable = new Table('mytable');
1106
1107
        $toTable->addColumn('unquoted1', 'string', ['comment' => 'Unquoted 1', 'length' => 255]);
1108
        $toTable->addColumn('unquoted2', 'string', ['comment' => 'Unquoted 2', 'length' => 255]);
1109
        $toTable->addColumn('unquoted3', 'string', ['comment' => 'Unquoted 3', 'length' => 255]);
1110
1111
        $toTable->addColumn('create', 'string', ['comment' => 'Reserved keyword 1', 'length' => 255]);
1112
        $toTable->addColumn('table', 'string', ['comment' => 'Reserved keyword 2', 'length' => 255]);
1113
        $toTable->addColumn('select', 'string', ['comment' => 'Reserved keyword 3', 'length' => 255]);
1114
1115
        $comparator = new Comparator();
1116
1117
        $diff = $comparator->diffTable($fromTable, $toTable);
1118
1119
        self::assertNotNull($diff);
1120
1121
        self::assertEquals(
1122
            $this->getQuotedAlterTableChangeColumnLengthSQL(),
1123
            $this->platform->getAlterTableSQL($diff)
1124
        );
1125
    }
1126
1127
    /**
1128
     * Returns SQL statements for {@link testQuotesAlterTableChangeColumnLength}.
1129
     *
1130
     * @return string[]
1131
     *
1132
     * @group DBAL-835
1133
     */
1134
    abstract protected function getQuotedAlterTableChangeColumnLengthSQL() : array;
1135
1136
    /**
1137
     * @group DBAL-807
1138
     */
1139
    public function testAlterTableRenameIndexInSchema() : void
1140
    {
1141
        $tableDiff            = new TableDiff('myschema.mytable');
1142
        $tableDiff->fromTable = new Table('myschema.mytable');
1143
        $tableDiff->fromTable->addColumn('id', 'integer');
1144
        $tableDiff->fromTable->setPrimaryKey(['id']);
1145
        $tableDiff->renamedIndexes = [
1146
            'idx_foo' => new Index('idx_bar', ['id']),
1147
        ];
1148
1149
        self::assertSame(
1150
            $this->getAlterTableRenameIndexInSchemaSQL(),
1151
            $this->platform->getAlterTableSQL($tableDiff)
1152
        );
1153
    }
1154
1155
    /**
1156
     * @return string[]
1157
     *
1158
     * @group DBAL-807
1159
     */
1160
    protected function getAlterTableRenameIndexInSchemaSQL() : array
1161
    {
1162
        return [
1163
            'DROP INDEX idx_foo',
1164
            'CREATE INDEX idx_bar ON myschema.mytable (id)',
1165
        ];
1166
    }
1167
1168
    /**
1169
     * @group DBAL-807
1170
     */
1171
    public function testQuotesAlterTableRenameIndexInSchema() : void
1172
    {
1173
        $tableDiff            = new TableDiff('`schema`.table');
1174
        $tableDiff->fromTable = new Table('`schema`.table');
1175
        $tableDiff->fromTable->addColumn('id', 'integer');
1176
        $tableDiff->fromTable->setPrimaryKey(['id']);
1177
        $tableDiff->renamedIndexes = [
1178
            'create' => new Index('select', ['id']),
1179
            '`foo`'  => new Index('`bar`', ['id']),
1180
        ];
1181
1182
        self::assertSame(
1183
            $this->getQuotedAlterTableRenameIndexInSchemaSQL(),
1184
            $this->platform->getAlterTableSQL($tableDiff)
1185
        );
1186
    }
1187
1188
    /**
1189
     * @return string[]
1190
     *
1191
     * @group DBAL-234
1192
     */
1193
    protected function getQuotedAlterTableRenameIndexInSchemaSQL() : array
1194
    {
1195
        return [
1196
            'DROP INDEX "schema"."create"',
1197
            'CREATE INDEX "select" ON "schema"."table" (id)',
1198
            'DROP INDEX "schema"."foo"',
1199
            'CREATE INDEX "bar" ON "schema"."table" (id)',
1200
        ];
1201
    }
1202
1203
    /**
1204
     * @group DBAL-1237
1205
     */
1206
    public function testQuotesDropForeignKeySQL() : void
1207
    {
1208
        if (! $this->platform->supportsCreateDropForeignKeyConstraints()) {
1209
            self::markTestSkipped(
1210
                sprintf('%s does not support modifying foreign key constraints.', get_class($this->platform))
1211
            );
1212
        }
1213
1214
        $tableName      = 'table';
1215
        $table          = new Table($tableName);
1216
        $foreignKeyName = 'select';
1217
        $foreignKey     = new ForeignKeyConstraint([], 'foo', [], 'select');
1218
        $expectedSql    = $this->getQuotesDropForeignKeySQL();
1219
1220
        self::assertSame($expectedSql, $this->platform->getDropForeignKeySQL($foreignKeyName, $tableName));
1221
        self::assertSame($expectedSql, $this->platform->getDropForeignKeySQL($foreignKey, $table));
1222
    }
1223
1224
    protected function getQuotesDropForeignKeySQL() : string
1225
    {
1226
        return 'ALTER TABLE "table" DROP FOREIGN KEY "select"';
1227
    }
1228
1229
    /**
1230
     * @group DBAL-1237
1231
     */
1232
    public function testQuotesDropConstraintSQL() : void
1233
    {
1234
        $tableName      = 'table';
1235
        $table          = new Table($tableName);
1236
        $constraintName = 'select';
1237
        $constraint     = new ForeignKeyConstraint([], 'foo', [], 'select');
1238
        $expectedSql    = $this->getQuotesDropConstraintSQL();
1239
1240
        self::assertSame($expectedSql, $this->platform->getDropConstraintSQL($constraintName, $tableName));
1241
        self::assertSame($expectedSql, $this->platform->getDropConstraintSQL($constraint, $table));
1242
    }
1243
1244
    protected function getQuotesDropConstraintSQL() : string
1245
    {
1246
        return 'ALTER TABLE "table" DROP CONSTRAINT "select"';
1247
    }
1248
1249
    protected function getStringLiteralQuoteCharacter() : string
1250
    {
1251
        return "'";
1252
    }
1253
1254
    public function testGetStringLiteralQuoteCharacter() : void
1255
    {
1256
        self::assertSame($this->getStringLiteralQuoteCharacter(), $this->platform->getStringLiteralQuoteCharacter());
1257
    }
1258
1259
    protected function getQuotedCommentOnColumnSQLWithoutQuoteCharacter() : string
1260
    {
1261
        return "COMMENT ON COLUMN mytable.id IS 'This is a comment'";
1262
    }
1263
1264
    public function testGetCommentOnColumnSQLWithoutQuoteCharacter() : void
1265
    {
1266
        self::assertEquals(
1267
            $this->getQuotedCommentOnColumnSQLWithoutQuoteCharacter(),
1268
            $this->platform->getCommentOnColumnSQL('mytable', 'id', 'This is a comment')
1269
        );
1270
    }
1271
1272
    protected function getQuotedCommentOnColumnSQLWithQuoteCharacter() : string
1273
    {
1274
        return "COMMENT ON COLUMN mytable.id IS 'It''s a quote !'";
1275
    }
1276
1277
    public function testGetCommentOnColumnSQLWithQuoteCharacter() : void
1278
    {
1279
        $c = $this->getStringLiteralQuoteCharacter();
1280
1281
        self::assertEquals(
1282
            $this->getQuotedCommentOnColumnSQLWithQuoteCharacter(),
1283
            $this->platform->getCommentOnColumnSQL('mytable', 'id', 'It' . $c . 's a quote !')
1284
        );
1285
    }
1286
1287
    /**
1288
     * @see testGetCommentOnColumnSQL
1289
     *
1290
     * @return string[]
1291
     */
1292
    abstract protected function getCommentOnColumnSQL() : array;
1293
1294
    /**
1295
     * @group DBAL-1004
1296
     */
1297
    public function testGetCommentOnColumnSQL() : void
1298
    {
1299
        self::assertSame(
1300
            $this->getCommentOnColumnSQL(),
1301
            [
1302
                $this->platform->getCommentOnColumnSQL('foo', 'bar', 'comment'), // regular identifiers
1303
                $this->platform->getCommentOnColumnSQL('`Foo`', '`BAR`', 'comment'), // explicitly quoted identifiers
1304
                $this->platform->getCommentOnColumnSQL('select', 'from', 'comment'), // reserved keyword identifiers
1305
            ]
1306
        );
1307
    }
1308
1309
    /**
1310
     * @group DBAL-1176
1311
     * @dataProvider getGeneratesInlineColumnCommentSQL
1312
     */
1313
    public function testGeneratesInlineColumnCommentSQL(string $comment, string $expectedSql) : void
1314
    {
1315
        if (! $this->platform->supportsInlineColumnComments()) {
1316
            self::markTestSkipped(sprintf('%s does not support inline column comments.', get_class($this->platform)));
1317
        }
1318
1319
        self::assertSame($expectedSql, $this->platform->getInlineColumnCommentSQL($comment));
1320
    }
1321
1322
    /**
1323
     * @return mixed[][]
1324
     */
1325
    public static function getGeneratesInlineColumnCommentSQL() : iterable
1326
    {
1327
        return [
1328
            'regular comment' => ['Regular comment', static::getInlineColumnRegularCommentSQL()],
1329
            'comment requiring escaping' => [
1330
                sprintf(
1331
                    'Using inline comment delimiter %s works',
1332
                    static::getInlineColumnCommentDelimiter()
1333
                ),
1334
                static::getInlineColumnCommentRequiringEscapingSQL(),
1335
            ],
1336
            'empty comment' => ['', static::getInlineColumnEmptyCommentSQL()],
1337
        ];
1338
    }
1339
1340
    protected static function getInlineColumnCommentDelimiter() : string
1341
    {
1342
        return "'";
1343
    }
1344
1345
    protected static function getInlineColumnRegularCommentSQL() : string
1346
    {
1347
        return "COMMENT 'Regular comment'";
1348
    }
1349
1350
    protected static function getInlineColumnCommentRequiringEscapingSQL() : string
1351
    {
1352
        return "COMMENT 'Using inline comment delimiter '' works'";
1353
    }
1354
1355
    protected static function getInlineColumnEmptyCommentSQL() : string
1356
    {
1357
        return "COMMENT ''";
1358
    }
1359
1360
    protected function getQuotedStringLiteralWithoutQuoteCharacter() : string
1361
    {
1362
        return "'No quote'";
1363
    }
1364
1365
    protected function getQuotedStringLiteralWithQuoteCharacter() : string
1366
    {
1367
        return "'It''s a quote'";
1368
    }
1369
1370
    protected function getQuotedStringLiteralQuoteCharacter() : string
1371
    {
1372
        return "''''";
1373
    }
1374
1375
    /**
1376
     * @group DBAL-1176
1377
     */
1378
    public function testThrowsExceptionOnGeneratingInlineColumnCommentSQLIfUnsupported() : void
1379
    {
1380
        if ($this->platform->supportsInlineColumnComments()) {
1381
            self::markTestSkipped(sprintf('%s supports inline column comments.', get_class($this->platform)));
1382
        }
1383
1384
        $this->expectException(DBALException::class);
1385
        $this->expectExceptionMessage('Operation "Doctrine\\DBAL\\Platforms\\AbstractPlatform::getInlineColumnCommentSQL" is not supported by platform.');
1386
        $this->expectExceptionCode(0);
1387
1388
        $this->platform->getInlineColumnCommentSQL('unsupported');
1389
    }
1390
1391
    public function testQuoteStringLiteral() : void
1392
    {
1393
        $c = $this->getStringLiteralQuoteCharacter();
1394
1395
        self::assertEquals(
1396
            $this->getQuotedStringLiteralWithoutQuoteCharacter(),
1397
            $this->platform->quoteStringLiteral('No quote')
1398
        );
1399
        self::assertEquals(
1400
            $this->getQuotedStringLiteralWithQuoteCharacter(),
1401
            $this->platform->quoteStringLiteral('It' . $c . 's a quote')
1402
        );
1403
        self::assertEquals(
1404
            $this->getQuotedStringLiteralQuoteCharacter(),
1405
            $this->platform->quoteStringLiteral($c)
1406
        );
1407
    }
1408
1409
    /**
1410
     * @group DBAL-423
1411
     */
1412
    public function testReturnsGuidTypeDeclarationSQL() : void
1413
    {
1414
        $this->expectException(DBALException::class);
1415
1416
        $this->platform->getGuidTypeDeclarationSQL([]);
1417
    }
1418
1419
    /**
1420
     * @group DBAL-1010
1421
     */
1422
    public function testGeneratesAlterTableRenameColumnSQL() : void
1423
    {
1424
        $table = new Table('foo');
1425
        $table->addColumn(
1426
            'bar',
1427
            'integer',
1428
            ['notnull' => true, 'default' => 666, 'comment' => 'rename test']
1429
        );
1430
1431
        $tableDiff                        = new TableDiff('foo');
1432
        $tableDiff->fromTable             = $table;
1433
        $tableDiff->renamedColumns['bar'] = new Column(
1434
            'baz',
1435
            Type::getType('integer'),
1436
            ['notnull' => true, 'default' => 666, 'comment' => 'rename test']
1437
        );
1438
1439
        self::assertSame($this->getAlterTableRenameColumnSQL(), $this->platform->getAlterTableSQL($tableDiff));
1440
    }
1441
1442
    /**
1443
     * @return string[]
1444
     */
1445
    abstract public function getAlterTableRenameColumnSQL() : array;
1446
1447
    /**
1448
     * @group DBAL-1016
1449
     */
1450
    public function testQuotesTableIdentifiersInAlterTableSQL() : void
1451
    {
1452
        $table = new Table('"foo"');
1453
        $table->addColumn('id', 'integer');
1454
        $table->addColumn('fk', 'integer');
1455
        $table->addColumn('fk2', 'integer');
1456
        $table->addColumn('fk3', 'integer');
1457
        $table->addColumn('bar', 'integer');
1458
        $table->addColumn('baz', 'integer');
1459
        $table->addForeignKeyConstraint('fk_table', ['fk'], ['id'], [], 'fk1');
1460
        $table->addForeignKeyConstraint('fk_table', ['fk2'], ['id'], [], 'fk2');
1461
1462
        $tableDiff                        = new TableDiff('"foo"');
1463
        $tableDiff->fromTable             = $table;
1464
        $tableDiff->newName               = 'table';
1465
        $tableDiff->addedColumns['bloo']  = new Column('bloo', Type::getType('integer'));
1466
        $tableDiff->changedColumns['bar'] = new ColumnDiff(
1467
            'bar',
1468
            new Column('bar', Type::getType('integer'), ['notnull' => false]),
1469
            ['notnull'],
1470
            $table->getColumn('bar')
1471
        );
1472
        $tableDiff->renamedColumns['id']  = new Column('war', Type::getType('integer'));
1473
        $tableDiff->removedColumns['baz'] = new Column('baz', Type::getType('integer'));
1474
        $tableDiff->addedForeignKeys[]    = new ForeignKeyConstraint(['fk3'], 'fk_table', ['id'], 'fk_add');
1475
        $tableDiff->changedForeignKeys[]  = new ForeignKeyConstraint(['fk2'], 'fk_table2', ['id'], 'fk2');
1476
        $tableDiff->removedForeignKeys[]  = new ForeignKeyConstraint(['fk'], 'fk_table', ['id'], 'fk1');
1477
1478
        self::assertSame(
1479
            $this->getQuotesTableIdentifiersInAlterTableSQL(),
1480
            $this->platform->getAlterTableSQL($tableDiff)
1481
        );
1482
    }
1483
1484
    /**
1485
     * @return string[]
1486
     */
1487
    abstract protected function getQuotesTableIdentifiersInAlterTableSQL() : array;
1488
1489
    /**
1490
     * @group DBAL-1090
1491
     */
1492
    public function testAlterStringToFixedString() : void
1493
    {
1494
        $table = new Table('mytable');
1495
        $table->addColumn('name', 'string', ['length' => 2]);
1496
1497
        $tableDiff            = new TableDiff('mytable');
1498
        $tableDiff->fromTable = $table;
1499
1500
        $tableDiff->changedColumns['name'] = new ColumnDiff(
1501
            'name',
1502
            new Column(
1503
                'name',
1504
                Type::getType('string'),
1505
                ['fixed' => true, 'length' => 2]
1506
            ),
1507
            ['fixed']
1508
        );
1509
1510
        $sql = $this->platform->getAlterTableSQL($tableDiff);
1511
1512
        $expectedSql = $this->getAlterStringToFixedStringSQL();
1513
1514
        self::assertEquals($expectedSql, $sql);
1515
    }
1516
1517
    /**
1518
     * @return string[]
1519
     */
1520
    abstract protected function getAlterStringToFixedStringSQL() : array;
1521
1522
    /**
1523
     * @group DBAL-1062
1524
     */
1525
    public function testGeneratesAlterTableRenameIndexUsedByForeignKeySQL() : void
1526
    {
1527
        $foreignTable = new Table('foreign_table');
1528
        $foreignTable->addColumn('id', 'integer');
1529
        $foreignTable->setPrimaryKey(['id']);
1530
1531
        $primaryTable = new Table('mytable');
1532
        $primaryTable->addColumn('foo', 'integer');
1533
        $primaryTable->addColumn('bar', 'integer');
1534
        $primaryTable->addColumn('baz', 'integer');
1535
        $primaryTable->addIndex(['foo'], 'idx_foo');
1536
        $primaryTable->addIndex(['bar'], 'idx_bar');
1537
        $primaryTable->addForeignKeyConstraint($foreignTable, ['foo'], ['id'], [], 'fk_foo');
1538
        $primaryTable->addForeignKeyConstraint($foreignTable, ['bar'], ['id'], [], 'fk_bar');
1539
1540
        $tableDiff                            = new TableDiff('mytable');
1541
        $tableDiff->fromTable                 = $primaryTable;
1542
        $tableDiff->renamedIndexes['idx_foo'] = new Index('idx_foo_renamed', ['foo']);
1543
1544
        self::assertSame(
1545
            $this->getGeneratesAlterTableRenameIndexUsedByForeignKeySQL(),
1546
            $this->platform->getAlterTableSQL($tableDiff)
1547
        );
1548
    }
1549
1550
    /**
1551
     * @return string[]
1552
     */
1553
    abstract protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL() : array;
1554
1555
    /**
1556
     * @param mixed[] $column
1557
     *
1558
     * @group DBAL-1082
1559
     * @dataProvider getGeneratesDecimalTypeDeclarationSQL
1560
     */
1561
    public function testGeneratesDecimalTypeDeclarationSQL(array $column, string $expectedSql) : void
1562
    {
1563
        self::assertSame($expectedSql, $this->platform->getDecimalTypeDeclarationSQL($column));
1564
    }
1565
1566
    /**
1567
     * @return mixed[][]
1568
     */
1569
    public static function getGeneratesDecimalTypeDeclarationSQL() : iterable
1570
    {
1571
        return [
1572
            [[], 'NUMERIC(10, 0)'],
1573
            [['unsigned' => true], 'NUMERIC(10, 0)'],
1574
            [['unsigned' => false], 'NUMERIC(10, 0)'],
1575
            [['precision' => 5], 'NUMERIC(5, 0)'],
1576
            [['scale' => 5], 'NUMERIC(10, 5)'],
1577
            [['precision' => 8, 'scale' => 2], 'NUMERIC(8, 2)'],
1578
        ];
1579
    }
1580
1581
    /**
1582
     * @param mixed[] $column
1583
     *
1584
     * @group DBAL-1082
1585
     * @dataProvider getGeneratesFloatDeclarationSQL
1586
     */
1587
    public function testGeneratesFloatDeclarationSQL(array $column, string $expectedSql) : void
1588
    {
1589
        self::assertSame($expectedSql, $this->platform->getFloatDeclarationSQL($column));
1590
    }
1591
1592
    /**
1593
     * @return mixed[][]
1594
     */
1595
    public static function getGeneratesFloatDeclarationSQL() : iterable
1596
    {
1597
        return [
1598
            [[], 'DOUBLE PRECISION'],
1599
            [['unsigned' => true], 'DOUBLE PRECISION'],
1600
            [['unsigned' => false], 'DOUBLE PRECISION'],
1601
            [['precision' => 5], 'DOUBLE PRECISION'],
1602
            [['scale' => 5], 'DOUBLE PRECISION'],
1603
            [['precision' => 8, 'scale' => 2], 'DOUBLE PRECISION'],
1604
        ];
1605
    }
1606
1607
    public function testItEscapesStringsForLike() : void
1608
    {
1609
        self::assertSame(
1610
            '\_25\% off\_ your next purchase \\\\o/',
1611
            $this->platform->escapeStringForLike('_25% off_ your next purchase \o/', '\\')
1612
        );
1613
    }
1614
1615
    public function testZeroOffsetWithoutLimitIsIgnored() : void
1616
    {
1617
        $query = 'SELECT * FROM user';
1618
1619
        self::assertSame(
1620
            $query,
1621
            $this->platform->modifyLimitQuery($query, null, 0)
1622
        );
1623
    }
1624
}
1625