Failed Conditions
Push — master ( 01c22b...e42c1f )
by Marco
79:13 queued 10s
created

testGeneratesSequenceSqlCommands()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 16
c 1
b 0
f 0
dl 0
loc 22
rs 9.7333
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\DBAL\Platforms;
6
7
use Doctrine\DBAL\DBALException;
8
use Doctrine\DBAL\Exception\ColumnLengthRequired;
9
use Doctrine\DBAL\LockMode;
10
use Doctrine\DBAL\Platforms\AbstractPlatform;
11
use Doctrine\DBAL\Platforms\SQLAnywherePlatform;
12
use Doctrine\DBAL\Platforms\TrimMode;
13
use Doctrine\DBAL\Schema\Column;
14
use Doctrine\DBAL\Schema\ColumnDiff;
15
use Doctrine\DBAL\Schema\Comparator;
16
use Doctrine\DBAL\Schema\Constraint;
17
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
18
use Doctrine\DBAL\Schema\Index;
19
use Doctrine\DBAL\Schema\Sequence;
20
use Doctrine\DBAL\Schema\Table;
21
use Doctrine\DBAL\Schema\TableDiff;
22
use Doctrine\DBAL\Schema\UniqueConstraint;
23
use Doctrine\DBAL\TransactionIsolationLevel;
24
use Doctrine\DBAL\Types\Type;
25
use InvalidArgumentException;
26
use function mt_rand;
27
use function strlen;
28
use function substr;
29
30
class SQLAnywherePlatformTest extends AbstractPlatformTestCase
31
{
32
    /** @var SQLAnywherePlatform */
33
    protected $platform;
34
35
    public function createPlatform() : AbstractPlatform
36
    {
37
        return new SQLAnywherePlatform();
38
    }
39
40
    /**
41
     * {@inheritDoc}
42
     */
43
    public function getGenerateAlterTableSql() : array
44
    {
45
        return [
46
            "ALTER TABLE mytable ADD quota INT DEFAULT NULL, DROP foo, ALTER baz VARCHAR(255) DEFAULT 'def' NOT NULL, ALTER bloo BIT DEFAULT '0' NOT NULL",
47
            'ALTER TABLE mytable RENAME userlist',
48
        ];
49
    }
50
51
    public function getGenerateForeignKeySql() : string
52
    {
53
        return 'ALTER TABLE test ADD FOREIGN KEY (fk_name_id) REFERENCES other_table (id)';
54
    }
55
56
    public function getGenerateIndexSql() : string
57
    {
58
        return 'CREATE INDEX my_idx ON mytable (user_name, last_login)';
59
    }
60
61
    public function getGenerateTableSql() : string
62
    {
63
        return 'CREATE TABLE test (id INT IDENTITY NOT NULL, test VARCHAR(255) DEFAULT NULL, PRIMARY KEY (id))';
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    public function getGenerateTableWithMultiColumnUniqueIndexSql() : array
70
    {
71
        return [
72
            'CREATE TABLE test (foo VARCHAR(255) DEFAULT NULL, bar VARCHAR(255) DEFAULT NULL)',
73
            'CREATE UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA ON test (foo, bar)',
74
        ];
75
    }
76
77
    public function getGenerateUniqueIndexSql() : string
78
    {
79
        return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    protected function getQuotedColumnInForeignKeySQL() : array
86
    {
87
        return ['CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL, foo VARCHAR(255) NOT NULL, "bar" VARCHAR(255) NOT NULL, CONSTRAINT FK_WITH_RESERVED_KEYWORD FOREIGN KEY ("create", foo, "bar") REFERENCES "foreign" ("create", bar, "foo-bar"), CONSTRAINT FK_WITH_NON_RESERVED_KEYWORD FOREIGN KEY ("create", foo, "bar") REFERENCES foo ("create", bar, "foo-bar"), CONSTRAINT FK_WITH_INTENDED_QUOTATION FOREIGN KEY ("create", foo, "bar") REFERENCES "foo-bar" ("create", bar, "foo-bar"))'];
88
    }
89
90
    /**
91
     * {@inheritDoc}
92
     */
93
    protected function getQuotedColumnInIndexSQL() : array
94
    {
95
        return [
96
            'CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL)',
97
            'CREATE INDEX IDX_22660D028FD6E0FB ON "quoted" ("create")',
98
        ];
99
    }
100
101
    /**
102
     * {@inheritDoc}
103
     */
104
    protected function getQuotedNameInIndexSQL() : array
105
    {
106
        return [
107
            'CREATE TABLE test (column1 VARCHAR(255) NOT NULL)',
108
            'CREATE INDEX "key" ON test (column1)',
109
        ];
110
    }
111
112
    /**
113
     * {@inheritDoc}
114
     */
115
    protected function getQuotedColumnInPrimaryKeySQL() : array
116
    {
117
        return ['CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL, PRIMARY KEY ("create"))'];
118
    }
119
120
    /**
121
     * {@inheritDoc}
122
     */
123
    public function getCreateTableColumnCommentsSQL() : array
124
    {
125
        return [
126
            'CREATE TABLE test (id INT NOT NULL, PRIMARY KEY (id))',
127
            "COMMENT ON COLUMN test.id IS 'This is a comment'",
128
        ];
129
    }
130
131
    /**
132
     * {@inheritDoc}
133
     */
134
    public function getAlterTableColumnCommentsSQL() : array
135
    {
136
        return [
137
            'ALTER TABLE mytable ADD quota INT NOT NULL',
138
            "COMMENT ON COLUMN mytable.quota IS 'A comment'",
139
            'COMMENT ON COLUMN mytable.foo IS NULL',
140
            "COMMENT ON COLUMN mytable.baz IS 'B comment'",
141
        ];
142
    }
143
144
    /**
145
     * {@inheritDoc}
146
     */
147
    public function getCreateTableColumnTypeCommentsSQL() : array
148
    {
149
        return [
150
            'CREATE TABLE test (id INT NOT NULL, data TEXT NOT NULL, PRIMARY KEY (id))',
151
            "COMMENT ON COLUMN test.data IS '(DC2Type:array)'",
152
        ];
153
    }
154
155
    public function testHasCorrectPlatformName() : void
156
    {
157
        self::assertEquals('sqlanywhere', $this->platform->getName());
158
    }
159
160
    public function testGeneratesCreateTableSQLWithCommonIndexes() : void
161
    {
162
        $table = new Table('test');
163
        $table->addColumn('id', 'integer');
164
        $table->addColumn('name', 'string', ['length' => 50]);
165
        $table->setPrimaryKey(['id']);
166
        $table->addIndex(['name']);
167
        $table->addIndex(['id', 'name'], 'composite_idx');
168
169
        self::assertEquals(
170
            [
171
                'CREATE TABLE test (id INT NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY (id))',
172
                'CREATE INDEX IDX_D87F7E0C5E237E06 ON test (name)',
173
                'CREATE INDEX composite_idx ON test (id, name)',
174
            ],
175
            $this->platform->getCreateTableSQL($table)
176
        );
177
    }
178
179
    public function testGeneratesCreateTableSQLWithForeignKeyConstraints() : void
180
    {
181
        $table = new Table('test');
182
        $table->addColumn('id', 'integer');
183
        $table->addColumn('fk_1', 'integer');
184
        $table->addColumn('fk_2', 'integer');
185
        $table->setPrimaryKey(['id']);
186
        $table->addForeignKeyConstraint('foreign_table', ['fk_1', 'fk_2'], ['pk_1', 'pk_2']);
187
        $table->addForeignKeyConstraint(
188
            'foreign_table2',
189
            ['fk_1', 'fk_2'],
190
            ['pk_1', 'pk_2'],
191
            [],
192
            'named_fk'
193
        );
194
195
        self::assertEquals(
196
            ['CREATE TABLE test (id INT NOT NULL, fk_1 INT NOT NULL, fk_2 INT NOT NULL, ' .
197
                'CONSTRAINT FK_D87F7E0C177612A38E7F4319 FOREIGN KEY (fk_1, fk_2) REFERENCES foreign_table (pk_1, pk_2), ' .
198
                'CONSTRAINT named_fk FOREIGN KEY (fk_1, fk_2) REFERENCES foreign_table2 (pk_1, pk_2))',
199
            ],
200
            $this->platform->getCreateTableSQL($table, AbstractPlatform::CREATE_FOREIGNKEYS)
201
        );
202
    }
203
204
    public function testGeneratesCreateTableSQLWithCheckConstraints() : void
205
    {
206
        $table = new Table('test');
207
        $table->addColumn('id', 'integer');
208
        $table->addColumn('check_max', 'integer', ['platformOptions' => ['max' => 10]]);
209
        $table->addColumn('check_min', 'integer', ['platformOptions' => ['min' => 10]]);
210
        $table->setPrimaryKey(['id']);
211
212
        self::assertEquals(
213
            ['CREATE TABLE test (id INT NOT NULL, check_max INT NOT NULL, check_min INT NOT NULL, PRIMARY KEY (id), CHECK (check_max <= 10), CHECK (check_min >= 10))'],
214
            $this->platform->getCreateTableSQL($table)
215
        );
216
    }
217
218
    public function testGeneratesTableAlterationWithRemovedColumnCommentSql() : void
219
    {
220
        $table = new Table('mytable');
221
        $table->addColumn('foo', 'string', ['comment' => 'foo comment']);
222
223
        $tableDiff                        = new TableDiff('mytable');
224
        $tableDiff->fromTable             = $table;
225
        $tableDiff->changedColumns['foo'] = new ColumnDiff(
226
            'foo',
227
            new Column('foo', Type::getType('string')),
228
            ['comment']
229
        );
230
231
        self::assertEquals(
232
            ['COMMENT ON COLUMN mytable.foo IS NULL'],
233
            $this->platform->getAlterTableSQL($tableDiff)
234
        );
235
    }
236
237
    /**
238
     * @dataProvider getLockHints
239
     */
240
    public function testAppendsLockHint(?int $lockMode, string $lockHint) : void
241
    {
242
        $fromClause     = 'FROM users';
243
        $expectedResult = $fromClause . $lockHint;
244
245
        self::assertSame($expectedResult, $this->platform->appendLockHint($fromClause, $lockMode));
246
    }
247
248
    /**
249
     * @return mixed[][]
250
     */
251
    public static function getLockHints() : iterable
252
    {
253
        return [
254
            [null, ''],
255
            [LockMode::NONE, ' WITH (NOLOCK)'],
256
            [LockMode::OPTIMISTIC, ''],
257
            [LockMode::PESSIMISTIC_READ, ' WITH (UPDLOCK)'],
258
            [LockMode::PESSIMISTIC_WRITE, ' WITH (XLOCK)'],
259
        ];
260
    }
261
262
    public function testHasCorrectMaxIdentifierLength() : void
263
    {
264
        self::assertEquals(128, $this->platform->getMaxIdentifierLength());
265
    }
266
267
    public function testFixesSchemaElementNames() : void
268
    {
269
        $maxIdentifierLength = $this->platform->getMaxIdentifierLength();
270
        $characters          = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
271
        $schemaElementName   = '';
272
273
        for ($i = 0; $i < $maxIdentifierLength + 100; $i++) {
274
            $schemaElementName .= $characters[mt_rand(0, strlen($characters) - 1)];
275
        }
276
277
        $fixedSchemaElementName = substr($schemaElementName, 0, $maxIdentifierLength);
278
279
        self::assertEquals(
280
            $fixedSchemaElementName,
281
            $this->platform->fixSchemaElementName($schemaElementName)
282
        );
283
        self::assertEquals(
284
            $fixedSchemaElementName,
285
            $this->platform->fixSchemaElementName($fixedSchemaElementName)
286
        );
287
    }
288
289
    public function testGeneratesColumnTypesDeclarationSQL() : void
290
    {
291
        $fullColumnDef = [
292
            'length' => 10,
293
            'fixed' => true,
294
            'unsigned' => true,
295
            'autoincrement' => true,
296
        ];
297
298
        self::assertEquals('SMALLINT', $this->platform->getSmallIntTypeDeclarationSQL([]));
299
        self::assertEquals('UNSIGNED SMALLINT', $this->platform->getSmallIntTypeDeclarationSQL(['unsigned' => true]));
300
        self::assertEquals('UNSIGNED SMALLINT IDENTITY', $this->platform->getSmallIntTypeDeclarationSQL($fullColumnDef));
301
        self::assertEquals('INT', $this->platform->getIntegerTypeDeclarationSQL([]));
302
        self::assertEquals('UNSIGNED INT', $this->platform->getIntegerTypeDeclarationSQL(['unsigned' => true]));
303
        self::assertEquals('UNSIGNED INT IDENTITY', $this->platform->getIntegerTypeDeclarationSQL($fullColumnDef));
304
        self::assertEquals('BIGINT', $this->platform->getBigIntTypeDeclarationSQL([]));
305
        self::assertEquals('UNSIGNED BIGINT', $this->platform->getBigIntTypeDeclarationSQL(['unsigned' => true]));
306
        self::assertEquals('UNSIGNED BIGINT IDENTITY', $this->platform->getBigIntTypeDeclarationSQL($fullColumnDef));
307
        self::assertEquals('LONG BINARY', $this->platform->getBlobTypeDeclarationSQL($fullColumnDef));
308
        self::assertEquals('BIT', $this->platform->getBooleanTypeDeclarationSQL($fullColumnDef));
309
        self::assertEquals('TEXT', $this->platform->getClobTypeDeclarationSQL($fullColumnDef));
310
        self::assertEquals('DATE', $this->platform->getDateTypeDeclarationSQL($fullColumnDef));
311
        self::assertEquals('DATETIME', $this->platform->getDateTimeTypeDeclarationSQL($fullColumnDef));
312
        self::assertEquals('TIME', $this->platform->getTimeTypeDeclarationSQL($fullColumnDef));
313
        self::assertEquals('UNIQUEIDENTIFIER', $this->platform->getGuidTypeDeclarationSQL($fullColumnDef));
314
    }
315
316
    public function testHasNativeGuidType() : void
317
    {
318
        self::assertTrue($this->platform->hasNativeGuidType());
319
    }
320
321
    public function testGeneratesDDLSnippets() : void
322
    {
323
        self::assertEquals("CREATE DATABASE 'foobar'", $this->platform->getCreateDatabaseSQL('foobar'));
324
        self::assertEquals("CREATE DATABASE 'foobar'", $this->platform->getCreateDatabaseSQL('"foobar"'));
325
        self::assertEquals("CREATE DATABASE 'create'", $this->platform->getCreateDatabaseSQL('create'));
326
        self::assertEquals("DROP DATABASE 'foobar'", $this->platform->getDropDatabaseSQL('foobar'));
327
        self::assertEquals("DROP DATABASE 'foobar'", $this->platform->getDropDatabaseSQL('"foobar"'));
328
        self::assertEquals("DROP DATABASE 'create'", $this->platform->getDropDatabaseSQL('create'));
329
        self::assertEquals('CREATE GLOBAL TEMPORARY TABLE', $this->platform->getCreateTemporaryTableSnippetSQL());
330
        self::assertEquals("START DATABASE 'foobar' AUTOSTOP OFF", $this->platform->getStartDatabaseSQL('foobar'));
331
        self::assertEquals("START DATABASE 'foobar' AUTOSTOP OFF", $this->platform->getStartDatabaseSQL('"foobar"'));
332
        self::assertEquals("START DATABASE 'create' AUTOSTOP OFF", $this->platform->getStartDatabaseSQL('create'));
333
        self::assertEquals('STOP DATABASE "foobar" UNCONDITIONALLY', $this->platform->getStopDatabaseSQL('foobar'));
334
        self::assertEquals('STOP DATABASE "foobar" UNCONDITIONALLY', $this->platform->getStopDatabaseSQL('"foobar"'));
335
        self::assertEquals('STOP DATABASE "create" UNCONDITIONALLY', $this->platform->getStopDatabaseSQL('create'));
336
        self::assertEquals('TRUNCATE TABLE foobar', $this->platform->getTruncateTableSQL('foobar'));
337
338
        $viewSql = 'SELECT * FROM footable';
339
        self::assertEquals('CREATE VIEW fooview AS ' . $viewSql, $this->platform->getCreateViewSQL('fooview', $viewSql));
340
        self::assertEquals('DROP VIEW fooview', $this->platform->getDropViewSQL('fooview'));
341
    }
342
343
    public function testGeneratesPrimaryKeyDeclarationSQL() : void
344
    {
345
        self::assertEquals(
346
            'CONSTRAINT pk PRIMARY KEY CLUSTERED (a, b)',
347
            $this->platform->getPrimaryKeyDeclarationSQL(
348
                new Index(null, ['a', 'b'], true, true, ['clustered']),
349
                'pk'
350
            )
351
        );
352
        self::assertEquals(
353
            'PRIMARY KEY (a, b)',
354
            $this->platform->getPrimaryKeyDeclarationSQL(
355
                new Index(null, ['a', 'b'], true, true)
356
            )
357
        );
358
    }
359
360
    public function testCannotGeneratePrimaryKeyDeclarationSQLWithEmptyColumns() : void
361
    {
362
        $this->expectException(InvalidArgumentException::class);
363
364
        $this->platform->getPrimaryKeyDeclarationSQL(new Index('pk', [], true, true));
365
    }
366
367
    public function testGeneratesCreateUnnamedPrimaryKeySQL() : void
368
    {
369
        self::assertEquals(
370
            'ALTER TABLE foo ADD PRIMARY KEY CLUSTERED (a, b)',
371
            $this->platform->getCreatePrimaryKeySQL(
372
                new Index('pk', ['a', 'b'], true, true, ['clustered']),
373
                'foo'
374
            )
375
        );
376
        self::assertEquals(
377
            'ALTER TABLE foo ADD PRIMARY KEY (a, b)',
378
            $this->platform->getCreatePrimaryKeySQL(
379
                new Index('any_pk_name', ['a', 'b'], true, true),
380
                new Table('foo')
381
            )
382
        );
383
    }
384
385
    public function testGeneratesUniqueConstraintDeclarationSQL() : void
386
    {
387
        self::assertEquals(
388
            'CONSTRAINT unique_constraint UNIQUE CLUSTERED (a, b)',
389
            $this->platform->getUniqueConstraintDeclarationSQL(
390
                'unique_constraint',
391
                new UniqueConstraint('', ['a', 'b'], ['clustered'])
392
            )
393
        );
394
        self::assertEquals(
395
            'CONSTRAINT UNIQUE (a, b)',
396
            $this->platform->getUniqueConstraintDeclarationSQL('', new UniqueConstraint('', ['a', 'b']))
397
        );
398
    }
399
400
    public function testCannotGenerateUniqueConstraintDeclarationSQLWithEmptyColumns() : void
401
    {
402
        $this->expectException(InvalidArgumentException::class);
403
404
        $this->platform->getUniqueConstraintDeclarationSQL('constr', new UniqueConstraint('constr', []));
405
    }
406
407
    public function testGeneratesForeignKeyConstraintsWithAdvancedPlatformOptionsSQL() : void
408
    {
409
        self::assertEquals(
410
            'CONSTRAINT fk ' .
411
                'NOT NULL FOREIGN KEY (a, b) ' .
412
                'REFERENCES foreign_table (c, d) ' .
413
                'MATCH UNIQUE SIMPLE ON UPDATE CASCADE ON DELETE SET NULL CHECK ON COMMIT CLUSTERED FOR OLAP WORKLOAD',
414
            $this->platform->getForeignKeyDeclarationSQL(
415
                new ForeignKeyConstraint(['a', 'b'], 'foreign_table', ['c', 'd'], 'fk', [
416
                    'notnull' => true,
417
                    'match' => SQLAnywherePlatform::FOREIGN_KEY_MATCH_SIMPLE_UNIQUE,
418
                    'onUpdate' => 'CASCADE',
419
                    'onDelete' => 'SET NULL',
420
                    'check_on_commit' => true,
421
                    'clustered' => true,
422
                    'for_olap_workload' => true,
423
                ])
424
            )
425
        );
426
        self::assertEquals(
427
            'FOREIGN KEY (a, b) REFERENCES foreign_table (c, d)',
428
            $this->platform->getForeignKeyDeclarationSQL(
429
                new ForeignKeyConstraint(['a', 'b'], 'foreign_table', ['c', 'd'])
430
            )
431
        );
432
    }
433
434
    public function testGeneratesForeignKeyMatchClausesSQL() : void
435
    {
436
        self::assertEquals('SIMPLE', $this->platform->getForeignKeyMatchClauseSQL(1));
437
        self::assertEquals('FULL', $this->platform->getForeignKeyMatchClauseSQL(2));
438
        self::assertEquals('UNIQUE SIMPLE', $this->platform->getForeignKeyMatchClauseSQL(129));
439
        self::assertEquals('UNIQUE FULL', $this->platform->getForeignKeyMatchClauseSQL(130));
440
    }
441
442
    public function testCannotGenerateInvalidForeignKeyMatchClauseSQL() : void
443
    {
444
        $this->expectException(InvalidArgumentException::class);
445
446
        $this->platform->getForeignKeyMatchCLauseSQL(3);
447
    }
448
449
    public function testCannotGenerateForeignKeyConstraintSQLWithEmptyLocalColumns() : void
450
    {
451
        $this->expectException(InvalidArgumentException::class);
452
        $this->platform->getForeignKeyDeclarationSQL(new ForeignKeyConstraint([], 'foreign_tbl', ['c', 'd']));
453
    }
454
455
    public function testCannotGenerateForeignKeyConstraintSQLWithEmptyForeignColumns() : void
456
    {
457
        $this->expectException(InvalidArgumentException::class);
458
        $this->platform->getForeignKeyDeclarationSQL(new ForeignKeyConstraint(['a', 'b'], 'foreign_tbl', []));
459
    }
460
461
    public function testCannotGenerateForeignKeyConstraintSQLWithEmptyForeignTableName() : void
462
    {
463
        $this->expectException(InvalidArgumentException::class);
464
        $this->platform->getForeignKeyDeclarationSQL(new ForeignKeyConstraint(['a', 'b'], '', ['c', 'd']));
465
    }
466
467
    public function testCannotGenerateCommonIndexWithCreateConstraintSQL() : void
468
    {
469
        $this->expectException(InvalidArgumentException::class);
470
471
        $this->platform->getCreateConstraintSQL(new Index('fooindex', []), new Table('footable'));
472
    }
473
474
    public function testCannotGenerateCustomConstraintWithCreateConstraintSQL() : void
475
    {
476
        $this->expectException(InvalidArgumentException::class);
477
478
        $this->platform->getCreateConstraintSQL($this->createMock(Constraint::class), 'footable');
479
    }
480
481
    public function testGeneratesCreateIndexWithAdvancedPlatformOptionsSQL() : void
482
    {
483
        self::assertEquals(
484
            'CREATE UNIQUE INDEX fooindex ON footable (a, b) WITH NULLS DISTINCT',
485
            $this->platform->getCreateIndexSQL(
486
                new Index(
487
                    'fooindex',
488
                    ['a', 'b'],
489
                    true,
490
                    false,
491
                    ['with_nulls_distinct']
492
                ),
493
                'footable'
494
            )
495
        );
496
497
        // WITH NULLS DISTINCT clause not available on primary indexes.
498
        self::assertEquals(
499
            'ALTER TABLE footable ADD PRIMARY KEY (a, b)',
500
            $this->platform->getCreateIndexSQL(
501
                new Index(
502
                    'fooindex',
503
                    ['a', 'b'],
504
                    false,
505
                    true,
506
                    ['with_nulls_distinct']
507
                ),
508
                'footable'
509
            )
510
        );
511
512
        // WITH NULLS DISTINCT clause not available on non-unique indexes.
513
        self::assertEquals(
514
            'CREATE INDEX fooindex ON footable (a, b)',
515
            $this->platform->getCreateIndexSQL(
516
                new Index(
517
                    'fooindex',
518
                    ['a', 'b'],
519
                    false,
520
                    false,
521
                    ['with_nulls_distinct']
522
                ),
523
                'footable'
524
            )
525
        );
526
527
        self::assertEquals(
528
            'CREATE VIRTUAL UNIQUE CLUSTERED INDEX fooindex ON footable (a, b) WITH NULLS NOT DISTINCT FOR OLAP WORKLOAD',
529
            $this->platform->getCreateIndexSQL(
530
                new Index(
531
                    'fooindex',
532
                    ['a', 'b'],
533
                    true,
534
                    false,
535
                    ['virtual', 'clustered', 'with_nulls_not_distinct', 'for_olap_workload']
536
                ),
537
                'footable'
538
            )
539
        );
540
        self::assertEquals(
541
            'CREATE VIRTUAL CLUSTERED INDEX fooindex ON footable (a, b) FOR OLAP WORKLOAD',
542
            $this->platform->getCreateIndexSQL(
543
                new Index(
544
                    'fooindex',
545
                    ['a', 'b'],
546
                    false,
547
                    false,
548
                    ['virtual', 'clustered', 'with_nulls_not_distinct', 'for_olap_workload']
549
                ),
550
                'footable'
551
            )
552
        );
553
554
        // WITH NULLS NOT DISTINCT clause not available on primary indexes.
555
        self::assertEquals(
556
            'ALTER TABLE footable ADD PRIMARY KEY (a, b)',
557
            $this->platform->getCreateIndexSQL(
558
                new Index(
559
                    'fooindex',
560
                    ['a', 'b'],
561
                    false,
562
                    true,
563
                    ['with_nulls_not_distinct']
564
                ),
565
                'footable'
566
            )
567
        );
568
569
        // WITH NULLS NOT DISTINCT clause not available on non-unique indexes.
570
        self::assertEquals(
571
            'CREATE INDEX fooindex ON footable (a, b)',
572
            $this->platform->getCreateIndexSQL(
573
                new Index(
574
                    'fooindex',
575
                    ['a', 'b'],
576
                    false,
577
                    false,
578
                    ['with_nulls_not_distinct']
579
                ),
580
                'footable'
581
            )
582
        );
583
    }
584
585
    public function testThrowsExceptionOnInvalidWithNullsNotDistinctIndexOptions() : void
586
    {
587
        $this->expectException('UnexpectedValueException');
588
589
        $this->platform->getCreateIndexSQL(
590
            new Index(
591
                'fooindex',
592
                ['a', 'b'],
593
                false,
594
                false,
595
                ['with_nulls_distinct', 'with_nulls_not_distinct']
596
            ),
597
            'footable'
598
        );
599
    }
600
601
    public function testDoesNotSupportIndexDeclarationInCreateAlterTableStatements() : void
602
    {
603
        $this->expectException(DBALException::class);
604
605
        $this->platform->getIndexDeclarationSQL('index', new Index('index', []));
606
    }
607
608
    public function testGeneratesDropIndexSQL() : void
609
    {
610
        $index = new Index('fooindex', []);
611
612
        self::assertEquals('DROP INDEX fooindex', $this->platform->getDropIndexSQL($index));
613
        self::assertEquals('DROP INDEX footable.fooindex', $this->platform->getDropIndexSQL($index, 'footable'));
614
        self::assertEquals('DROP INDEX footable.fooindex', $this->platform->getDropIndexSQL(
615
            $index,
616
            new Table('footable')
617
        ));
618
    }
619
620
    public function testCannotGenerateDropIndexSQLWithInvalidIndexParameter() : void
621
    {
622
        $this->expectException(InvalidArgumentException::class);
623
624
        $this->platform->getDropIndexSQL(['index'], 'table');
625
    }
626
627
    public function testCannotGenerateDropIndexSQLWithInvalidTableParameter() : void
628
    {
629
        $this->expectException(InvalidArgumentException::class);
630
631
        $this->platform->getDropIndexSQL('index', ['table']);
632
    }
633
634
    public function testGeneratesSQLSnippets() : void
635
    {
636
        self::assertEquals('STRING(column1, "string1", column2, "string2")', $this->platform->getConcatExpression(
637
            'column1',
638
            '"string1"',
639
            'column2',
640
            '"string2"'
641
        ));
642
        self::assertEquals('CURRENT DATE', $this->platform->getCurrentDateSQL());
643
        self::assertEquals('CURRENT TIME', $this->platform->getCurrentTimeSQL());
644
        self::assertEquals('CURRENT TIMESTAMP', $this->platform->getCurrentTimestampSQL());
645
        self::assertEquals("DATEADD(DAY, 4, '1987/05/02')", $this->platform->getDateAddDaysExpression("'1987/05/02'", '4'));
646
        self::assertEquals("DATEADD(HOUR, 12, '1987/05/02')", $this->platform->getDateAddHourExpression("'1987/05/02'", '12'));
647
        self::assertEquals("DATEADD(MINUTE, 2, '1987/05/02')", $this->platform->getDateAddMinutesExpression("'1987/05/02'", '2'));
648
        self::assertEquals("DATEADD(MONTH, 102, '1987/05/02')", $this->platform->getDateAddMonthExpression("'1987/05/02'", '102'));
649
        self::assertEquals("DATEADD(QUARTER, 5, '1987/05/02')", $this->platform->getDateAddQuartersExpression("'1987/05/02'", '5'));
650
        self::assertEquals("DATEADD(SECOND, 1, '1987/05/02')", $this->platform->getDateAddSecondsExpression("'1987/05/02'", '1'));
651
        self::assertEquals("DATEADD(WEEK, 3, '1987/05/02')", $this->platform->getDateAddWeeksExpression("'1987/05/02'", '3'));
652
        self::assertEquals("DATEADD(YEAR, 10, '1987/05/02')", $this->platform->getDateAddYearsExpression("'1987/05/02'", '10'));
653
        self::assertEquals("DATEDIFF(day, '1987/04/01', '1987/05/02')", $this->platform->getDateDiffExpression("'1987/05/02'", "'1987/04/01'"));
654
        self::assertEquals("DATEADD(DAY, -1 * 4, '1987/05/02')", $this->platform->getDateSubDaysExpression("'1987/05/02'", '4'));
655
        self::assertEquals("DATEADD(HOUR, -1 * 12, '1987/05/02')", $this->platform->getDateSubHourExpression("'1987/05/02'", '12'));
656
        self::assertEquals("DATEADD(MINUTE, -1 * 2, '1987/05/02')", $this->platform->getDateSubMinutesExpression("'1987/05/02'", '2'));
657
        self::assertEquals("DATEADD(MONTH, -1 * 102, '1987/05/02')", $this->platform->getDateSubMonthExpression("'1987/05/02'", '102'));
658
        self::assertEquals("DATEADD(QUARTER, -1 * 5, '1987/05/02')", $this->platform->getDateSubQuartersExpression("'1987/05/02'", '5'));
659
        self::assertEquals("DATEADD(SECOND, -1 * 1, '1987/05/02')", $this->platform->getDateSubSecondsExpression("'1987/05/02'", '1'));
660
        self::assertEquals("DATEADD(WEEK, -1 * 3, '1987/05/02')", $this->platform->getDateSubWeeksExpression("'1987/05/02'", '3'));
661
        self::assertEquals("DATEADD(YEAR, -1 * 10, '1987/05/02')", $this->platform->getDateSubYearsExpression("'1987/05/02'", '10'));
662
        self::assertEquals('Y-m-d H:i:s.u', $this->platform->getDateTimeFormatString());
663
        self::assertEquals('H:i:s.u', $this->platform->getTimeFormatString());
664
        self::assertEquals('', $this->platform->getForUpdateSQL());
665
        self::assertEquals('LOCATE(string_column, substring_column)', $this->platform->getLocateExpression('string_column', 'substring_column'));
666
        self::assertEquals('LOCATE(string_column, substring_column, 1)', $this->platform->getLocateExpression('string_column', 'substring_column', '1'));
667
        self::assertEquals("HASH(column, 'MD5')", $this->platform->getMd5Expression('column'));
668
        self::assertEquals('SUBSTRING(column, 5)', $this->platform->getSubstringExpression('column', '5'));
669
        self::assertEquals('SUBSTRING(column, 5, 2)', $this->platform->getSubstringExpression('column', '5', '2'));
670
        self::assertEquals('GLOBAL TEMPORARY', $this->platform->getTemporaryTableSQL());
671
        self::assertEquals(
672
            'LTRIM(column)',
673
            $this->platform->getTrimExpression('column', TrimMode::LEADING)
674
        );
675
        self::assertEquals(
676
            'RTRIM(column)',
677
            $this->platform->getTrimExpression('column', TrimMode::TRAILING)
678
        );
679
        self::assertEquals(
680
            'TRIM(column)',
681
            $this->platform->getTrimExpression('column')
682
        );
683
        self::assertEquals(
684
            'TRIM(column)',
685
            $this->platform->getTrimExpression('column', TrimMode::UNSPECIFIED)
686
        );
687
        self::assertEquals(
688
            "SUBSTR(column, PATINDEX('%[^' + c + ']%', column))",
689
            $this->platform->getTrimExpression('column', TrimMode::LEADING, 'c')
690
        );
691
        self::assertEquals(
692
            "REVERSE(SUBSTR(REVERSE(column), PATINDEX('%[^' + c + ']%', REVERSE(column))))",
693
            $this->platform->getTrimExpression('column', TrimMode::TRAILING, 'c')
694
        );
695
        self::assertEquals(
696
            "REVERSE(SUBSTR(REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))), PATINDEX('%[^' + c + ']%', " .
697
            "REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))))))",
698
            $this->platform->getTrimExpression('column', TrimMode::UNSPECIFIED, 'c')
699
        );
700
    }
701
702
    public function testHasCorrectDateTimeTzFormatString() : void
703
    {
704
        self::assertEquals('Y-m-d H:i:s.uP', $this->platform->getDateTimeTzFormatString());
705
    }
706
707
    public function testGeneratesDateTimeTzColumnTypeDeclarationSQL() : void
708
    {
709
        self::assertEquals(
710
            'TIMESTAMP WITH TIME ZONE',
711
            $this->platform->getDateTimeTzTypeDeclarationSQL([
712
                'length' => 10,
713
                'fixed' => true,
714
                'unsigned' => true,
715
                'autoincrement' => true,
716
            ])
717
        );
718
    }
719
720
    public function testInitializesDateTimeTzTypeMapping() : void
721
    {
722
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('timestamp with time zone'));
723
        self::assertEquals('datetime', $this->platform->getDoctrineTypeMapping('timestamp with time zone'));
724
    }
725
726
    public function testHasCorrectDefaultTransactionIsolationLevel() : void
727
    {
728
        self::assertEquals(
729
            TransactionIsolationLevel::READ_UNCOMMITTED,
730
            $this->platform->getDefaultTransactionIsolationLevel()
731
        );
732
    }
733
734
    public function testGeneratesTransactionsCommands() : void
735
    {
736
        self::assertEquals(
737
            'SET TEMPORARY OPTION isolation_level = 0',
738
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_UNCOMMITTED)
739
        );
740
        self::assertEquals(
741
            'SET TEMPORARY OPTION isolation_level = 1',
742
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_COMMITTED)
743
        );
744
        self::assertEquals(
745
            'SET TEMPORARY OPTION isolation_level = 2',
746
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::REPEATABLE_READ)
747
        );
748
        self::assertEquals(
749
            'SET TEMPORARY OPTION isolation_level = 3',
750
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::SERIALIZABLE)
751
        );
752
    }
753
754
    public function testModifiesLimitQuery() : void
755
    {
756
        self::assertEquals(
757
            'SELECT TOP 10 * FROM user',
758
            $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 0)
759
        );
760
    }
761
762
    public function testModifiesLimitQueryWithEmptyOffset() : void
763
    {
764
        self::assertEquals(
765
            'SELECT TOP 10 * FROM user',
766
            $this->platform->modifyLimitQuery('SELECT * FROM user', 10)
767
        );
768
    }
769
770
    public function testModifiesLimitQueryWithOffset() : void
771
    {
772
        self::assertEquals(
773
            'SELECT TOP 10 START AT 6 * FROM user',
774
            $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 5)
775
        );
776
        self::assertEquals(
777
            'SELECT TOP 0 START AT 6 * FROM user',
778
            $this->platform->modifyLimitQuery('SELECT * FROM user', 0, 5)
779
        );
780
    }
781
782
    public function testModifiesLimitQueryWithSubSelect() : void
783
    {
784
        self::assertEquals(
785
            'SELECT TOP 10 * FROM (SELECT u.id as uid, u.name as uname FROM user) AS doctrine_tbl',
786
            $this->platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname FROM user) AS doctrine_tbl', 10)
787
        );
788
    }
789
790
    public function testModifiesLimitQueryWithoutLimit() : void
791
    {
792
        self::assertEquals(
793
            'SELECT TOP ALL START AT 11 n FROM Foo',
794
            $this->platform->modifyLimitQuery('SELECT n FROM Foo', null, 10)
795
        );
796
    }
797
798
    public function testPrefersIdentityColumns() : void
799
    {
800
        self::assertTrue($this->platform->prefersIdentityColumns());
801
    }
802
803
    public function testDoesNotPreferSequences() : void
804
    {
805
        self::assertFalse($this->platform->prefersSequences());
806
    }
807
808
    public function testSupportsIdentityColumns() : void
809
    {
810
        self::assertTrue($this->platform->supportsIdentityColumns());
811
    }
812
813
    public function testSupportsPrimaryConstraints() : void
814
    {
815
        self::assertTrue($this->platform->supportsPrimaryConstraints());
816
    }
817
818
    public function testSupportsForeignKeyConstraints() : void
819
    {
820
        self::assertTrue($this->platform->supportsForeignKeyConstraints());
821
    }
822
823
    public function testSupportsForeignKeyOnUpdate() : void
824
    {
825
        self::assertTrue($this->platform->supportsForeignKeyOnUpdate());
826
    }
827
828
    public function testSupportsAlterTable() : void
829
    {
830
        self::assertTrue($this->platform->supportsAlterTable());
831
    }
832
833
    public function testSupportsTransactions() : void
834
    {
835
        self::assertTrue($this->platform->supportsTransactions());
836
    }
837
838
    public function testSupportsSchemas() : void
839
    {
840
        self::assertFalse($this->platform->supportsSchemas());
841
    }
842
843
    public function testSupportsIndexes() : void
844
    {
845
        self::assertTrue($this->platform->supportsIndexes());
846
    }
847
848
    public function testSupportsCommentOnStatement() : void
849
    {
850
        self::assertTrue($this->platform->supportsCommentOnStatement());
851
    }
852
853
    public function testSupportsSavePoints() : void
854
    {
855
        self::assertTrue($this->platform->supportsSavepoints());
856
    }
857
858
    public function testSupportsReleasePoints() : void
859
    {
860
        self::assertTrue($this->platform->supportsReleaseSavepoints());
861
    }
862
863
    public function testSupportsCreateDropDatabase() : void
864
    {
865
        self::assertTrue($this->platform->supportsCreateDropDatabase());
866
    }
867
868
    public function testSupportsGettingAffectedRows() : void
869
    {
870
        self::assertTrue($this->platform->supportsGettingAffectedRows());
871
    }
872
873
    public function testDoesNotSupportSequences() : void
874
    {
875
        self::markTestSkipped('This version of the platform now supports sequences.');
876
    }
877
878
    public function testSupportsSequences() : void
879
    {
880
        self::assertTrue($this->platform->supportsSequences());
881
    }
882
883
    public function testGeneratesSequenceSqlCommands() : void
884
    {
885
        $sequence = new Sequence('myseq', 20, 1);
886
        self::assertEquals(
887
            'CREATE SEQUENCE myseq INCREMENT BY 20 START WITH 1 MINVALUE 1',
888
            $this->platform->getCreateSequenceSQL($sequence)
889
        );
890
        self::assertEquals(
891
            'ALTER SEQUENCE myseq INCREMENT BY 20',
892
            $this->platform->getAlterSequenceSQL($sequence)
893
        );
894
        self::assertEquals(
895
            'DROP SEQUENCE myseq',
896
            $this->platform->getDropSequenceSQL('myseq')
897
        );
898
        self::assertEquals(
899
            'DROP SEQUENCE myseq',
900
            $this->platform->getDropSequenceSQL($sequence)
901
        );
902
        self::assertEquals(
903
            'SELECT myseq.NEXTVAL',
904
            $this->platform->getSequenceNextValSQL('myseq')
905
        );
906
    }
907
908
    public function testDoesNotSupportInlineColumnComments() : void
909
    {
910
        self::assertFalse($this->platform->supportsInlineColumnComments());
911
    }
912
913
    public function testCannotEmulateSchemas() : void
914
    {
915
        self::assertFalse($this->platform->canEmulateSchemas());
916
    }
917
918
    public function testInitializesDoctrineTypeMappings() : void
919
    {
920
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('integer'));
921
        self::assertSame('integer', $this->platform->getDoctrineTypeMapping('integer'));
922
923
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('binary'));
924
        self::assertSame('binary', $this->platform->getDoctrineTypeMapping('binary'));
925
926
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('varbinary'));
927
        self::assertSame('binary', $this->platform->getDoctrineTypeMapping('varbinary'));
928
    }
929
930
    public function testGetVariableLengthStringTypeDeclarationSQLNoLength() : void
931
    {
932
        $this->expectException(ColumnLengthRequired::class);
933
934
        parent::testGetVariableLengthStringTypeDeclarationSQLNoLength();
935
    }
936
937
    public function testGetVariableLengthBinaryTypeDeclarationSQLNoLength() : void
938
    {
939
        $this->expectException(ColumnLengthRequired::class);
940
941
        parent::testGetVariableLengthBinaryTypeDeclarationSQLNoLength();
942
    }
943
944
    /**
945
     * {@inheritDoc}
946
     *
947
     * @group DBAL-234
948
     */
949
    protected function getAlterTableRenameIndexSQL() : array
950
    {
951
        return ['ALTER INDEX idx_foo ON mytable RENAME TO idx_bar'];
952
    }
953
954
    /**
955
     * {@inheritDoc}
956
     *
957
     * @group DBAL-234
958
     */
959
    protected function getQuotedAlterTableRenameIndexSQL() : array
960
    {
961
        return [
962
            'ALTER INDEX "create" ON "table" RENAME TO "select"',
963
            'ALTER INDEX "foo" ON "table" RENAME TO "bar"',
964
        ];
965
    }
966
967
    /**
968
     * {@inheritdoc}
969
     */
970
    protected function getQuotedAlterTableRenameColumnSQL() : array
971
    {
972
        return [
973
            'ALTER TABLE mytable RENAME unquoted1 TO unquoted',
974
            'ALTER TABLE mytable RENAME unquoted2 TO "where"',
975
            'ALTER TABLE mytable RENAME unquoted3 TO "foo"',
976
            'ALTER TABLE mytable RENAME "create" TO reserved_keyword',
977
            'ALTER TABLE mytable RENAME "table" TO "from"',
978
            'ALTER TABLE mytable RENAME "select" TO "bar"',
979
            'ALTER TABLE mytable RENAME quoted1 TO quoted',
980
            'ALTER TABLE mytable RENAME quoted2 TO "and"',
981
            'ALTER TABLE mytable RENAME quoted3 TO "baz"',
982
        ];
983
    }
984
985
    /**
986
     * {@inheritdoc}
987
     */
988
    protected function getQuotedAlterTableChangeColumnLengthSQL() : array
989
    {
990
        $this->markTestIncomplete('Not implemented yet');
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...
991
    }
992
993
    /**
994
     * {@inheritDoc}
995
     *
996
     * @group DBAL-807
997
     */
998
    protected function getAlterTableRenameIndexInSchemaSQL() : array
999
    {
1000
        return ['ALTER INDEX idx_foo ON myschema.mytable RENAME TO idx_bar'];
1001
    }
1002
1003
    /**
1004
     * {@inheritDoc}
1005
     *
1006
     * @group DBAL-807
1007
     */
1008
    protected function getQuotedAlterTableRenameIndexInSchemaSQL() : array
1009
    {
1010
        return [
1011
            'ALTER INDEX "create" ON "schema"."table" RENAME TO "select"',
1012
            'ALTER INDEX "foo" ON "schema"."table" RENAME TO "bar"',
1013
        ];
1014
    }
1015
1016
    /**
1017
     * @group DBAL-423
1018
     */
1019
    public function testReturnsGuidTypeDeclarationSQL() : void
1020
    {
1021
        self::assertSame('UNIQUEIDENTIFIER', $this->platform->getGuidTypeDeclarationSQL([]));
1022
    }
1023
1024
    /**
1025
     * {@inheritdoc}
1026
     */
1027
    public function getAlterTableRenameColumnSQL() : array
1028
    {
1029
        return ['ALTER TABLE foo RENAME bar TO baz'];
1030
    }
1031
1032
    /**
1033
     * {@inheritdoc}
1034
     */
1035
    protected function getQuotesTableIdentifiersInAlterTableSQL() : array
1036
    {
1037
        return [
1038
            'ALTER TABLE "foo" DROP FOREIGN KEY fk1',
1039
            'ALTER TABLE "foo" DROP FOREIGN KEY fk2',
1040
            'ALTER TABLE "foo" RENAME id TO war',
1041
            'ALTER TABLE "foo" ADD bloo INT NOT NULL, DROP baz, ALTER bar INT DEFAULT NULL',
1042
            'ALTER TABLE "foo" RENAME "table"',
1043
            'ALTER TABLE "table" ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id)',
1044
            'ALTER TABLE "table" ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id)',
1045
        ];
1046
    }
1047
1048
    /**
1049
     * {@inheritdoc}
1050
     */
1051
    protected function getCommentOnColumnSQL() : array
1052
    {
1053
        return [
1054
            'COMMENT ON COLUMN foo.bar IS \'comment\'',
1055
            'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
1056
            'COMMENT ON COLUMN "select"."from" IS \'comment\'',
1057
        ];
1058
    }
1059
1060
    /**
1061
     * @group DBAL-1004
1062
     */
1063
    public function testAltersTableColumnCommentWithExplicitlyQuotedIdentifiers() : void
1064
    {
1065
        $table1 = new Table('"foo"', [new Column('"bar"', Type::getType('integer'))]);
1066
        $table2 = new Table('"foo"', [new Column('"bar"', Type::getType('integer'), ['comment' => 'baz'])]);
1067
1068
        $comparator = new Comparator();
1069
1070
        $tableDiff = $comparator->diffTable($table1, $table2);
1071
1072
        self::assertInstanceOf(TableDiff::class, $tableDiff);
1073
        self::assertSame(
1074
            ['COMMENT ON COLUMN "foo"."bar" IS \'baz\''],
1075
            $this->platform->getAlterTableSQL($tableDiff)
1076
        );
1077
    }
1078
1079
    /**
1080
     * {@inheritdoc}
1081
     */
1082
    public static function getReturnsForeignKeyReferentialActionSQL() : iterable
1083
    {
1084
        return [
1085
            ['CASCADE', 'CASCADE'],
1086
            ['SET NULL', 'SET NULL'],
1087
            ['NO ACTION', 'RESTRICT'],
1088
            ['RESTRICT', 'RESTRICT'],
1089
            ['SET DEFAULT', 'SET DEFAULT'],
1090
            ['CaScAdE', 'CASCADE'],
1091
        ];
1092
    }
1093
1094
    /**
1095
     * {@inheritdoc}
1096
     */
1097
    protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL() : string
1098
    {
1099
        return 'CONSTRAINT "select" UNIQUE (foo)';
1100
    }
1101
1102
    /**
1103
     * {@inheritdoc}
1104
     */
1105
    protected function getQuotesReservedKeywordInIndexDeclarationSQL() : string
1106
    {
1107
        return ''; // not supported by this platform
1108
    }
1109
1110
    /**
1111
     * {@inheritdoc}
1112
     */
1113
    protected function getQuotesReservedKeywordInTruncateTableSQL() : string
1114
    {
1115
        return 'TRUNCATE TABLE "select"';
1116
    }
1117
1118
    /**
1119
     * {@inheritdoc}
1120
     */
1121
    protected function supportsInlineIndexDeclaration() : bool
1122
    {
1123
        return false;
1124
    }
1125
1126
    /**
1127
     * {@inheritdoc}
1128
     */
1129
    protected function getAlterStringToFixedStringSQL() : array
1130
    {
1131
        return ['ALTER TABLE mytable ALTER name CHAR(2) NOT NULL'];
1132
    }
1133
1134
    /**
1135
     * {@inheritdoc}
1136
     */
1137
    protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL() : array
1138
    {
1139
        return ['ALTER INDEX idx_foo ON mytable RENAME TO idx_foo_renamed'];
1140
    }
1141
1142
    /**
1143
     * @group DBAL-2436
1144
     */
1145
    public function testQuotesSchemaNameInListTableColumnsSQL() : void
1146
    {
1147
        self::assertStringContainsStringIgnoringCase(
1148
            "'Foo''Bar\\'",
1149
            $this->platform->getListTableColumnsSQL("Foo'Bar\\.baz_table")
1150
        );
1151
    }
1152
1153
    /**
1154
     * @group DBAL-2436
1155
     */
1156
    public function testQuotesTableNameInListTableConstraintsSQL() : void
1157
    {
1158
        self::assertStringContainsStringIgnoringCase("'Foo''Bar\\'", $this->platform->getListTableConstraintsSQL("Foo'Bar\\"), '');
1159
    }
1160
1161
    /**
1162
     * @group DBAL-2436
1163
     */
1164
    public function testQuotesSchemaNameInListTableConstraintsSQL() : void
1165
    {
1166
        self::assertStringContainsStringIgnoringCase(
1167
            "'Foo''Bar\\'",
1168
            $this->platform->getListTableConstraintsSQL("Foo'Bar\\.baz_table")
1169
        );
1170
    }
1171
1172
    /**
1173
     * @group DBAL-2436
1174
     */
1175
    public function testQuotesTableNameInListTableForeignKeysSQL() : void
1176
    {
1177
        self::assertStringContainsStringIgnoringCase(
1178
            "'Foo''Bar\\'",
1179
            $this->platform->getListTableForeignKeysSQL("Foo'Bar\\")
1180
        );
1181
    }
1182
1183
    /**
1184
     * @group DBAL-2436
1185
     */
1186
    public function testQuotesSchemaNameInListTableForeignKeysSQL() : void
1187
    {
1188
        self::assertStringContainsStringIgnoringCase(
1189
            "'Foo''Bar\\'",
1190
            $this->platform->getListTableForeignKeysSQL("Foo'Bar\\.baz_table")
1191
        );
1192
    }
1193
1194
    /**
1195
     * @group DBAL-2436
1196
     */
1197
    public function testQuotesTableNameInListTableIndexesSQL() : void
1198
    {
1199
        self::assertStringContainsStringIgnoringCase(
1200
            "'Foo''Bar\\'",
1201
            $this->platform->getListTableIndexesSQL("Foo'Bar\\")
1202
        );
1203
    }
1204
1205
    /**
1206
     * @group DBAL-2436
1207
     */
1208
    public function testQuotesSchemaNameInListTableIndexesSQL() : void
1209
    {
1210
        self::assertStringContainsStringIgnoringCase(
1211
            "'Foo''Bar\\'",
1212
            $this->platform->getListTableIndexesSQL("Foo'Bar\\.baz_table")
1213
        );
1214
    }
1215
}
1216