Completed
Pull Request — develop (#3582)
by Jonathan
64:18
created

DB2PlatformTest::supportsInlineIndexDeclaration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\DBAL\Platforms;
6
7
use Doctrine\DBAL\Platforms\AbstractPlatform;
8
use Doctrine\DBAL\Platforms\DB2Platform;
9
use Doctrine\DBAL\Schema\Column;
10
use Doctrine\DBAL\Schema\ColumnDiff;
11
use Doctrine\DBAL\Schema\Index;
12
use Doctrine\DBAL\Schema\Table;
13
use Doctrine\DBAL\Schema\TableDiff;
14
use Doctrine\DBAL\Types\Type;
15
use Doctrine\DBAL\Types\Types;
16
17
class DB2PlatformTest extends AbstractPlatformTestCase
18
{
19
    /** @var DB2Platform */
20
    protected $platform;
21
22
    public function createPlatform() : AbstractPlatform
23
    {
24
        return new DB2Platform();
25
    }
26
27
    /**
28
     * {@inheritDoc}
29
     */
30
    public function getGenerateAlterTableSql() : array
31
    {
32
        return [
33
            'ALTER TABLE mytable ALTER COLUMN baz SET DATA TYPE VARCHAR(255)',
34
            'ALTER TABLE mytable ALTER COLUMN baz SET NOT NULL',
35
            "ALTER TABLE mytable ALTER COLUMN baz SET DEFAULT 'def'",
36
            'ALTER TABLE mytable ALTER COLUMN bloo SET DATA TYPE SMALLINT',
37
            'ALTER TABLE mytable ALTER COLUMN bloo SET NOT NULL',
38
            "ALTER TABLE mytable ALTER COLUMN bloo SET DEFAULT '0'",
39
            'ALTER TABLE mytable ' .
40
            'ADD COLUMN quota INTEGER DEFAULT NULL ' .
41
            'DROP COLUMN foo',
42
            "CALL SYSPROC.ADMIN_CMD ('REORG TABLE mytable')",
43
            'RENAME TABLE mytable TO userlist',
44
        ];
45
    }
46
47
    public function getGenerateForeignKeySql() : string
48
    {
49
        return 'ALTER TABLE test ADD FOREIGN KEY (fk_name_id) REFERENCES other_table (id)';
50
    }
51
52
    public function getGenerateIndexSql() : string
53
    {
54
        return 'CREATE INDEX my_idx ON mytable (user_name, last_login)';
55
    }
56
57
    public function getGenerateTableSql() : string
58
    {
59
        return 'CREATE TABLE test (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, test VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))';
60
    }
61
62
    /**
63
     * {@inheritDoc}
64
     */
65
    public function getGenerateTableWithMultiColumnUniqueIndexSql() : array
66
    {
67
        return [
68
            'CREATE TABLE test (foo VARCHAR(255) DEFAULT NULL, bar VARCHAR(255) DEFAULT NULL)',
69
            'CREATE UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA ON test (foo, bar)',
70
        ];
71
    }
72
73
    public function getGenerateUniqueIndexSql() : string
74
    {
75
        return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
76
    }
77
78
    /**
79
     * {@inheritDoc}
80
     */
81
    protected function getQuotedColumnInForeignKeySQL() : array
82
    {
83
        return [
84
            'CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL, foo VARCHAR(255) NOT NULL, "bar" VARCHAR(255) NOT NULL)',
85
            'ALTER TABLE "quoted" ADD CONSTRAINT FK_WITH_RESERVED_KEYWORD FOREIGN KEY ("create", foo, "bar") REFERENCES "foreign" ("create", bar, "foo-bar")',
86
            'ALTER TABLE "quoted" ADD CONSTRAINT FK_WITH_NON_RESERVED_KEYWORD FOREIGN KEY ("create", foo, "bar") REFERENCES foo ("create", bar, "foo-bar")',
87
            'ALTER TABLE "quoted" ADD CONSTRAINT FK_WITH_INTENDED_QUOTATION FOREIGN KEY ("create", foo, "bar") REFERENCES "foo-bar" ("create", bar, "foo-bar")',
88
        ];
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94
    protected function getQuotedColumnInIndexSQL() : array
95
    {
96
        return [
97
            'CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL)',
98
            'CREATE INDEX IDX_22660D028FD6E0FB ON "quoted" ("create")',
99
        ];
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     */
105
    protected function getQuotedNameInIndexSQL() : array
106
    {
107
        return [
108
            'CREATE TABLE test (column1 VARCHAR(255) NOT NULL)',
109
            'CREATE INDEX "key" ON test (column1)',
110
        ];
111
    }
112
113
    /**
114
     * {@inheritDoc}
115
     */
116
    protected function getQuotedColumnInPrimaryKeySQL() : array
117
    {
118
        return ['CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL, PRIMARY KEY("create"))'];
119
    }
120
121
    protected function getBitAndComparisonExpressionSql(string $value1, string $value2) : string
122
    {
123
        return 'BITAND(' . $value1 . ', ' . $value2 . ')';
124
    }
125
126
    protected function getBitOrComparisonExpressionSql(string $value1, string $value2) : string
127
    {
128
        return 'BITOR(' . $value1 . ', ' . $value2 . ')';
129
    }
130
131
    /**
132
     * {@inheritDoc}
133
     */
134
    public function getCreateTableColumnCommentsSQL() : array
135
    {
136
        return [
137
            'CREATE TABLE test (id INTEGER NOT NULL, PRIMARY KEY(id))',
138
            "COMMENT ON COLUMN test.id IS 'This is a comment'",
139
        ];
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145
    public function getAlterTableColumnCommentsSQL() : array
146
    {
147
        return [
148
            'ALTER TABLE mytable ' .
149
            'ADD COLUMN quota INTEGER NOT NULL WITH DEFAULT',
150
            "CALL SYSPROC.ADMIN_CMD ('REORG TABLE mytable')",
151
            "COMMENT ON COLUMN mytable.quota IS 'A comment'",
152
            "COMMENT ON COLUMN mytable.foo IS ''",
153
            "COMMENT ON COLUMN mytable.baz IS 'B comment'",
154
        ];
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160
    public function getCreateTableColumnTypeCommentsSQL() : array
161
    {
162
        return [
163
            'CREATE TABLE test (id INTEGER NOT NULL, "data" CLOB(1M) NOT NULL, PRIMARY KEY(id))',
164
            'COMMENT ON COLUMN test."data" IS \'(DC2Type:array)\'',
165
        ];
166
    }
167
168
    public function testHasCorrectPlatformName() : void
169
    {
170
        self::assertEquals('db2', $this->platform->getName());
171
    }
172
173
    public function testGeneratesCreateTableSQLWithCommonIndexes() : void
174
    {
175
        $table = new Table('test');
176
        $table->addColumn('id', 'integer');
177
        $table->addColumn('name', 'string', ['length' => 50]);
178
        $table->setPrimaryKey(['id']);
179
        $table->addIndex(['name']);
180
        $table->addIndex(['id', 'name'], 'composite_idx');
181
182
        self::assertEquals(
183
            [
184
                'CREATE TABLE test (id INTEGER NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY(id))',
185
                'CREATE INDEX IDX_D87F7E0C5E237E06 ON test (name)',
186
                'CREATE INDEX composite_idx ON test (id, name)',
187
            ],
188
            $this->platform->getCreateTableSQL($table)
189
        );
190
    }
191
192
    public function testGeneratesCreateTableSQLWithForeignKeyConstraints() : void
193
    {
194
        $table = new Table('test');
195
        $table->addColumn('id', 'integer');
196
        $table->addColumn('fk_1', 'integer');
197
        $table->addColumn('fk_2', 'integer');
198
        $table->setPrimaryKey(['id']);
199
        $table->addForeignKeyConstraint('foreign_table', ['fk_1', 'fk_2'], ['pk_1', 'pk_2']);
200
        $table->addForeignKeyConstraint(
201
            'foreign_table2',
202
            ['fk_1', 'fk_2'],
203
            ['pk_1', 'pk_2'],
204
            [],
205
            'named_fk'
206
        );
207
208
        self::assertEquals(
209
            [
210
                'CREATE TABLE test (id INTEGER NOT NULL, fk_1 INTEGER NOT NULL, fk_2 INTEGER NOT NULL)',
211
                'ALTER TABLE test ADD CONSTRAINT FK_D87F7E0C177612A38E7F4319 FOREIGN KEY (fk_1, fk_2) REFERENCES foreign_table (pk_1, pk_2)',
212
                'ALTER TABLE test ADD CONSTRAINT named_fk FOREIGN KEY (fk_1, fk_2) REFERENCES foreign_table2 (pk_1, pk_2)',
213
            ],
214
            $this->platform->getCreateTableSQL($table, AbstractPlatform::CREATE_FOREIGNKEYS)
215
        );
216
    }
217
218
    public function testGeneratesCreateTableSQLWithCheckConstraints() : void
219
    {
220
        $table = new Table('test');
221
        $table->addColumn('id', 'integer');
222
        $table->addColumn('check_max', 'integer', ['platformOptions' => ['max' => 10]]);
223
        $table->addColumn('check_min', 'integer', ['platformOptions' => ['min' => 10]]);
224
        $table->setPrimaryKey(['id']);
225
226
        self::assertEquals(
227
            ['CREATE TABLE test (id INTEGER NOT NULL, check_max INTEGER NOT NULL, check_min INTEGER NOT NULL, PRIMARY KEY(id), CHECK (check_max <= 10), CHECK (check_min >= 10))'],
228
            $this->platform->getCreateTableSQL($table)
229
        );
230
    }
231
232
    public function testGeneratesColumnTypesDeclarationSQL() : void
233
    {
234
        $fullColumnDef = [
235
            'length' => 10,
236
            'fixed' => true,
237
            'unsigned' => true,
238
            'autoincrement' => true,
239
        ];
240
241
        self::assertEquals('VARCHAR(255)', $this->platform->getVarcharTypeDeclarationSQL([]));
242
        self::assertEquals('VARCHAR(10)', $this->platform->getVarcharTypeDeclarationSQL(['length' => 10]));
243
        self::assertEquals('CHAR(254)', $this->platform->getVarcharTypeDeclarationSQL(['fixed' => true]));
244
        self::assertEquals('CHAR(10)', $this->platform->getVarcharTypeDeclarationSQL($fullColumnDef));
245
246
        self::assertEquals('SMALLINT', $this->platform->getSmallIntTypeDeclarationSQL([]));
247
        self::assertEquals('SMALLINT', $this->platform->getSmallIntTypeDeclarationSQL(['unsigned' => true]));
248
        self::assertEquals('SMALLINT GENERATED BY DEFAULT AS IDENTITY', $this->platform->getSmallIntTypeDeclarationSQL($fullColumnDef));
249
        self::assertEquals('INTEGER', $this->platform->getIntegerTypeDeclarationSQL([]));
250
        self::assertEquals('INTEGER', $this->platform->getIntegerTypeDeclarationSQL(['unsigned' => true]));
251
        self::assertEquals('INTEGER GENERATED BY DEFAULT AS IDENTITY', $this->platform->getIntegerTypeDeclarationSQL($fullColumnDef));
252
        self::assertEquals('BIGINT', $this->platform->getBigIntTypeDeclarationSQL([]));
253
        self::assertEquals('BIGINT', $this->platform->getBigIntTypeDeclarationSQL(['unsigned' => true]));
254
        self::assertEquals('BIGINT GENERATED BY DEFAULT AS IDENTITY', $this->platform->getBigIntTypeDeclarationSQL($fullColumnDef));
255
        self::assertEquals('BLOB(1M)', $this->platform->getBlobTypeDeclarationSQL($fullColumnDef));
256
        self::assertEquals('SMALLINT', $this->platform->getBooleanTypeDeclarationSQL($fullColumnDef));
257
        self::assertEquals('CLOB(1M)', $this->platform->getClobTypeDeclarationSQL($fullColumnDef));
258
        self::assertEquals('DATE', $this->platform->getDateTypeDeclarationSQL($fullColumnDef));
259
        self::assertEquals('TIMESTAMP(0) WITH DEFAULT', $this->platform->getDateTimeTypeDeclarationSQL(['version' => true]));
260
        self::assertEquals('TIMESTAMP(0)', $this->platform->getDateTimeTypeDeclarationSQL($fullColumnDef));
261
        self::assertEquals('TIME', $this->platform->getTimeTypeDeclarationSQL($fullColumnDef));
262
    }
263
264
    public function testInitializesDoctrineTypeMappings() : void
265
    {
266
        $this->platform->initializeDoctrineTypeMappings();
267
268
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('smallint'));
269
        self::assertSame('smallint', $this->platform->getDoctrineTypeMapping('smallint'));
270
271
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('bigint'));
272
        self::assertSame('bigint', $this->platform->getDoctrineTypeMapping('bigint'));
273
274
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('integer'));
275
        self::assertSame('integer', $this->platform->getDoctrineTypeMapping('integer'));
276
277
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('time'));
278
        self::assertSame('time', $this->platform->getDoctrineTypeMapping('time'));
279
280
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('date'));
281
        self::assertSame('date', $this->platform->getDoctrineTypeMapping('date'));
282
283
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('varchar'));
284
        self::assertSame('string', $this->platform->getDoctrineTypeMapping('varchar'));
285
286
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('character'));
287
        self::assertSame('string', $this->platform->getDoctrineTypeMapping('character'));
288
289
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('clob'));
290
        self::assertSame('text', $this->platform->getDoctrineTypeMapping('clob'));
291
292
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('blob'));
293
        self::assertSame('blob', $this->platform->getDoctrineTypeMapping('blob'));
294
295
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('decimal'));
296
        self::assertSame('decimal', $this->platform->getDoctrineTypeMapping('decimal'));
297
298
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('double'));
299
        self::assertSame('float', $this->platform->getDoctrineTypeMapping('double'));
300
301
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('real'));
302
        self::assertSame('float', $this->platform->getDoctrineTypeMapping('real'));
303
304
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('timestamp'));
305
        self::assertSame('datetime', $this->platform->getDoctrineTypeMapping('timestamp'));
306
    }
307
308
    /**
309
     * {@inheritDoc}
310
     */
311
    public function getIsCommentedDoctrineType() : iterable
312
    {
313
        $types = [];
314
315
        foreach (parent::getIsCommentedDoctrineType() as $key => $value) {
316
            $types[$key] = $value;
317
        }
318
319
        $types[Types::BOOLEAN] = [Type::getType(Types::BOOLEAN), true];
320
321
        return $types;
322
    }
323
324
    public function testGeneratesDDLSnippets() : void
325
    {
326
        self::assertEquals('CREATE DATABASE foobar', $this->platform->getCreateDatabaseSQL('foobar'));
327
        self::assertEquals('DROP DATABASE foobar', $this->platform->getDropDatabaseSQL('foobar'));
328
        self::assertEquals('DECLARE GLOBAL TEMPORARY TABLE', $this->platform->getCreateTemporaryTableSnippetSQL());
329
        self::assertEquals('TRUNCATE foobar IMMEDIATE', $this->platform->getTruncateTableSQL('foobar'));
330
331
        $viewSql = 'SELECT * FROM footable';
332
        self::assertEquals('CREATE VIEW fooview AS ' . $viewSql, $this->platform->getCreateViewSQL('fooview', $viewSql));
333
        self::assertEquals('DROP VIEW fooview', $this->platform->getDropViewSQL('fooview'));
334
    }
335
336
    public function testGeneratesCreateUnnamedPrimaryKeySQL() : void
337
    {
338
        self::assertEquals(
339
            'ALTER TABLE foo ADD PRIMARY KEY (a, b)',
340
            $this->platform->getCreatePrimaryKeySQL(
341
                new Index('any_pk_name', ['a', 'b'], true, true),
342
                'foo'
343
            )
344
        );
345
    }
346
347
    public function testGeneratesSQLSnippets() : void
348
    {
349
        self::assertEquals('CURRENT DATE', $this->platform->getCurrentDateSQL());
350
        self::assertEquals('CURRENT TIME', $this->platform->getCurrentTimeSQL());
351
        self::assertEquals('CURRENT TIMESTAMP', $this->platform->getCurrentTimestampSQL());
352
        self::assertEquals("'1987/05/02' + 4 DAY", $this->platform->getDateAddDaysExpression("'1987/05/02'", '4'));
353
        self::assertEquals("'1987/05/02' + 12 HOUR", $this->platform->getDateAddHourExpression("'1987/05/02'", '12'));
354
        self::assertEquals("'1987/05/02' + 2 MINUTE", $this->platform->getDateAddMinutesExpression("'1987/05/02'", '2'));
355
        self::assertEquals("'1987/05/02' + 102 MONTH", $this->platform->getDateAddMonthExpression("'1987/05/02'", '102'));
356
        self::assertEquals("'1987/05/02' + (5 * 3) MONTH", $this->platform->getDateAddQuartersExpression("'1987/05/02'", '5'));
357
        self::assertEquals("'1987/05/02' + 1 SECOND", $this->platform->getDateAddSecondsExpression("'1987/05/02'", '1'));
358
        self::assertEquals("'1987/05/02' + (3 * 7) DAY", $this->platform->getDateAddWeeksExpression("'1987/05/02'", '3'));
359
        self::assertEquals("'1987/05/02' + 10 YEAR", $this->platform->getDateAddYearsExpression("'1987/05/02'", '10'));
360
        self::assertEquals("DAYS('1987/05/02') - DAYS('1987/04/01')", $this->platform->getDateDiffExpression("'1987/05/02'", "'1987/04/01'"));
361
        self::assertEquals("'1987/05/02' - 4 DAY", $this->platform->getDateSubDaysExpression("'1987/05/02'", '4'));
362
        self::assertEquals("'1987/05/02' - 12 HOUR", $this->platform->getDateSubHourExpression("'1987/05/02'", '12'));
363
        self::assertEquals("'1987/05/02' - 2 MINUTE", $this->platform->getDateSubMinutesExpression("'1987/05/02'", '2'));
364
        self::assertEquals("'1987/05/02' - 102 MONTH", $this->platform->getDateSubMonthExpression("'1987/05/02'", '102'));
365
        self::assertEquals("'1987/05/02' - (5 * 3) MONTH", $this->platform->getDateSubQuartersExpression("'1987/05/02'", '5'));
366
        self::assertEquals("'1987/05/02' - 1 SECOND", $this->platform->getDateSubSecondsExpression("'1987/05/02'", '1'));
367
        self::assertEquals("'1987/05/02' - (3 * 7) DAY", $this->platform->getDateSubWeeksExpression("'1987/05/02'", '3'));
368
        self::assertEquals("'1987/05/02' - 10 YEAR", $this->platform->getDateSubYearsExpression("'1987/05/02'", '10'));
369
        self::assertEquals(' WITH RR USE AND KEEP UPDATE LOCKS', $this->platform->getForUpdateSQL());
370
        self::assertEquals('LOCATE(substring_column, string_column)', $this->platform->getLocateExpression('string_column', 'substring_column'));
371
        self::assertEquals('LOCATE(substring_column, string_column, 1)', $this->platform->getLocateExpression('string_column', 'substring_column', '1'));
372
        self::assertEquals('SUBSTR(column, 5)', $this->platform->getSubstringExpression('column', '5'));
373
        self::assertEquals('SUBSTR(column, 5, 2)', $this->platform->getSubstringExpression('column', '5', '2'));
374
    }
375
376
    public function testModifiesLimitQuery() : void
377
    {
378
        self::assertEquals(
379
            'SELECT * FROM user',
380
            $this->platform->modifyLimitQuery('SELECT * FROM user', null, 0)
381
        );
382
383
        self::assertEquals(
384
            'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (SELECT * FROM user) db21) db22 WHERE db22.DC_ROWNUM <= 10',
385
            $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 0)
386
        );
387
388
        self::assertEquals(
389
            'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (SELECT * FROM user) db21) db22 WHERE db22.DC_ROWNUM <= 10',
390
            $this->platform->modifyLimitQuery('SELECT * FROM user', 10)
391
        );
392
393
        self::assertEquals(
394
            'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (SELECT * FROM user) db21) db22 WHERE db22.DC_ROWNUM >= 6 AND db22.DC_ROWNUM <= 15',
395
            $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 5)
396
        );
397
        self::assertEquals(
398
            'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (SELECT * FROM user) db21) db22 WHERE db22.DC_ROWNUM >= 6 AND db22.DC_ROWNUM <= 5',
399
            $this->platform->modifyLimitQuery('SELECT * FROM user', 0, 5)
400
        );
401
    }
402
403
    public function testPrefersIdentityColumns() : void
404
    {
405
        self::assertTrue($this->platform->prefersIdentityColumns());
406
    }
407
408
    public function testSupportsIdentityColumns() : void
409
    {
410
        self::assertTrue($this->platform->supportsIdentityColumns());
411
    }
412
413
    public function testDoesNotSupportSavePoints() : void
414
    {
415
        self::assertFalse($this->platform->supportsSavepoints());
416
    }
417
418
    public function testDoesNotSupportReleasePoints() : void
419
    {
420
        self::assertFalse($this->platform->supportsReleaseSavepoints());
421
    }
422
423
    public function testDoesNotSupportCreateDropDatabase() : void
424
    {
425
        self::assertFalse($this->platform->supportsCreateDropDatabase());
426
    }
427
428
    public function testReturnsSQLResultCasing() : void
429
    {
430
        self::assertSame('COL', $this->platform->getSQLResultCasing('cOl'));
431
    }
432
433
    protected function getBinaryDefaultLength() : int
434
    {
435
        return 1;
436
    }
437
438
    protected function getBinaryMaxLength() : int
439
    {
440
        return 32704;
441
    }
442
443
    public function testReturnsBinaryTypeDeclarationSQL() : void
444
    {
445
        self::assertSame('VARCHAR(1) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL([]));
446
        self::assertSame('VARCHAR(255) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL(['length' => 0]));
447
        self::assertSame('VARCHAR(32704) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL(['length' => 32704]));
448
449
        self::assertSame('CHAR(1) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
450
        self::assertSame('CHAR(254) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0]));
451
    }
452
453
    /**
454
     * {@inheritDoc}
455
     *
456
     * @group DBAL-234
457
     */
458
    protected function getAlterTableRenameIndexSQL() : array
459
    {
460
        return ['RENAME INDEX idx_foo TO idx_bar'];
461
    }
462
463
    /**
464
     * {@inheritDoc}
465
     *
466
     * @group DBAL-234
467
     */
468
    protected function getQuotedAlterTableRenameIndexSQL() : array
469
    {
470
        return [
471
            'RENAME INDEX "create" TO "select"',
472
            'RENAME INDEX "foo" TO "bar"',
473
        ];
474
    }
475
476
    /**
477
     * {@inheritdoc}
478
     */
479
    protected function getQuotedAlterTableRenameColumnSQL() : array
480
    {
481
        return ['ALTER TABLE mytable ' .
482
            'RENAME COLUMN unquoted1 TO unquoted ' .
483
            'RENAME COLUMN unquoted2 TO "where" ' .
484
            'RENAME COLUMN unquoted3 TO "foo" ' .
485
            'RENAME COLUMN "create" TO reserved_keyword ' .
486
            'RENAME COLUMN "table" TO "from" ' .
487
            'RENAME COLUMN "select" TO "bar" ' .
488
            'RENAME COLUMN quoted1 TO quoted ' .
489
            'RENAME COLUMN quoted2 TO "and" ' .
490
            'RENAME COLUMN quoted3 TO "baz"',
491
        ];
492
    }
493
494
    /**
495
     * {@inheritdoc}
496
     */
497
    protected function getQuotedAlterTableChangeColumnLengthSQL() : array
498
    {
499
        $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...
500
    }
501
502
    /**
503
     * {@inheritDoc}
504
     *
505
     * @group DBAL-807
506
     */
507
    protected function getAlterTableRenameIndexInSchemaSQL() : array
508
    {
509
        return ['RENAME INDEX myschema.idx_foo TO idx_bar'];
510
    }
511
512
    /**
513
     * {@inheritDoc}
514
     *
515
     * @group DBAL-807
516
     */
517
    protected function getQuotedAlterTableRenameIndexInSchemaSQL() : array
518
    {
519
        return [
520
            'RENAME INDEX "schema"."create" TO "select"',
521
            'RENAME INDEX "schema"."foo" TO "bar"',
522
        ];
523
    }
524
525
    /**
526
     * @group DBAL-423
527
     */
528
    public function testReturnsGuidTypeDeclarationSQL() : void
529
    {
530
        self::assertSame('CHAR(36)', $this->platform->getGuidTypeDeclarationSQL([]));
531
    }
532
533
    /**
534
     * {@inheritdoc}
535
     */
536
    public function getAlterTableRenameColumnSQL() : array
537
    {
538
        return ['ALTER TABLE foo RENAME COLUMN bar TO baz'];
539
    }
540
541
    /**
542
     * {@inheritdoc}
543
     */
544
    protected function getQuotesTableIdentifiersInAlterTableSQL() : array
545
    {
546
        return [
547
            'ALTER TABLE "foo" DROP FOREIGN KEY fk1',
548
            'ALTER TABLE "foo" DROP FOREIGN KEY fk2',
549
            'ALTER TABLE "foo" ' .
550
            'ADD COLUMN bloo INTEGER NOT NULL WITH DEFAULT ' .
551
            'DROP COLUMN baz ' .
552
            'ALTER COLUMN bar DROP NOT NULL ' .
553
            'RENAME COLUMN id TO war',
554
            'CALL SYSPROC.ADMIN_CMD (\'REORG TABLE "foo"\')',
555
            'RENAME TABLE "foo" TO "table"',
556
            'ALTER TABLE "table" ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id)',
557
            'ALTER TABLE "table" ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id)',
558
        ];
559
    }
560
561
    /**
562
     * {@inheritdoc}
563
     */
564
    protected function getCommentOnColumnSQL() : array
565
    {
566
        return [
567
            'COMMENT ON COLUMN foo.bar IS \'comment\'',
568
            'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
569
            'COMMENT ON COLUMN "select"."from" IS \'comment\'',
570
        ];
571
    }
572
573
    /**
574
     * @group DBAL-944
575
     * @dataProvider getGeneratesAlterColumnSQL
576
     */
577
    public function testGeneratesAlterColumnSQL(string $changedProperty, Column $column, ?string $expectedSQLClause = null) : void
578
    {
579
        $tableDiff                        = new TableDiff('foo');
580
        $tableDiff->fromTable             = new Table('foo');
581
        $tableDiff->changedColumns['bar'] = new ColumnDiff('bar', $column, [$changedProperty]);
582
583
        $expectedSQL = [];
584
585
        if ($expectedSQLClause !== null) {
586
            $expectedSQL[] = 'ALTER TABLE foo ALTER COLUMN bar ' . $expectedSQLClause;
587
        }
588
589
        $expectedSQL[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE foo')";
590
591
        self::assertSame($expectedSQL, $this->platform->getAlterTableSQL($tableDiff));
592
    }
593
594
    /**
595
     * @return mixed[][]
596
     */
597
    public static function getGeneratesAlterColumnSQL() : iterable
598
    {
599
        return [
600
            [
601
                'columnDefinition',
602
                new Column('bar', Type::getType('decimal'), ['columnDefinition' => 'MONEY NOT NULL']),
603
                'MONEY NOT NULL',
604
            ],
605
            [
606
                'type',
607
                new Column('bar', Type::getType('integer')),
608
                'SET DATA TYPE INTEGER',
609
            ],
610
            [
611
                'length',
612
                new Column('bar', Type::getType('string'), ['length' => 100]),
613
                'SET DATA TYPE VARCHAR(100)',
614
            ],
615
            [
616
                'precision',
617
                new Column('bar', Type::getType('decimal'), ['precision' => 10, 'scale' => 2]),
618
                'SET DATA TYPE NUMERIC(10, 2)',
619
            ],
620
            [
621
                'scale',
622
                new Column('bar', Type::getType('decimal'), ['precision' => 5, 'scale' => 4]),
623
                'SET DATA TYPE NUMERIC(5, 4)',
624
            ],
625
            [
626
                'fixed',
627
                new Column('bar', Type::getType('string'), ['length' => 20, 'fixed' => true]),
628
                'SET DATA TYPE CHAR(20)',
629
            ],
630
            [
631
                'notnull',
632
                new Column('bar', Type::getType('string'), ['notnull' => true]),
633
                'SET NOT NULL',
634
            ],
635
            [
636
                'notnull',
637
                new Column('bar', Type::getType('string'), ['notnull' => false]),
638
                'DROP NOT NULL',
639
            ],
640
            [
641
                'default',
642
                new Column('bar', Type::getType('string'), ['default' => 'foo']),
643
                "SET DEFAULT 'foo'",
644
            ],
645
            [
646
                'default',
647
                new Column('bar', Type::getType('integer'), ['autoincrement' => true, 'default' => 666]),
648
                null,
649
            ],
650
            [
651
                'default',
652
                new Column('bar', Type::getType('string')),
653
                'DROP DEFAULT',
654
            ],
655
        ];
656
    }
657
658
    /**
659
     * {@inheritdoc}
660
     */
661
    protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL() : string
662
    {
663
        return 'CONSTRAINT "select" UNIQUE (foo)';
664
    }
665
666
    /**
667
     * {@inheritdoc}
668
     */
669
    protected function getQuotesReservedKeywordInIndexDeclarationSQL() : string
670
    {
671
        return ''; // not supported by this platform
672
    }
673
674
    /**
675
     * {@inheritdoc}
676
     */
677
    protected function getQuotesReservedKeywordInTruncateTableSQL() : string
678
    {
679
        return 'TRUNCATE "select" IMMEDIATE';
680
    }
681
682
    /**
683
     * {@inheritdoc}
684
     */
685
    protected function supportsInlineIndexDeclaration() : bool
686
    {
687
        return false;
688
    }
689
690
    /**
691
     * {@inheritdoc}
692
     */
693
    protected function supportsCommentOnStatement() : bool
694
    {
695
        return true;
696
    }
697
698
    /**
699
     * {@inheritdoc}
700
     */
701
    protected function getAlterStringToFixedStringSQL() : array
702
    {
703
        return [
704
            'ALTER TABLE mytable ALTER COLUMN name SET DATA TYPE CHAR(2)',
705
            'CALL SYSPROC.ADMIN_CMD (\'REORG TABLE mytable\')',
706
        ];
707
    }
708
709
    /**
710
     * {@inheritdoc}
711
     */
712
    protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL() : array
713
    {
714
        return ['RENAME INDEX idx_foo TO idx_foo_renamed'];
715
    }
716
717
    /**
718
     * @group DBAL-2436
719
     */
720
    public function testQuotesTableNameInListTableColumnsSQL() : void
721
    {
722
        self::assertStringContainsStringIgnoringCase(
723
            "'Foo''Bar\\'",
724
            $this->platform->getListTableColumnsSQL("Foo'Bar\\")
725
        );
726
    }
727
728
    /**
729
     * @group DBAL-2436
730
     */
731
    public function testQuotesTableNameInListTableIndexesSQL() : void
732
    {
733
        self::assertStringContainsStringIgnoringCase(
734
            "'Foo''Bar\\'",
735
            $this->platform->getListTableIndexesSQL("Foo'Bar\\")
736
        );
737
    }
738
739
    /**
740
     * @group DBAL-2436
741
     */
742
    public function testQuotesTableNameInListTableForeignKeysSQL() : void
743
    {
744
        self::assertStringContainsStringIgnoringCase(
745
            "'Foo''Bar\\'",
746
            $this->platform->getListTableForeignKeysSQL("Foo'Bar\\")
747
        );
748
    }
749
}
750