Failed Conditions
Pull Request — develop (#3348)
by Sergei
38:24 queued 35:29
created

testGetNullCommentOnColumnSQL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Platforms;
4
5
use Doctrine\DBAL\Schema\Column;
6
use Doctrine\DBAL\Schema\ColumnDiff;
7
use Doctrine\DBAL\Schema\Comparator;
8
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
9
use Doctrine\DBAL\Schema\Sequence;
10
use Doctrine\DBAL\Schema\Table;
11
use Doctrine\DBAL\Schema\TableDiff;
12
use Doctrine\DBAL\TransactionIsolationLevel;
13
use Doctrine\DBAL\Types\Type;
14
use function sprintf;
15
16
abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCase
17
{
18
    public function getGenerateTableSql() : string
19
    {
20
        return 'CREATE TABLE test (id SERIAL NOT NULL, test VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))';
21
    }
22
23
    /**
24
     * {@inheritDoc}
25
     */
26
    public function getGenerateTableWithMultiColumnUniqueIndexSql() : array
27
    {
28
        return [
29
            'CREATE TABLE test (foo VARCHAR(255) DEFAULT NULL, bar VARCHAR(255) DEFAULT NULL)',
30
            'CREATE UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA ON test (foo, bar)',
31
        ];
32
    }
33
34
    /**
35
     * {@inheritDoc}
36
     */
37
    public function getGenerateAlterTableSql() : array
38
    {
39
        return [
40
            'ALTER TABLE mytable ADD quota INT DEFAULT NULL',
41
            'ALTER TABLE mytable DROP foo',
42
            'ALTER TABLE mytable ALTER bar TYPE VARCHAR(255)',
43
            "ALTER TABLE mytable ALTER bar SET DEFAULT 'def'",
44
            'ALTER TABLE mytable ALTER bar SET NOT NULL',
45
            'ALTER TABLE mytable ALTER bloo TYPE BOOLEAN',
46
            "ALTER TABLE mytable ALTER bloo SET DEFAULT 'false'",
47
            'ALTER TABLE mytable ALTER bloo SET NOT NULL',
48
            'ALTER TABLE mytable RENAME TO userlist',
49
        ];
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 getGenerateForeignKeySql() : string
58
    {
59
        return 'ALTER TABLE test ADD FOREIGN KEY (fk_name_id) REFERENCES other_table (id) NOT DEFERRABLE INITIALLY IMMEDIATE';
60
    }
61
62
    public function testGeneratesForeignKeySqlForNonStandardOptions() : void
63
    {
64
        $foreignKey = new ForeignKeyConstraint(
65
            ['foreign_id'],
66
            'my_table',
67
            ['id'],
68
            'my_fk',
69
            ['onDelete' => 'CASCADE']
70
        );
71
        self::assertEquals(
72
            'CONSTRAINT my_fk FOREIGN KEY (foreign_id) REFERENCES my_table (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE',
73
            $this->platform->getForeignKeyDeclarationSQL($foreignKey)
74
        );
75
76
        $foreignKey = new ForeignKeyConstraint(
77
            ['foreign_id'],
78
            'my_table',
79
            ['id'],
80
            'my_fk',
81
            ['match' => 'full']
82
        );
83
        self::assertEquals(
84
            'CONSTRAINT my_fk FOREIGN KEY (foreign_id) REFERENCES my_table (id) MATCH full NOT DEFERRABLE INITIALLY IMMEDIATE',
85
            $this->platform->getForeignKeyDeclarationSQL($foreignKey)
86
        );
87
88
        $foreignKey = new ForeignKeyConstraint(
89
            ['foreign_id'],
90
            'my_table',
91
            ['id'],
92
            'my_fk',
93
            ['deferrable' => true]
94
        );
95
        self::assertEquals(
96
            'CONSTRAINT my_fk FOREIGN KEY (foreign_id) REFERENCES my_table (id) DEFERRABLE INITIALLY IMMEDIATE',
97
            $this->platform->getForeignKeyDeclarationSQL($foreignKey)
98
        );
99
100
        $foreignKey = new ForeignKeyConstraint(
101
            ['foreign_id'],
102
            'my_table',
103
            ['id'],
104
            'my_fk',
105
            ['deferred' => true]
106
        );
107
        self::assertEquals(
108
            'CONSTRAINT my_fk FOREIGN KEY (foreign_id) REFERENCES my_table (id) NOT DEFERRABLE INITIALLY DEFERRED',
109
            $this->platform->getForeignKeyDeclarationSQL($foreignKey)
110
        );
111
112
        $foreignKey = new ForeignKeyConstraint(
113
            ['foreign_id'],
114
            'my_table',
115
            ['id'],
116
            'my_fk',
117
            ['feferred' => true]
118
        );
119
        self::assertEquals(
120
            'CONSTRAINT my_fk FOREIGN KEY (foreign_id) REFERENCES my_table (id) NOT DEFERRABLE INITIALLY DEFERRED',
121
            $this->platform->getForeignKeyDeclarationSQL($foreignKey)
122
        );
123
124
        $foreignKey = new ForeignKeyConstraint(
125
            ['foreign_id'],
126
            'my_table',
127
            ['id'],
128
            'my_fk',
129
            ['deferrable' => true, 'deferred' => true, 'match' => 'full']
130
        );
131
        self::assertEquals(
132
            'CONSTRAINT my_fk FOREIGN KEY (foreign_id) REFERENCES my_table (id) MATCH full DEFERRABLE INITIALLY DEFERRED',
133
            $this->platform->getForeignKeyDeclarationSQL($foreignKey)
134
        );
135
    }
136
137
    public function testGeneratesSqlSnippets() : void
138
    {
139
        self::assertEquals('SIMILAR TO', $this->platform->getRegexpExpression(), 'Regular expression operator is not correct');
140
        self::assertEquals('"', $this->platform->getIdentifierQuoteCharacter(), 'Identifier quote character is not correct');
141
        self::assertEquals('column1 || column2 || column3', $this->platform->getConcatExpression('column1', 'column2', 'column3'), 'Concatenation expression is not correct');
142
        self::assertEquals('SUBSTRING(column FROM 5)', $this->platform->getSubstringExpression('column', 5), 'Substring expression without length is not correct');
143
        self::assertEquals('SUBSTRING(column FROM 1 FOR 5)', $this->platform->getSubstringExpression('column', 1, 5), 'Substring expression with length is not correct');
144
    }
145
146
    public function testGeneratesTransactionCommands() : void
147
    {
148
        self::assertEquals(
149
            'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ UNCOMMITTED',
150
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_UNCOMMITTED)
151
        );
152
        self::assertEquals(
153
            'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED',
154
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_COMMITTED)
155
        );
156
        self::assertEquals(
157
            'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL REPEATABLE READ',
158
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::REPEATABLE_READ)
159
        );
160
        self::assertEquals(
161
            'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE',
162
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::SERIALIZABLE)
163
        );
164
    }
165
166
    public function testGeneratesDDLSnippets() : void
167
    {
168
        self::assertEquals('CREATE DATABASE foobar', $this->platform->getCreateDatabaseSQL('foobar'));
169
        self::assertEquals('DROP DATABASE foobar', $this->platform->getDropDatabaseSQL('foobar'));
170
        self::assertEquals('DROP TABLE foobar', $this->platform->getDropTableSQL('foobar'));
171
    }
172
173
    public function testGenerateTableWithAutoincrement() : void
174
    {
175
        $table  = new Table('autoinc_table');
176
        $column = $table->addColumn('id', 'integer');
177
        $column->setAutoincrement(true);
178
179
        self::assertEquals(['CREATE TABLE autoinc_table (id SERIAL NOT NULL)'], $this->platform->getCreateTableSQL($table));
180
    }
181
182
    /**
183
     * @return mixed[][]
184
     */
185
    public static function serialTypes() : iterable
186
    {
187
        return [
188
            ['integer', 'SERIAL'],
189
            ['bigint', 'BIGSERIAL'],
190
        ];
191
    }
192
193
    /**
194
     * @dataProvider serialTypes
195
     * @group 2906
196
     */
197
    public function testGenerateTableWithAutoincrementDoesNotSetDefault(string $type, string $definition) : void
198
    {
199
        $table  = new Table('autoinc_table_notnull');
200
        $column = $table->addColumn('id', $type);
201
        $column->setAutoIncrement(true);
202
        $column->setNotNull(false);
203
204
        $sql = $this->platform->getCreateTableSQL($table);
205
206
        self::assertEquals([sprintf('CREATE TABLE autoinc_table_notnull (id %s)', $definition)], $sql);
207
    }
208
209
    /**
210
     * @dataProvider serialTypes
211
     * @group 2906
212
     */
213
    public function testCreateTableWithAutoincrementAndNotNullAddsConstraint(string $type, string $definition) : void
214
    {
215
        $table  = new Table('autoinc_table_notnull_enabled');
216
        $column = $table->addColumn('id', $type);
217
        $column->setAutoIncrement(true);
218
        $column->setNotNull(true);
219
220
        $sql = $this->platform->getCreateTableSQL($table);
221
222
        self::assertEquals([sprintf('CREATE TABLE autoinc_table_notnull_enabled (id %s NOT NULL)', $definition)], $sql);
223
    }
224
225
    /**
226
     * @dataProvider serialTypes
227
     * @group 2906
228
     */
229
    public function testGetDefaultValueDeclarationSQLIgnoresTheDefaultKeyWhenTheFieldIsSerial(string $type) : void
230
    {
231
        $sql = $this->platform->getDefaultValueDeclarationSQL(
232
            [
233
                'autoincrement' => true,
234
                'type'          => Type::getType($type),
235
                'default'       => 1,
236
            ]
237
        );
238
239
        self::assertSame('', $sql);
240
    }
241
242
    public function testGeneratesTypeDeclarationForIntegers() : void
243
    {
244
        self::assertEquals(
245
            'INT',
246
            $this->platform->getIntegerTypeDeclarationSQL([])
247
        );
248
        self::assertEquals(
249
            'SERIAL',
250
            $this->platform->getIntegerTypeDeclarationSQL(['autoincrement' => true])
251
        );
252
        self::assertEquals(
253
            'SERIAL',
254
            $this->platform->getIntegerTypeDeclarationSQL(
255
                ['autoincrement' => true, 'primary' => true]
256
            )
257
        );
258
    }
259
260
    public function testGeneratesTypeDeclarationForStrings() : void
261
    {
262
        self::assertEquals(
263
            'CHAR(10)',
264
            $this->platform->getVarcharTypeDeclarationSQL(
265
                ['length' => 10, 'fixed' => true]
266
            )
267
        );
268
        self::assertEquals(
269
            'VARCHAR(50)',
270
            $this->platform->getVarcharTypeDeclarationSQL(['length' => 50]),
271
            'Variable string declaration is not correct'
272
        );
273
        self::assertEquals(
274
            'VARCHAR(255)',
275
            $this->platform->getVarcharTypeDeclarationSQL([]),
276
            'Long string declaration is not correct'
277
        );
278
    }
279
280
    public function getGenerateUniqueIndexSql() : string
281
    {
282
        return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
283
    }
284
285
    public function testGeneratesSequenceSqlCommands() : void
286
    {
287
        $sequence = new Sequence('myseq', 20, 1);
288
        self::assertEquals(
289
            'CREATE SEQUENCE myseq INCREMENT BY 20 MINVALUE 1 START 1',
290
            $this->platform->getCreateSequenceSQL($sequence)
291
        );
292
        self::assertEquals(
293
            'DROP SEQUENCE myseq CASCADE',
294
            $this->platform->getDropSequenceSQL('myseq')
295
        );
296
        self::assertEquals(
297
            "SELECT NEXTVAL('myseq')",
298
            $this->platform->getSequenceNextValSQL('myseq')
299
        );
300
    }
301
302
    public function testDoesNotPreferIdentityColumns() : void
303
    {
304
        self::assertFalse($this->platform->prefersIdentityColumns());
305
    }
306
307
    public function testPrefersSequences() : void
308
    {
309
        self::assertTrue($this->platform->prefersSequences());
310
    }
311
312
    public function testSupportsIdentityColumns() : void
313
    {
314
        self::assertTrue($this->platform->supportsIdentityColumns());
315
    }
316
317
    public function testSupportsSavePoints() : void
318
    {
319
        self::assertTrue($this->platform->supportsSavepoints());
320
    }
321
322
    public function testSupportsSequences() : void
323
    {
324
        self::assertTrue($this->platform->supportsSequences());
325
    }
326
327
    /**
328
     * {@inheritdoc}
329
     */
330
    protected function supportsCommentOnStatement() : bool
331
    {
332
        return true;
333
    }
334
335
    public function testModifyLimitQuery() : void
336
    {
337
        $sql = $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 0);
338
        self::assertEquals('SELECT * FROM user LIMIT 10', $sql);
339
    }
340
341
    public function testModifyLimitQueryWithEmptyOffset() : void
342
    {
343
        $sql = $this->platform->modifyLimitQuery('SELECT * FROM user', 10);
344
        self::assertEquals('SELECT * FROM user LIMIT 10', $sql);
345
    }
346
347
    /**
348
     * {@inheritDoc}
349
     */
350
    public function getCreateTableColumnCommentsSQL() : array
351
    {
352
        return [
353
            'CREATE TABLE test (id INT NOT NULL, PRIMARY KEY(id))',
354
            "COMMENT ON COLUMN test.id IS 'This is a comment'",
355
        ];
356
    }
357
358
    /**
359
     * {@inheritDoc}
360
     */
361
    public function getAlterTableColumnCommentsSQL() : array
362
    {
363
        return [
364
            'ALTER TABLE mytable ADD quota INT NOT NULL',
365
            "COMMENT ON COLUMN mytable.quota IS 'A comment'",
366
            "COMMENT ON COLUMN mytable.foo IS ''",
367
            "COMMENT ON COLUMN mytable.baz IS 'B comment'",
368
        ];
369
    }
370
371
    /**
372
     * {@inheritDoc}
373
     */
374
    public function getCreateTableColumnTypeCommentsSQL() : array
375
    {
376
        return [
377
            'CREATE TABLE test (id INT NOT NULL, data TEXT NOT NULL, PRIMARY KEY(id))',
378
            "COMMENT ON COLUMN test.data IS '(DC2Type:array)'",
379
        ];
380
    }
381
382
    /**
383
     * {@inheritDoc}
384
     */
385
    protected function getQuotedColumnInPrimaryKeySQL() : array
386
    {
387
        return ['CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL, PRIMARY KEY("create"))'];
388
    }
389
390
    /**
391
     * {@inheritDoc}
392
     */
393
    protected function getQuotedColumnInIndexSQL() : array
394
    {
395
        return [
396
            'CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL)',
397
            'CREATE INDEX IDX_22660D028FD6E0FB ON "quoted" ("create")',
398
        ];
399
    }
400
401
    /**
402
     * {@inheritDoc}
403
     */
404
    protected function getQuotedNameInIndexSQL() : array
405
    {
406
        return [
407
            'CREATE TABLE test (column1 VARCHAR(255) NOT NULL)',
408
            'CREATE INDEX "key" ON test (column1)',
409
        ];
410
    }
411
412
    /**
413
     * {@inheritDoc}
414
     */
415
    protected function getQuotedColumnInForeignKeySQL() : array
416
    {
417
        return [
418
            'CREATE TABLE "quoted" ("create" VARCHAR(255) NOT NULL, foo VARCHAR(255) NOT NULL, "bar" VARCHAR(255) NOT NULL)',
419
            'ALTER TABLE "quoted" ADD CONSTRAINT FK_WITH_RESERVED_KEYWORD FOREIGN KEY ("create", foo, "bar") REFERENCES "foreign" ("create", bar, "foo-bar") NOT DEFERRABLE INITIALLY IMMEDIATE',
420
            'ALTER TABLE "quoted" ADD CONSTRAINT FK_WITH_NON_RESERVED_KEYWORD FOREIGN KEY ("create", foo, "bar") REFERENCES foo ("create", bar, "foo-bar") NOT DEFERRABLE INITIALLY IMMEDIATE',
421
            'ALTER TABLE "quoted" ADD CONSTRAINT FK_WITH_INTENDED_QUOTATION FOREIGN KEY ("create", foo, "bar") REFERENCES "foo-bar" ("create", bar, "foo-bar") NOT DEFERRABLE INITIALLY IMMEDIATE',
422
        ];
423
    }
424
425
    /**
426
     * @group DBAL-457
427
     * @dataProvider pgBooleanProvider
428
     */
429
    public function testConvertBooleanAsLiteralStrings(
430
        string $databaseValue,
431
        string $preparedStatementValue,
432
        int $integerValue,
0 ignored issues
show
Unused Code introduced by
The parameter $integerValue is not used and could be removed. ( Ignorable by Annotation )

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

432
        /** @scrutinizer ignore-unused */ int $integerValue,

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

Loading history...
433
        bool $booleanValue
0 ignored issues
show
Unused Code introduced by
The parameter $booleanValue is not used and could be removed. ( Ignorable by Annotation )

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

433
        /** @scrutinizer ignore-unused */ bool $booleanValue

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

Loading history...
434
    ) : void {
435
        $platform = $this->createPlatform();
436
437
        self::assertEquals($preparedStatementValue, $platform->convertBooleans($databaseValue));
438
    }
439
440
    /**
441
     * @group DBAL-457
442
     */
443
    public function testConvertBooleanAsLiteralIntegers() : void
444
    {
445
        $platform = $this->createPlatform();
446
        $platform->setUseBooleanTrueFalseStrings(false);
0 ignored issues
show
Bug introduced by
The method setUseBooleanTrueFalseStrings() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. It seems like you code against a sub-type of Doctrine\DBAL\Platforms\AbstractPlatform such as Doctrine\DBAL\Platforms\PostgreSqlPlatform. ( Ignorable by Annotation )

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

446
        $platform->/** @scrutinizer ignore-call */ 
447
                   setUseBooleanTrueFalseStrings(false);
Loading history...
447
448
        self::assertEquals(1, $platform->convertBooleans(true));
449
        self::assertEquals(1, $platform->convertBooleans('1'));
450
451
        self::assertEquals(0, $platform->convertBooleans(false));
452
        self::assertEquals(0, $platform->convertBooleans('0'));
453
    }
454
455
    /**
456
     * @group DBAL-630
457
     * @dataProvider pgBooleanProvider
458
     */
459
    public function testConvertBooleanAsDatabaseValueStrings(
460
        string $databaseValue,
0 ignored issues
show
Unused Code introduced by
The parameter $databaseValue is not used and could be removed. ( Ignorable by Annotation )

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

460
        /** @scrutinizer ignore-unused */ string $databaseValue,

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

Loading history...
461
        string $preparedStatementValue,
0 ignored issues
show
Unused Code introduced by
The parameter $preparedStatementValue is not used and could be removed. ( Ignorable by Annotation )

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

461
        /** @scrutinizer ignore-unused */ string $preparedStatementValue,

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

Loading history...
462
        int $integerValue,
463
        bool $booleanValue
464
    ) : void {
465
        $platform = $this->createPlatform();
466
467
        self::assertSame($integerValue, $platform->convertBooleansToDatabaseValue($booleanValue));
468
    }
469
470
    /**
471
     * @group DBAL-630
472
     */
473
    public function testConvertBooleanAsDatabaseValueIntegers() : void
474
    {
475
        $platform = $this->createPlatform();
476
        $platform->setUseBooleanTrueFalseStrings(false);
477
478
        self::assertSame(1, $platform->convertBooleansToDatabaseValue(true));
479
        self::assertSame(0, $platform->convertBooleansToDatabaseValue(false));
480
    }
481
482
    /**
483
     * @dataProvider pgBooleanProvider
484
     */
485
    public function testConvertFromBoolean(string $databaseValue, string $prepareStatementValue, int $integerValue, bool $booleanValue) : void
0 ignored issues
show
Unused Code introduced by
The parameter $prepareStatementValue is not used and could be removed. ( Ignorable by Annotation )

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

485
    public function testConvertFromBoolean(string $databaseValue, /** @scrutinizer ignore-unused */ string $prepareStatementValue, int $integerValue, bool $booleanValue) : void

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

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

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

485
    public function testConvertFromBoolean(string $databaseValue, string $prepareStatementValue, /** @scrutinizer ignore-unused */ int $integerValue, bool $booleanValue) : void

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

Loading history...
486
    {
487
        $platform = $this->createPlatform();
488
489
        self::assertSame($booleanValue, $platform->convertFromBoolean($databaseValue));
490
    }
491
492
    /**
493
     * @expectedException        UnexpectedValueException
494
     * @expectedExceptionMessage Unrecognized boolean literal 'my-bool'
495
     */
496
    public function testThrowsExceptionWithInvalidBooleanLiteral() : void
497
    {
498
        $platform = $this->createPlatform()->convertBooleansToDatabaseValue('my-bool');
0 ignored issues
show
Unused Code introduced by
The assignment to $platform is dead and can be removed.
Loading history...
499
    }
500
501
    public function testGetCreateSchemaSQL() : void
502
    {
503
        $schemaName = 'schema';
504
        $sql        = $this->platform->getCreateSchemaSQL($schemaName);
505
        self::assertEquals('CREATE SCHEMA ' . $schemaName, $sql);
506
    }
507
508
    public function testAlterDecimalPrecisionScale() : void
509
    {
510
        $table = new Table('mytable');
511
        $table->addColumn('dfoo1', 'decimal');
512
        $table->addColumn('dfoo2', 'decimal', ['precision' => 10, 'scale' => 6]);
513
        $table->addColumn('dfoo3', 'decimal', ['precision' => 10, 'scale' => 6]);
514
        $table->addColumn('dfoo4', 'decimal', ['precision' => 10, 'scale' => 6]);
515
516
        $tableDiff            = new TableDiff('mytable');
517
        $tableDiff->fromTable = $table;
518
519
        $tableDiff->changedColumns['dloo1'] = new ColumnDiff(
520
            'dloo1',
521
            new Column(
522
                'dloo1',
523
                Type::getType('decimal'),
524
                ['precision' => 16, 'scale' => 6]
525
            ),
526
            ['precision']
527
        );
528
        $tableDiff->changedColumns['dloo2'] = new ColumnDiff(
529
            'dloo2',
530
            new Column(
531
                'dloo2',
532
                Type::getType('decimal'),
533
                ['precision' => 10, 'scale' => 4]
534
            ),
535
            ['scale']
536
        );
537
        $tableDiff->changedColumns['dloo3'] = new ColumnDiff(
538
            'dloo3',
539
            new Column(
540
                'dloo3',
541
                Type::getType('decimal'),
542
                ['precision' => 10, 'scale' => 6]
543
            ),
544
            []
545
        );
546
        $tableDiff->changedColumns['dloo4'] = new ColumnDiff(
547
            'dloo4',
548
            new Column(
549
                'dloo4',
550
                Type::getType('decimal'),
551
                ['precision' => 16, 'scale' => 8]
552
            ),
553
            ['precision', 'scale']
554
        );
555
556
        $sql = $this->platform->getAlterTableSQL($tableDiff);
557
558
        $expectedSql = [
559
            'ALTER TABLE mytable ALTER dloo1 TYPE NUMERIC(16, 6)',
560
            'ALTER TABLE mytable ALTER dloo2 TYPE NUMERIC(10, 4)',
561
            'ALTER TABLE mytable ALTER dloo4 TYPE NUMERIC(16, 8)',
562
        ];
563
564
        self::assertEquals($expectedSql, $sql);
565
    }
566
567
    /**
568
     * @group DBAL-365
569
     */
570
    public function testDroppingConstraintsBeforeColumns() : void
571
    {
572
        $newTable = new Table('mytable');
573
        $newTable->addColumn('id', 'integer');
574
        $newTable->setPrimaryKey(['id']);
575
576
        $oldTable = clone $newTable;
577
        $oldTable->addColumn('parent_id', 'integer');
578
        $oldTable->addUnnamedForeignKeyConstraint('mytable', ['parent_id'], ['id']);
1 ignored issue
show
Deprecated Code introduced by
The function Doctrine\DBAL\Schema\Tab...dForeignKeyConstraint() has been deprecated: Use {@link addForeignKeyConstraint} ( Ignorable by Annotation )

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

578
        /** @scrutinizer ignore-deprecated */ $oldTable->addUnnamedForeignKeyConstraint('mytable', ['parent_id'], ['id']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
579
580
        $comparator = new Comparator();
581
        $tableDiff  = $comparator->diffTable($oldTable, $newTable);
582
583
        $sql = $this->platform->getAlterTableSQL($tableDiff);
0 ignored issues
show
Bug introduced by
It seems like $tableDiff can also be of type false; however, parameter $diff of Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() does only seem to accept Doctrine\DBAL\Schema\TableDiff, maybe add an additional type check? ( Ignorable by Annotation )

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

583
        $sql = $this->platform->getAlterTableSQL(/** @scrutinizer ignore-type */ $tableDiff);
Loading history...
584
585
        $expectedSql = [
586
            'ALTER TABLE mytable DROP CONSTRAINT FK_6B2BD609727ACA70',
587
            'DROP INDEX IDX_6B2BD609727ACA70',
588
            'ALTER TABLE mytable DROP parent_id',
589
        ];
590
591
        self::assertEquals($expectedSql, $sql);
592
    }
593
594
    /**
595
     * @group DBAL-563
596
     */
597
    public function testUsesSequenceEmulatedIdentityColumns() : void
598
    {
599
        self::assertTrue($this->platform->usesSequenceEmulatedIdentityColumns());
600
    }
601
602
    /**
603
     * @group DBAL-563
604
     */
605
    public function testReturnsIdentitySequenceName() : void
606
    {
607
        self::assertSame('mytable_mycolumn_seq', $this->platform->getIdentitySequenceName('mytable', 'mycolumn'));
608
    }
609
610
    /**
611
     * @dataProvider dataCreateSequenceWithCache
612
     * @group DBAL-139
613
     */
614
    public function testCreateSequenceWithCache(int $cacheSize, string $expectedSql) : void
615
    {
616
        $sequence = new Sequence('foo', 1, 1, $cacheSize);
617
        self::assertContains($expectedSql, $this->platform->getCreateSequenceSQL($sequence));
618
    }
619
620
    /**
621
     * @return mixed[][]
622
     */
623
    public static function dataCreateSequenceWithCache() : iterable
624
    {
625
        return [
626
            [3, 'CACHE 3'],
627
        ];
628
    }
629
630
    protected function getBinaryDefaultLength() : int
631
    {
632
        return 0;
633
    }
634
635
    protected function getBinaryMaxLength() : int
636
    {
637
        return 0;
638
    }
639
640
    public function testReturnsBinaryTypeDeclarationSQL() : void
641
    {
642
        self::assertSame('BYTEA', $this->platform->getBinaryTypeDeclarationSQL([]));
643
        self::assertSame('BYTEA', $this->platform->getBinaryTypeDeclarationSQL(['length' => 0]));
644
        self::assertSame('BYTEA', $this->platform->getBinaryTypeDeclarationSQL(['length' => 9999999]));
645
646
        self::assertSame('BYTEA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
647
        self::assertSame('BYTEA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0]));
648
        self::assertSame('BYTEA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 9999999]));
649
    }
650
651
    public function testDoesNotPropagateUnnecessaryTableAlterationOnBinaryType() : void
652
    {
653
        $table1 = new Table('mytable');
654
        $table1->addColumn('column_varbinary', 'binary');
655
        $table1->addColumn('column_binary', 'binary', ['fixed' => true]);
656
        $table1->addColumn('column_blob', 'blob');
657
658
        $table2 = new Table('mytable');
659
        $table2->addColumn('column_varbinary', 'binary', ['fixed' => true]);
660
        $table2->addColumn('column_binary', 'binary');
661
        $table2->addColumn('column_blob', 'binary');
662
663
        $comparator = new Comparator();
664
665
        // VARBINARY -> BINARY
666
        // BINARY    -> VARBINARY
667
        // BLOB      -> VARBINARY
668
        self::assertEmpty($this->platform->getAlterTableSQL($comparator->diffTable($table1, $table2)));
0 ignored issues
show
Bug introduced by
It seems like $comparator->diffTable($table1, $table2) can also be of type false; however, parameter $diff of Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() does only seem to accept Doctrine\DBAL\Schema\TableDiff, maybe add an additional type check? ( Ignorable by Annotation )

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

668
        self::assertEmpty($this->platform->getAlterTableSQL(/** @scrutinizer ignore-type */ $comparator->diffTable($table1, $table2)));
Loading history...
669
670
        $table2 = new Table('mytable');
671
        $table2->addColumn('column_varbinary', 'binary', ['length' => 42]);
672
        $table2->addColumn('column_binary', 'blob');
673
        $table2->addColumn('column_blob', 'binary', ['length' => 11, 'fixed' => true]);
674
675
        // VARBINARY -> VARBINARY with changed length
676
        // BINARY    -> BLOB
677
        // BLOB      -> BINARY
678
        self::assertEmpty($this->platform->getAlterTableSQL($comparator->diffTable($table1, $table2)));
679
680
        $table2 = new Table('mytable');
681
        $table2->addColumn('column_varbinary', 'blob');
682
        $table2->addColumn('column_binary', 'binary', ['length' => 42, 'fixed' => true]);
683
        $table2->addColumn('column_blob', 'blob');
684
685
        // VARBINARY -> BLOB
686
        // BINARY    -> BINARY with changed length
687
        // BLOB      -> BLOB
688
        self::assertEmpty($this->platform->getAlterTableSQL($comparator->diffTable($table1, $table2)));
689
    }
690
691
    /**
692
     * {@inheritDoc}
693
     *
694
     * @group DBAL-234
695
     */
696
    protected function getAlterTableRenameIndexSQL() : array
697
    {
698
        return ['ALTER INDEX idx_foo RENAME TO idx_bar'];
699
    }
700
701
    /**
702
     * {@inheritDoc}
703
     *
704
     * @group DBAL-234
705
     */
706
    protected function getQuotedAlterTableRenameIndexSQL() : array
707
    {
708
        return [
709
            'ALTER INDEX "create" RENAME TO "select"',
710
            'ALTER INDEX "foo" RENAME TO "bar"',
711
        ];
712
    }
713
714
    /**
715
     * PostgreSQL boolean strings provider
716
     *
717
     * @return mixed[][]
718
     */
719
    public static function pgBooleanProvider() : iterable
720
    {
721
        return [
722
            // Database value, prepared statement value, boolean integer value, boolean value.
723
            ['t', 'true', 1, true],
724
            ['true', 'true', 1, true],
725
            ['y', 'true', 1, true],
726
            ['yes', 'true', 1, true],
727
            ['on', 'true', 1, true],
728
            ['1', 'true', 1, true],
729
730
            ['f', 'false', 0, false],
731
            ['false', 'false', 0, false],
732
            [ 'n', 'false', 0, false],
733
            ['no', 'false', 0, false],
734
            ['off', 'false', 0, false],
735
            ['0', 'false', 0, false],
736
        ];
737
    }
738
739
    /**
740
     * {@inheritdoc}
741
     */
742
    protected function getQuotedAlterTableRenameColumnSQL() : array
743
    {
744
        return [
745
            'ALTER TABLE mytable RENAME COLUMN unquoted1 TO unquoted',
746
            'ALTER TABLE mytable RENAME COLUMN unquoted2 TO "where"',
747
            'ALTER TABLE mytable RENAME COLUMN unquoted3 TO "foo"',
748
            'ALTER TABLE mytable RENAME COLUMN "create" TO reserved_keyword',
749
            'ALTER TABLE mytable RENAME COLUMN "table" TO "from"',
750
            'ALTER TABLE mytable RENAME COLUMN "select" TO "bar"',
751
            'ALTER TABLE mytable RENAME COLUMN quoted1 TO quoted',
752
            'ALTER TABLE mytable RENAME COLUMN quoted2 TO "and"',
753
            'ALTER TABLE mytable RENAME COLUMN quoted3 TO "baz"',
754
        ];
755
    }
756
757
    /**
758
     * {@inheritdoc}
759
     */
760
    protected function getQuotedAlterTableChangeColumnLengthSQL() : array
761
    {
762
        return [
763
            'ALTER TABLE mytable ALTER unquoted1 TYPE VARCHAR(255)',
764
            'ALTER TABLE mytable ALTER unquoted2 TYPE VARCHAR(255)',
765
            'ALTER TABLE mytable ALTER unquoted3 TYPE VARCHAR(255)',
766
            'ALTER TABLE mytable ALTER "create" TYPE VARCHAR(255)',
767
            'ALTER TABLE mytable ALTER "table" TYPE VARCHAR(255)',
768
            'ALTER TABLE mytable ALTER "select" TYPE VARCHAR(255)',
769
        ];
770
    }
771
772
    /**
773
     * {@inheritDoc}
774
     *
775
     * @group DBAL-807
776
     */
777
    protected function getAlterTableRenameIndexInSchemaSQL() : array
778
    {
779
        return ['ALTER INDEX myschema.idx_foo RENAME TO idx_bar'];
780
    }
781
782
    /**
783
     * {@inheritDoc}
784
     *
785
     * @group DBAL-807
786
     */
787
    protected function getQuotedAlterTableRenameIndexInSchemaSQL() : array
788
    {
789
        return [
790
            'ALTER INDEX "schema"."create" RENAME TO "select"',
791
            'ALTER INDEX "schema"."foo" RENAME TO "bar"',
792
        ];
793
    }
794
795
    protected function getQuotesDropForeignKeySQL() : string
796
    {
797
        return 'ALTER TABLE "table" DROP CONSTRAINT "select"';
798
    }
799
800
    /**
801
     * @group DBAL-423
802
     */
803
    public function testReturnsGuidTypeDeclarationSQL() : void
804
    {
805
        self::assertSame('UUID', $this->platform->getGuidTypeDeclarationSQL([]));
806
    }
807
808
    /**
809
     * {@inheritdoc}
810
     */
811
    public function getAlterTableRenameColumnSQL() : array
812
    {
813
        return ['ALTER TABLE foo RENAME COLUMN bar TO baz'];
814
    }
815
816
    /**
817
     * {@inheritdoc}
818
     */
819
    protected function getQuotesTableIdentifiersInAlterTableSQL() : array
820
    {
821
        return [
822
            'ALTER TABLE "foo" DROP CONSTRAINT fk1',
823
            'ALTER TABLE "foo" DROP CONSTRAINT fk2',
824
            'ALTER TABLE "foo" ADD bloo INT NOT NULL',
825
            'ALTER TABLE "foo" DROP baz',
826
            'ALTER TABLE "foo" ALTER bar DROP NOT NULL',
827
            'ALTER TABLE "foo" RENAME COLUMN id TO war',
828
            'ALTER TABLE "foo" RENAME TO "table"',
829
            'ALTER TABLE "table" ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id) NOT DEFERRABLE ' .
830
            'INITIALLY IMMEDIATE',
831
            'ALTER TABLE "table" ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id) NOT DEFERRABLE ' .
832
            'INITIALLY IMMEDIATE',
833
        ];
834
    }
835
836
    /**
837
     * {@inheritdoc}
838
     */
839
    protected function getCommentOnColumnSQL() : array
840
    {
841
        return [
842
            'COMMENT ON COLUMN foo.bar IS \'comment\'',
843
            'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
844
            'COMMENT ON COLUMN "select"."from" IS \'comment\'',
845
        ];
846
    }
847
848
    /**
849
     * @group DBAL-1004
850
     */
851
    public function testAltersTableColumnCommentWithExplicitlyQuotedIdentifiers() : void
852
    {
853
        $table1 = new Table('"foo"', [new Column('"bar"', Type::getType('integer'))]);
854
        $table2 = new Table('"foo"', [new Column('"bar"', Type::getType('integer'), ['comment' => 'baz'])]);
855
856
        $comparator = new Comparator();
857
858
        $tableDiff = $comparator->diffTable($table1, $table2);
859
860
        self::assertInstanceOf(TableDiff::class, $tableDiff);
861
        self::assertSame(
862
            ['COMMENT ON COLUMN "foo"."bar" IS \'baz\''],
863
            $this->platform->getAlterTableSQL($tableDiff)
0 ignored issues
show
Bug introduced by
It seems like $tableDiff can also be of type false; however, parameter $diff of Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() does only seem to accept Doctrine\DBAL\Schema\TableDiff, maybe add an additional type check? ( Ignorable by Annotation )

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

863
            $this->platform->getAlterTableSQL(/** @scrutinizer ignore-type */ $tableDiff)
Loading history...
864
        );
865
    }
866
867
    /**
868
     * @group 3158
869
     */
870
    public function testAltersTableColumnCommentIfRequiredByType() : void
871
    {
872
        $table1 = new Table('"foo"', [new Column('"bar"', Type::getType('datetime'))]);
873
        $table2 = new Table('"foo"', [new Column('"bar"', Type::getType('datetime_immutable'))]);
874
875
        $comparator = new Comparator();
876
877
        $tableDiff = $comparator->diffTable($table1, $table2);
878
879
        $this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $tableDiff);
880
        $this->assertSame(
881
            [
882
                'ALTER TABLE "foo" ALTER "bar" TYPE TIMESTAMP(0) WITHOUT TIME ZONE',
883
                'ALTER TABLE "foo" ALTER "bar" DROP DEFAULT',
884
                'COMMENT ON COLUMN "foo"."bar" IS \'(DC2Type:datetime_immutable)\'',
885
            ],
886
            $this->platform->getAlterTableSQL($tableDiff)
0 ignored issues
show
Bug introduced by
It seems like $tableDiff can also be of type false; however, parameter $diff of Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() does only seem to accept Doctrine\DBAL\Schema\TableDiff, maybe add an additional type check? ( Ignorable by Annotation )

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

886
            $this->platform->getAlterTableSQL(/** @scrutinizer ignore-type */ $tableDiff)
Loading history...
887
        );
888
    }
889
890
    /**
891
     * {@inheritdoc}
892
     */
893
    protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL() : string
894
    {
895
        return 'CONSTRAINT "select" UNIQUE (foo)';
896
    }
897
898
    /**
899
     * {@inheritdoc}
900
     */
901
    protected function getQuotesReservedKeywordInIndexDeclarationSQL() : string
902
    {
903
        return 'INDEX "select" (foo)';
904
    }
905
906
    /**
907
     * {@inheritdoc}
908
     */
909
    protected function getQuotesReservedKeywordInTruncateTableSQL() : string
910
    {
911
        return 'TRUNCATE "select"';
912
    }
913
914
    /**
915
     * {@inheritdoc}
916
     */
917
    protected function getAlterStringToFixedStringSQL() : array
918
    {
919
        return ['ALTER TABLE mytable ALTER name TYPE CHAR(2)'];
920
    }
921
922
    /**
923
     * {@inheritdoc}
924
     */
925
    protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL() : array
926
    {
927
        return ['ALTER INDEX idx_foo RENAME TO idx_foo_renamed'];
928
    }
929
930
    /**
931
     * @group DBAL-1142
932
     */
933
    public function testInitializesTsvectorTypeMapping() : void
934
    {
935
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('tsvector'));
936
        self::assertEquals('text', $this->platform->getDoctrineTypeMapping('tsvector'));
937
    }
938
939
    /**
940
     * @group DBAL-1220
941
     */
942
    public function testReturnsDisallowDatabaseConnectionsSQL() : void
943
    {
944
        self::assertSame(
945
            "UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'foo'",
946
            $this->platform->getDisallowDatabaseConnectionsSQL('foo')
0 ignored issues
show
Bug introduced by
The method getDisallowDatabaseConnectionsSQL() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. It seems like you code against a sub-type of Doctrine\DBAL\Platforms\AbstractPlatform such as Doctrine\DBAL\Platforms\PostgreSqlPlatform. ( Ignorable by Annotation )

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

946
            $this->platform->/** @scrutinizer ignore-call */ 
947
                             getDisallowDatabaseConnectionsSQL('foo')
Loading history...
947
        );
948
    }
949
950
    /**
951
     * @group DBAL-1220
952
     */
953
    public function testReturnsCloseActiveDatabaseConnectionsSQL() : void
954
    {
955
        self::assertSame(
956
            "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = 'foo'",
957
            $this->platform->getCloseActiveDatabaseConnectionsSQL('foo')
0 ignored issues
show
Bug introduced by
The method getCloseActiveDatabaseConnectionsSQL() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. It seems like you code against a sub-type of Doctrine\DBAL\Platforms\AbstractPlatform such as Doctrine\DBAL\Platforms\PostgreSqlPlatform. ( Ignorable by Annotation )

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

957
            $this->platform->/** @scrutinizer ignore-call */ 
958
                             getCloseActiveDatabaseConnectionsSQL('foo')
Loading history...
958
        );
959
    }
960
961
    /**
962
     * @group DBAL-2436
963
     */
964
    public function testQuotesTableNameInListTableForeignKeysSQL() : void
965
    {
966
        self::assertContains("'Foo''Bar\\'", $this->platform->getListTableForeignKeysSQL("Foo'Bar\\"), '', true);
967
    }
968
969
    /**
970
     * @group DBAL-2436
971
     */
972
    public function testQuotesSchemaNameInListTableForeignKeysSQL() : void
973
    {
974
        self::assertContains(
975
            "'Foo''Bar\\'",
976
            $this->platform->getListTableForeignKeysSQL("Foo'Bar\\.baz_table"),
977
            '',
978
            true
979
        );
980
    }
981
982
    /**
983
     * @group DBAL-2436
984
     */
985
    public function testQuotesTableNameInListTableConstraintsSQL() : void
986
    {
987
        self::assertContains("'Foo''Bar\\'", $this->platform->getListTableConstraintsSQL("Foo'Bar\\"), '', true);
988
    }
989
990
    /**
991
     * @group DBAL-2436
992
     */
993
    public function testQuotesTableNameInListTableIndexesSQL() : void
994
    {
995
        self::assertContains("'Foo''Bar\\'", $this->platform->getListTableIndexesSQL("Foo'Bar\\"), '', true);
996
    }
997
998
    /**
999
     * @group DBAL-2436
1000
     */
1001
    public function testQuotesSchemaNameInListTableIndexesSQL() : void
1002
    {
1003
        self::assertContains(
1004
            "'Foo''Bar\\'",
1005
            $this->platform->getListTableIndexesSQL("Foo'Bar\\.baz_table"),
1006
            '',
1007
            true
1008
        );
1009
    }
1010
1011
    /**
1012
     * @group DBAL-2436
1013
     */
1014
    public function testQuotesTableNameInListTableColumnsSQL() : void
1015
    {
1016
        self::assertContains("'Foo''Bar\\'", $this->platform->getListTableColumnsSQL("Foo'Bar\\"), '', true);
1017
    }
1018
1019
    /**
1020
     * @group DBAL-2436
1021
     */
1022
    public function testQuotesSchemaNameInListTableColumnsSQL() : void
1023
    {
1024
        self::assertContains(
1025
            "'Foo''Bar\\'",
1026
            $this->platform->getListTableColumnsSQL("Foo'Bar\\.baz_table"),
1027
            '',
1028
            true
1029
        );
1030
    }
1031
1032
    /**
1033
     * @group DBAL-2436
1034
     */
1035
    public function testQuotesDatabaseNameInCloseActiveDatabaseConnectionsSQL() : void
1036
    {
1037
        self::assertContains(
1038
            "'Foo''Bar\\'",
1039
            $this->platform->getCloseActiveDatabaseConnectionsSQL("Foo'Bar\\"),
1040
            '',
1041
            true
1042
        );
1043
    }
1044
}
1045