AbstractMySQLPlatformTestCase.php 36.6 KB
Newer Older
1 2 3 4 5 6 7
<?php

namespace Doctrine\Tests\DBAL\Platforms;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
jeroendedauw's avatar
jeroendedauw committed
8
use Doctrine\DBAL\Schema\Index;
9 10
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
11
use Doctrine\DBAL\TransactionIsolationLevel;
12
use function array_shift;
13 14 15

abstract class AbstractMySQLPlatformTestCase extends AbstractPlatformTestCase
{
16 17 18
    /** @var MySqlPlatform */
    protected $platform;

19
    public function testModifyLimitQueryWitoutLimit() : void
20
    {
Sergei Morozov's avatar
Sergei Morozov committed
21
        $sql = $this->platform->modifyLimitQuery('SELECT n FROM Foo', null, 10);
Sergei Morozov's avatar
Sergei Morozov committed
22
        self::assertEquals('SELECT n FROM Foo LIMIT 18446744073709551615 OFFSET 10', $sql);
23 24
    }

25
    public function testGenerateMixedCaseTableCreate() : void
26
    {
Sergei Morozov's avatar
Sergei Morozov committed
27 28
        $table = new Table('Foo');
        $table->addColumn('Bar', 'integer');
29

Sergei Morozov's avatar
Sergei Morozov committed
30
        $sql = $this->platform->getCreateTableSQL($table);
31
        self::assertEquals('CREATE TABLE Foo (Bar INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB', array_shift($sql));
32 33
    }

34
    public function getGenerateTableSql() : string
35
    {
36
        return 'CREATE TABLE test (id INT AUTO_INCREMENT NOT NULL, test VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB';
37 38
    }

39 40 41 42
    /**
     * @return string[]
     */
    public function getGenerateTableWithMultiColumnUniqueIndexSql() : array
43
    {
44
        return ['CREATE TABLE test (foo VARCHAR(255) DEFAULT NULL, bar VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA (foo, bar)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'];
45 46
    }

47 48 49 50
    /**
     * {@inheritDoc}
     */
    public function getGenerateAlterTableSql() : array
51
    {
Sergei Morozov's avatar
Sergei Morozov committed
52
        return ["ALTER TABLE mytable RENAME TO userlist, ADD quota INT DEFAULT NULL, DROP foo, CHANGE bar baz VARCHAR(255) DEFAULT 'def' NOT NULL, CHANGE bloo bloo TINYINT(1) DEFAULT '0' NOT NULL"];
53 54
    }

55
    public function testGeneratesSqlSnippets() : void
56
    {
Sergei Morozov's avatar
Sergei Morozov committed
57 58 59
        self::assertEquals('RLIKE', $this->platform->getRegexpExpression(), 'Regular expression operator is not correct');
        self::assertEquals('`', $this->platform->getIdentifierQuoteCharacter(), 'Quote character is not correct');
        self::assertEquals('CONCAT(column1, column2, column3)', $this->platform->getConcatExpression('column1', 'column2', 'column3'), 'Concatenation function is not correct');
60 61
    }

62
    public function testGeneratesTransactionsCommands() : void
63
    {
64
        self::assertEquals(
65
            'SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED',
Sergei Morozov's avatar
Sergei Morozov committed
66
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_UNCOMMITTED),
67 68
            ''
        );
69
        self::assertEquals(
70
            'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
Sergei Morozov's avatar
Sergei Morozov committed
71
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_COMMITTED)
72
        );
73
        self::assertEquals(
74
            'SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ',
Sergei Morozov's avatar
Sergei Morozov committed
75
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::REPEATABLE_READ)
76
        );
77
        self::assertEquals(
78
            'SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE',
Sergei Morozov's avatar
Sergei Morozov committed
79
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::SERIALIZABLE)
80 81 82
        );
    }

83
    public function testGeneratesDDLSnippets() : void
84
    {
Sergei Morozov's avatar
Sergei Morozov committed
85 86 87 88
        self::assertEquals('SHOW DATABASES', $this->platform->getListDatabasesSQL());
        self::assertEquals('CREATE DATABASE foobar', $this->platform->getCreateDatabaseSQL('foobar'));
        self::assertEquals('DROP DATABASE foobar', $this->platform->getDropDatabaseSQL('foobar'));
        self::assertEquals('DROP TABLE foobar', $this->platform->getDropTableSQL('foobar'));
89 90
    }

91
    public function testGeneratesTypeDeclarationForIntegers() : void
92
    {
93
        self::assertEquals(
94
            'INT',
Sergei Morozov's avatar
Sergei Morozov committed
95
            $this->platform->getIntegerTypeDeclarationSQL([])
96
        );
97
        self::assertEquals(
98
            'INT AUTO_INCREMENT',
Sergei Morozov's avatar
Sergei Morozov committed
99
            $this->platform->getIntegerTypeDeclarationSQL(['autoincrement' => true])
Sergei Morozov's avatar
Sergei Morozov committed
100
        );
101
        self::assertEquals(
102
            'INT AUTO_INCREMENT',
Sergei Morozov's avatar
Sergei Morozov committed
103
            $this->platform->getIntegerTypeDeclarationSQL(
Sergei Morozov's avatar
Sergei Morozov committed
104 105 106
                ['autoincrement' => true, 'primary' => true]
            )
        );
107 108
    }

109
    public function testGeneratesTypeDeclarationForStrings() : void
110
    {
111
        self::assertEquals(
112
            'CHAR(10)',
Sergei Morozov's avatar
Sergei Morozov committed
113
            $this->platform->getVarcharTypeDeclarationSQL(
Sergei Morozov's avatar
Sergei Morozov committed
114 115 116
                ['length' => 10, 'fixed' => true]
            )
        );
117
        self::assertEquals(
118
            'VARCHAR(50)',
Sergei Morozov's avatar
Sergei Morozov committed
119
            $this->platform->getVarcharTypeDeclarationSQL(['length' => 50]),
120 121
            'Variable string declaration is not correct'
        );
122
        self::assertEquals(
123
            'VARCHAR(255)',
Sergei Morozov's avatar
Sergei Morozov committed
124
            $this->platform->getVarcharTypeDeclarationSQL([]),
125 126 127 128
            'Long string declaration is not correct'
        );
    }

129
    public function testPrefersIdentityColumns() : void
130
    {
Sergei Morozov's avatar
Sergei Morozov committed
131
        self::assertTrue($this->platform->prefersIdentityColumns());
132 133
    }

134
    public function testSupportsIdentityColumns() : void
135
    {
Sergei Morozov's avatar
Sergei Morozov committed
136
        self::assertTrue($this->platform->supportsIdentityColumns());
137 138
    }

139
    public function testDoesSupportSavePoints() : void
140
    {
Sergei Morozov's avatar
Sergei Morozov committed
141
        self::assertTrue($this->platform->supportsSavepoints());
142 143
    }

144
    public function getGenerateIndexSql() : string
145 146 147 148
    {
        return 'CREATE INDEX my_idx ON mytable (user_name, last_login)';
    }

149
    public function getGenerateUniqueIndexSql() : string
150 151 152 153
    {
        return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
    }

154
    public function getGenerateForeignKeySql() : string
155 156 157 158 159 160 161
    {
        return 'ALTER TABLE test ADD FOREIGN KEY (fk_name_id) REFERENCES other_table (id)';
    }

    /**
     * @group DBAL-126
     */
162
    public function testUniquePrimaryKey() : void
163
    {
Sergei Morozov's avatar
Sergei Morozov committed
164 165 166 167 168
        $keyTable = new Table('foo');
        $keyTable->addColumn('bar', 'integer');
        $keyTable->addColumn('baz', 'string');
        $keyTable->setPrimaryKey(['bar']);
        $keyTable->addUniqueIndex(['baz']);
169

Sergei Morozov's avatar
Sergei Morozov committed
170 171 172
        $oldTable = new Table('foo');
        $oldTable->addColumn('bar', 'integer');
        $oldTable->addColumn('baz', 'string');
173

Sergei Morozov's avatar
Sergei Morozov committed
174
        $c    = new Comparator();
175 176
        $diff = $c->diffTable($oldTable, $keyTable);

Sergei Morozov's avatar
Sergei Morozov committed
177
        $sql = $this->platform->getAlterTableSQL($diff);
178

Sergei Morozov's avatar
Sergei Morozov committed
179 180 181 182
        self::assertEquals([
            'ALTER TABLE foo ADD PRIMARY KEY (bar)',
            'CREATE UNIQUE INDEX UNIQ_8C73652178240498 ON foo (baz)',
        ], $sql);
183 184
    }

185
    public function testModifyLimitQuery() : void
186
    {
Sergei Morozov's avatar
Sergei Morozov committed
187
        $sql = $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 0);
188
        self::assertEquals('SELECT * FROM user LIMIT 10', $sql);
189 190
    }

191
    public function testModifyLimitQueryWithEmptyOffset() : void
192
    {
Sergei Morozov's avatar
Sergei Morozov committed
193
        $sql = $this->platform->modifyLimitQuery('SELECT * FROM user', 10);
194
        self::assertEquals('SELECT * FROM user LIMIT 10', $sql);
195 196 197 198 199
    }

    /**
     * @group DDC-118
     */
200
    public function testGetDateTimeTypeDeclarationSql() : void
201
    {
Sergei Morozov's avatar
Sergei Morozov committed
202 203 204
        self::assertEquals('DATETIME', $this->platform->getDateTimeTypeDeclarationSQL(['version' => false]));
        self::assertEquals('TIMESTAMP', $this->platform->getDateTimeTypeDeclarationSQL(['version' => true]));
        self::assertEquals('DATETIME', $this->platform->getDateTimeTypeDeclarationSQL([]));
205 206
    }

207 208 209 210
    /**
     * {@inheritDoc}
     */
    public function getCreateTableColumnCommentsSQL() : array
211
    {
212
        return ["CREATE TABLE test (id INT NOT NULL COMMENT 'This is a comment', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB"];
213 214
    }

215 216 217 218
    /**
     * {@inheritDoc}
     */
    public function getAlterTableColumnCommentsSQL() : array
219
    {
Sergei Morozov's avatar
Sergei Morozov committed
220
        return ["ALTER TABLE mytable ADD quota INT NOT NULL COMMENT 'A comment', CHANGE foo foo VARCHAR(255) NOT NULL, CHANGE bar baz VARCHAR(255) NOT NULL COMMENT 'B comment'"];
221 222
    }

223 224 225 226
    /**
     * {@inheritDoc}
     */
    public function getCreateTableColumnTypeCommentsSQL() : array
227
    {
228
        return ["CREATE TABLE test (id INT NOT NULL, data LONGTEXT NOT NULL COMMENT '(DC2Type:array)', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB"];
229 230 231 232 233
    }

    /**
     * @group DBAL-237
     */
234
    public function testChangeIndexWithForeignKeys() : void
235
    {
Sergei Morozov's avatar
Sergei Morozov committed
236 237
        $index  = new Index('idx', ['col'], false);
        $unique = new Index('uniq', ['col'], true);
238

Sergei Morozov's avatar
Sergei Morozov committed
239
        $diff = new TableDiff('test', [], [], [], [$unique], [], [$index]);
Sergei Morozov's avatar
Sergei Morozov committed
240
        $sql  = $this->platform->getAlterTableSQL($diff);
Sergei Morozov's avatar
Sergei Morozov committed
241
        self::assertEquals(['ALTER TABLE test DROP INDEX idx, ADD UNIQUE INDEX uniq (col)'], $sql);
242

Sergei Morozov's avatar
Sergei Morozov committed
243
        $diff = new TableDiff('test', [], [], [], [$index], [], [$unique]);
Sergei Morozov's avatar
Sergei Morozov committed
244
        $sql  = $this->platform->getAlterTableSQL($diff);
Sergei Morozov's avatar
Sergei Morozov committed
245
        self::assertEquals(['ALTER TABLE test DROP INDEX uniq, ADD INDEX idx (col)'], $sql);
246 247
    }

248 249 250 251
    /**
     * @return string[]
     */
    protected function getQuotedColumnInPrimaryKeySQL() : array
252
    {
253
        return ['CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, PRIMARY KEY(`create`)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'];
254 255
    }

256 257 258 259
    /**
     * @return string[]
     */
    protected function getQuotedColumnInIndexSQL() : array
260
    {
261
        return ['CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, INDEX IDX_22660D028FD6E0FB (`create`)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'];
262 263
    }

264 265 266 267
    /**
     * @return string[]
     */
    protected function getQuotedNameInIndexSQL() : array
Markus Fasselt's avatar
Markus Fasselt committed
268
    {
269
        return ['CREATE TABLE test (column1 VARCHAR(255) NOT NULL, INDEX `key` (column1)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'];
Markus Fasselt's avatar
Markus Fasselt committed
270 271
    }

272 273 274 275
    /**
     * @return string[]
     */
    protected function getQuotedColumnInForeignKeySQL() : array
276
    {
Sergei Morozov's avatar
Sergei Morozov committed
277
        return [
278
            'CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, foo VARCHAR(255) NOT NULL, `bar` VARCHAR(255) NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
279 280 281
            'ALTER TABLE `quoted` ADD CONSTRAINT FK_WITH_RESERVED_KEYWORD FOREIGN KEY (`create`, foo, `bar`) REFERENCES `foreign` (`create`, bar, `foo-bar`)',
            'ALTER TABLE `quoted` ADD CONSTRAINT FK_WITH_NON_RESERVED_KEYWORD FOREIGN KEY (`create`, foo, `bar`) REFERENCES foo (`create`, bar, `foo-bar`)',
            'ALTER TABLE `quoted` ADD CONSTRAINT FK_WITH_INTENDED_QUOTATION FOREIGN KEY (`create`, foo, `bar`) REFERENCES `foo-bar` (`create`, bar, `foo-bar`)',
Sergei Morozov's avatar
Sergei Morozov committed
282
        ];
283 284
    }

285
    public function testCreateTableWithFulltextIndex() : void
286 287 288 289
    {
        $table = new Table('fulltext_table');
        $table->addOption('engine', 'MyISAM');
        $table->addColumn('text', 'text');
Sergei Morozov's avatar
Sergei Morozov committed
290
        $table->addIndex(['text'], 'fulltext_text');
291 292 293 294

        $index = $table->getIndex('fulltext_text');
        $index->addFlag('fulltext');

Sergei Morozov's avatar
Sergei Morozov committed
295
        $sql = $this->platform->getCreateTableSQL($table);
296
        self::assertEquals(['CREATE TABLE fulltext_table (text LONGTEXT NOT NULL, FULLTEXT INDEX fulltext_text (text)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM'], $sql);
297 298
    }

299
    public function testCreateTableWithSpatialIndex() : void
300 301 302 303
    {
        $table = new Table('spatial_table');
        $table->addOption('engine', 'MyISAM');
        $table->addColumn('point', 'text'); // This should be a point type
Sergei Morozov's avatar
Sergei Morozov committed
304
        $table->addIndex(['point'], 'spatial_text');
305 306 307 308

        $index = $table->getIndex('spatial_text');
        $index->addFlag('spatial');

Sergei Morozov's avatar
Sergei Morozov committed
309
        $sql = $this->platform->getCreateTableSQL($table);
310
        self::assertEquals(['CREATE TABLE spatial_table (point LONGTEXT NOT NULL, SPATIAL INDEX spatial_text (point)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM'], $sql);
311 312
    }

313
    public function testClobTypeDeclarationSQL() : void
314
    {
Sergei Morozov's avatar
Sergei Morozov committed
315 316 317 318 319 320 321 322
        self::assertEquals('TINYTEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 1]));
        self::assertEquals('TINYTEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 255]));
        self::assertEquals('TEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 256]));
        self::assertEquals('TEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 65535]));
        self::assertEquals('MEDIUMTEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 65536]));
        self::assertEquals('MEDIUMTEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 16777215]));
        self::assertEquals('LONGTEXT', $this->platform->getClobTypeDeclarationSQL(['length' => 16777216]));
        self::assertEquals('LONGTEXT', $this->platform->getClobTypeDeclarationSQL([]));
323 324
    }

325
    public function testBlobTypeDeclarationSQL() : void
326
    {
Sergei Morozov's avatar
Sergei Morozov committed
327 328 329 330 331 332 333 334
        self::assertEquals('TINYBLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 1]));
        self::assertEquals('TINYBLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 255]));
        self::assertEquals('BLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 256]));
        self::assertEquals('BLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 65535]));
        self::assertEquals('MEDIUMBLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 65536]));
        self::assertEquals('MEDIUMBLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 16777215]));
        self::assertEquals('LONGBLOB', $this->platform->getBlobTypeDeclarationSQL(['length' => 16777216]));
        self::assertEquals('LONGBLOB', $this->platform->getBlobTypeDeclarationSQL([]));
335 336 337 338 339
    }

    /**
     * @group DBAL-400
     */
340
    public function testAlterTableAddPrimaryKey() : void
341 342 343 344
    {
        $table = new Table('alter_table_add_pk');
        $table->addColumn('id', 'integer');
        $table->addColumn('foo', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
345
        $table->addIndex(['id'], 'idx_id');
346 347 348 349 350

        $comparator = new Comparator();
        $diffTable  = clone $table;

        $diffTable->dropIndex('idx_id');
Sergei Morozov's avatar
Sergei Morozov committed
351
        $diffTable->setPrimaryKey(['id']);
352

353
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
354
            ['DROP INDEX idx_id ON alter_table_add_pk', 'ALTER TABLE alter_table_add_pk ADD PRIMARY KEY (id)'],
Sergei Morozov's avatar
Sergei Morozov committed
355
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
356 357 358
        );
    }

359
    /**
360
     * @group DBAL-1132
361
     */
362
    public function testAlterPrimaryKeyWithAutoincrementColumn() : void
363
    {
Sergei Morozov's avatar
Sergei Morozov committed
364 365
        $table = new Table('alter_primary_key');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
366
        $table->addColumn('foo', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
367
        $table->setPrimaryKey(['id']);
368 369

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
370
        $diffTable  = clone $table;
371 372

        $diffTable->dropPrimaryKey();
Sergei Morozov's avatar
Sergei Morozov committed
373
        $diffTable->setPrimaryKey(['foo']);
374

375
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
376
            [
Steve Müller's avatar
Steve Müller committed
377 378
                'ALTER TABLE alter_primary_key MODIFY id INT NOT NULL',
                'ALTER TABLE alter_primary_key DROP PRIMARY KEY',
Sergei Morozov's avatar
Sergei Morozov committed
379 380
                'ALTER TABLE alter_primary_key ADD PRIMARY KEY (foo)',
            ],
Sergei Morozov's avatar
Sergei Morozov committed
381
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
382 383 384
        );
    }

385 386 387
    /**
     * @group DBAL-464
     */
388
    public function testDropPrimaryKeyWithAutoincrementColumn() : void
389
    {
Sergei Morozov's avatar
Sergei Morozov committed
390 391
        $table = new Table('drop_primary_key');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
andig's avatar
andig committed
392
        $table->addColumn('foo', 'integer');
393
        $table->addColumn('bar', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
394
        $table->setPrimaryKey(['id', 'foo']);
395 396

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
397
        $diffTable  = clone $table;
398 399 400

        $diffTable->dropPrimaryKey();

401
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
402
            [
403
                'ALTER TABLE drop_primary_key MODIFY id INT NOT NULL',
Sergei Morozov's avatar
Sergei Morozov committed
404 405
                'ALTER TABLE drop_primary_key DROP PRIMARY KEY',
            ],
Sergei Morozov's avatar
Sergei Morozov committed
406
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
407 408 409
        );
    }

410 411 412
    /**
     * @group DBAL-2302
     */
413
    public function testDropNonAutoincrementColumnFromCompositePrimaryKeyWithAutoincrementColumn() : void
414
    {
Sergei Morozov's avatar
Sergei Morozov committed
415 416
        $table = new Table('tbl');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
417 418
        $table->addColumn('foo', 'integer');
        $table->addColumn('bar', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
419
        $table->setPrimaryKey(['id', 'foo']);
420 421

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
422
        $diffTable  = clone $table;
423 424

        $diffTable->dropPrimaryKey();
Sergei Morozov's avatar
Sergei Morozov committed
425
        $diffTable->setPrimaryKey(['id']);
426

427
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
428
            [
429 430 431
                'ALTER TABLE tbl MODIFY id INT NOT NULL',
                'ALTER TABLE tbl DROP PRIMARY KEY',
                'ALTER TABLE tbl ADD PRIMARY KEY (id)',
Sergei Morozov's avatar
Sergei Morozov committed
432
            ],
Sergei Morozov's avatar
Sergei Morozov committed
433
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
434 435 436
        );
    }

437 438 439
    /**
     * @group DBAL-2302
     */
440
    public function testAddNonAutoincrementColumnToPrimaryKeyWithAutoincrementColumn() : void
441
    {
Sergei Morozov's avatar
Sergei Morozov committed
442 443
        $table = new Table('tbl');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
444 445
        $table->addColumn('foo', 'integer');
        $table->addColumn('bar', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
446
        $table->setPrimaryKey(['id']);
447 448

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
449
        $diffTable  = clone $table;
450 451

        $diffTable->dropPrimaryKey();
Sergei Morozov's avatar
Sergei Morozov committed
452
        $diffTable->setPrimaryKey(['id', 'foo']);
453

454
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
455
            [
456 457 458
                'ALTER TABLE tbl MODIFY id INT NOT NULL',
                'ALTER TABLE tbl DROP PRIMARY KEY',
                'ALTER TABLE tbl ADD PRIMARY KEY (id, foo)',
Sergei Morozov's avatar
Sergei Morozov committed
459
            ],
Sergei Morozov's avatar
Sergei Morozov committed
460
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
461 462 463
        );
    }

464 465 466
    /**
     * @group DBAL-586
     */
467
    public function testAddAutoIncrementPrimaryKey() : void
468
    {
Sergei Morozov's avatar
Sergei Morozov committed
469 470 471 472
        $keyTable = new Table('foo');
        $keyTable->addColumn('id', 'integer', ['autoincrement' => true]);
        $keyTable->addColumn('baz', 'string');
        $keyTable->setPrimaryKey(['id']);
473

Sergei Morozov's avatar
Sergei Morozov committed
474 475
        $oldTable = new Table('foo');
        $oldTable->addColumn('baz', 'string');
476

Sergei Morozov's avatar
Sergei Morozov committed
477
        $c    = new Comparator();
478 479
        $diff = $c->diffTable($oldTable, $keyTable);

Sergei Morozov's avatar
Sergei Morozov committed
480
        $sql = $this->platform->getAlterTableSQL($diff);
481

Sergei Morozov's avatar
Sergei Morozov committed
482
        self::assertEquals(['ALTER TABLE foo ADD id INT AUTO_INCREMENT NOT NULL, ADD PRIMARY KEY (id)'], $sql);
483 484
    }

485
    public function testNamedPrimaryKey() : void
486
    {
Sergei Morozov's avatar
Sergei Morozov committed
487 488
        $diff                              = new TableDiff('mytable');
        $diff->changedIndexes['foo_index'] = new Index('foo_index', ['foo'], true, true);
489

Sergei Morozov's avatar
Sergei Morozov committed
490
        $sql = $this->platform->getAlterTableSQL($diff);
491

Sergei Morozov's avatar
Sergei Morozov committed
492 493 494 495
        self::assertEquals([
            'ALTER TABLE mytable DROP PRIMARY KEY',
            'ALTER TABLE mytable ADD PRIMARY KEY (foo)',
        ], $sql);
496
    }
497

498
    public function testAlterPrimaryKeyWithNewColumn() : void
499
    {
Sergei Morozov's avatar
Sergei Morozov committed
500
        $table = new Table('yolo');
501 502
        $table->addColumn('pkc1', 'integer');
        $table->addColumn('col_a', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
503
        $table->setPrimaryKey(['pkc1']);
504 505

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
506
        $diffTable  = clone $table;
507

508 509
        $diffTable->addColumn('pkc2', 'integer');
        $diffTable->dropPrimaryKey();
Sergei Morozov's avatar
Sergei Morozov committed
510
        $diffTable->setPrimaryKey(['pkc1', 'pkc2']);
511

512
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
513
            [
514 515 516
                'ALTER TABLE yolo DROP PRIMARY KEY',
                'ALTER TABLE yolo ADD pkc2 INT NOT NULL',
                'ALTER TABLE yolo ADD PRIMARY KEY (pkc1, pkc2)',
Sergei Morozov's avatar
Sergei Morozov committed
517
            ],
Sergei Morozov's avatar
Sergei Morozov committed
518
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
519
        );
520
    }
521

522
    public function testInitializesDoctrineTypeMappings() : void
523
    {
Sergei Morozov's avatar
Sergei Morozov committed
524 525
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('binary'));
        self::assertSame('binary', $this->platform->getDoctrineTypeMapping('binary'));
526

Sergei Morozov's avatar
Sergei Morozov committed
527 528
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('varbinary'));
        self::assertSame('binary', $this->platform->getDoctrineTypeMapping('varbinary'));
529 530
    }

531
    protected function getBinaryMaxLength() : int
532 533 534 535
    {
        return 65535;
    }

536
    public function testReturnsBinaryTypeDeclarationSQL() : void
537
    {
Sergei Morozov's avatar
Sergei Morozov committed
538 539 540
        self::assertSame('VARBINARY(255)', $this->platform->getBinaryTypeDeclarationSQL([]));
        self::assertSame('VARBINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 0]));
        self::assertSame('VARBINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65535]));
541

Sergei Morozov's avatar
Sergei Morozov committed
542 543 544
        self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
        self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0]));
        self::assertSame('BINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 65535]));
545 546 547 548
    }

    /**
     * @group legacy
549 550 551
     * @expectedDeprecation Binary field length 65536 is greater than supported by the platform (65535). Reduce the field length or use a BLOB field instead.
     * @expectedDeprecation Binary field length 16777215 is greater than supported by the platform (65535). Reduce the field length or use a BLOB field instead.
     * @expectedDeprecation Binary field length 16777216 is greater than supported by the platform (65535). Reduce the field length or use a BLOB field instead.
552
     */
553
    public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL() : void
554
    {
Sergei Morozov's avatar
Sergei Morozov committed
555 556 557
        self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65536]));
        self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 16777215]));
        self::assertSame('LONGBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 16777216]));
558

Sergei Morozov's avatar
Sergei Morozov committed
559 560 561
        self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 65536]));
        self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 16777215]));
        self::assertSame('LONGBLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 16777216]));
562 563
    }

564
    public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines() : void
565
    {
Sergei Morozov's avatar
Sergei Morozov committed
566
        $table = new Table('foreign_table');
567 568
        $table->addColumn('id', 'integer');
        $table->addColumn('fk_id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
569 570
        $table->addForeignKeyConstraint('foreign_table', ['fk_id'], ['id']);
        $table->setPrimaryKey(['id']);
571 572
        $table->addOption('engine', 'MyISAM');

573
        self::assertSame(
574
            ['CREATE TABLE foreign_table (id INT NOT NULL, fk_id INT NOT NULL, INDEX IDX_5690FFE2A57719D0 (fk_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM'],
Sergei Morozov's avatar
Sergei Morozov committed
575
            $this->platform->getCreateTableSQL(
576 577 578 579 580 581 582 583
                $table,
                AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS
            )
        );

        $table = clone $table;
        $table->addOption('engine', 'InnoDB');

584
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
585
            [
586
                'CREATE TABLE foreign_table (id INT NOT NULL, fk_id INT NOT NULL, INDEX IDX_5690FFE2A57719D0 (fk_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
Sergei Morozov's avatar
Sergei Morozov committed
587 588
                'ALTER TABLE foreign_table ADD CONSTRAINT FK_5690FFE2A57719D0 FOREIGN KEY (fk_id) REFERENCES foreign_table (id)',
            ],
Sergei Morozov's avatar
Sergei Morozov committed
589
            $this->platform->getCreateTableSQL(
590 591 592 593 594 595
                $table,
                AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS
            )
        );
    }

596
    public function testDoesNotPropagateForeignKeyAlterationForNonSupportingEngines() : void
597
    {
Sergei Morozov's avatar
Sergei Morozov committed
598
        $table = new Table('foreign_table');
599 600
        $table->addColumn('id', 'integer');
        $table->addColumn('fk_id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
601 602
        $table->addForeignKeyConstraint('foreign_table', ['fk_id'], ['id']);
        $table->setPrimaryKey(['id']);
603 604
        $table->addOption('engine', 'MyISAM');

Sergei Morozov's avatar
Sergei Morozov committed
605 606 607
        $addedForeignKeys   = [new ForeignKeyConstraint(['fk_id'], 'foo', ['id'], 'fk_add')];
        $changedForeignKeys = [new ForeignKeyConstraint(['fk_id'], 'bar', ['id'], 'fk_change')];
        $removedForeignKeys = [new ForeignKeyConstraint(['fk_id'], 'baz', ['id'], 'fk_remove')];
608

Sergei Morozov's avatar
Sergei Morozov committed
609 610 611
        $tableDiff                     = new TableDiff('foreign_table');
        $tableDiff->fromTable          = $table;
        $tableDiff->addedForeignKeys   = $addedForeignKeys;
612 613 614
        $tableDiff->changedForeignKeys = $changedForeignKeys;
        $tableDiff->removedForeignKeys = $removedForeignKeys;

Sergei Morozov's avatar
Sergei Morozov committed
615
        self::assertEmpty($this->platform->getAlterTableSQL($tableDiff));
616 617 618

        $table->addOption('engine', 'InnoDB');

Sergei Morozov's avatar
Sergei Morozov committed
619 620 621
        $tableDiff                     = new TableDiff('foreign_table');
        $tableDiff->fromTable          = $table;
        $tableDiff->addedForeignKeys   = $addedForeignKeys;
622 623 624
        $tableDiff->changedForeignKeys = $changedForeignKeys;
        $tableDiff->removedForeignKeys = $removedForeignKeys;

625
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
626
            [
627 628 629 630
                'ALTER TABLE foreign_table DROP FOREIGN KEY fk_remove',
                'ALTER TABLE foreign_table DROP FOREIGN KEY fk_change',
                'ALTER TABLE foreign_table ADD CONSTRAINT fk_add FOREIGN KEY (fk_id) REFERENCES foo (id)',
                'ALTER TABLE foreign_table ADD CONSTRAINT fk_change FOREIGN KEY (fk_id) REFERENCES bar (id)',
Sergei Morozov's avatar
Sergei Morozov committed
631
            ],
Sergei Morozov's avatar
Sergei Morozov committed
632
            $this->platform->getAlterTableSQL($tableDiff)
633 634 635 636
        );
    }

    /**
637 638
     * @return string[]
     *
639 640
     * @group DBAL-234
     */
641
    protected function getAlterTableRenameIndexSQL() : array
642
    {
Sergei Morozov's avatar
Sergei Morozov committed
643
        return [
644 645
            'DROP INDEX idx_foo ON mytable',
            'CREATE INDEX idx_bar ON mytable (id)',
Sergei Morozov's avatar
Sergei Morozov committed
646
        ];
647 648 649
    }

    /**
650 651
     * @return string[]
     *
652 653
     * @group DBAL-234
     */
654
    protected function getQuotedAlterTableRenameIndexSQL() : array
655
    {
Sergei Morozov's avatar
Sergei Morozov committed
656
        return [
657 658 659 660
            'DROP INDEX `create` ON `table`',
            'CREATE INDEX `select` ON `table` (id)',
            'DROP INDEX `foo` ON `table`',
            'CREATE INDEX `bar` ON `table` (id)',
Sergei Morozov's avatar
Sergei Morozov committed
661
        ];
662
    }
663

664
    /**
665 666
     * @return string[]
     *
667 668
     * @group DBAL-807
     */
669
    protected function getAlterTableRenameIndexInSchemaSQL() : array
670
    {
Sergei Morozov's avatar
Sergei Morozov committed
671
        return [
672 673
            'DROP INDEX idx_foo ON myschema.mytable',
            'CREATE INDEX idx_bar ON myschema.mytable (id)',
Sergei Morozov's avatar
Sergei Morozov committed
674
        ];
675 676 677
    }

    /**
678 679
     * @return string[]
     *
680 681
     * @group DBAL-807
     */
682
    protected function getQuotedAlterTableRenameIndexInSchemaSQL() : array
683
    {
Sergei Morozov's avatar
Sergei Morozov committed
684
        return [
685 686 687 688
            'DROP INDEX `create` ON `schema`.`table`',
            'CREATE INDEX `select` ON `schema`.`table` (id)',
            'DROP INDEX `foo` ON `schema`.`table`',
            'CREATE INDEX `bar` ON `schema`.`table` (id)',
Sergei Morozov's avatar
Sergei Morozov committed
689
        ];
690 691
    }

692
    protected function getQuotesDropForeignKeySQL() : string
693 694 695 696
    {
        return 'ALTER TABLE `table` DROP FOREIGN KEY `select`';
    }

697
    protected function getQuotesDropConstraintSQL() : string
698 699 700 701
    {
        return 'ALTER TABLE `table` DROP CONSTRAINT `select`';
    }

702
    public function testDoesNotPropagateDefaultValuesForUnsupportedColumnTypes() : void
703
    {
Sergei Morozov's avatar
Sergei Morozov committed
704 705 706 707 708
        $table = new Table('text_blob_default_value');
        $table->addColumn('def_text', 'text', ['default' => 'def']);
        $table->addColumn('def_text_null', 'text', ['notnull' => false, 'default' => 'def']);
        $table->addColumn('def_blob', 'blob', ['default' => 'def']);
        $table->addColumn('def_blob_null', 'blob', ['notnull' => false, 'default' => 'def']);
709

710
        self::assertSame(
711
            ['CREATE TABLE text_blob_default_value (def_text LONGTEXT NOT NULL, def_text_null LONGTEXT DEFAULT NULL, def_blob LONGBLOB NOT NULL, def_blob_null LONGBLOB DEFAULT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'],
Sergei Morozov's avatar
Sergei Morozov committed
712
            $this->platform->getCreateTableSQL($table)
713 714 715
        );

        $diffTable = clone $table;
Sergei Morozov's avatar
Sergei Morozov committed
716 717 718 719
        $diffTable->changeColumn('def_text', ['default' => null]);
        $diffTable->changeColumn('def_text_null', ['default' => null]);
        $diffTable->changeColumn('def_blob', ['default' => null]);
        $diffTable->changeColumn('def_blob_null', ['default' => null]);
720 721 722

        $comparator = new Comparator();

Sergei Morozov's avatar
Sergei Morozov committed
723
        self::assertEmpty($this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable)));
724
    }
725 726 727 728

    /**
     * {@inheritdoc}
     */
729
    protected function getQuotedAlterTableRenameColumnSQL() : array
730
    {
Sergei Morozov's avatar
Sergei Morozov committed
731
        return ['ALTER TABLE mytable ' .
732 733 734 735 736 737 738 739
            "CHANGE unquoted1 unquoted INT NOT NULL COMMENT 'Unquoted 1', " .
            "CHANGE unquoted2 `where` INT NOT NULL COMMENT 'Unquoted 2', " .
            "CHANGE unquoted3 `foo` INT NOT NULL COMMENT 'Unquoted 3', " .
            "CHANGE `create` reserved_keyword INT NOT NULL COMMENT 'Reserved keyword 1', " .
            "CHANGE `table` `from` INT NOT NULL COMMENT 'Reserved keyword 2', " .
            "CHANGE `select` `bar` INT NOT NULL COMMENT 'Reserved keyword 3', " .
            "CHANGE quoted1 quoted INT NOT NULL COMMENT 'Quoted 1', " .
            "CHANGE quoted2 `and` INT NOT NULL COMMENT 'Quoted 2', " .
Sergei Morozov's avatar
Sergei Morozov committed
740 741
            "CHANGE quoted3 `baz` INT NOT NULL COMMENT 'Quoted 3'",
        ];
742
    }
743 744 745 746

    /**
     * {@inheritdoc}
     */
747
    protected function getQuotedAlterTableChangeColumnLengthSQL() : array
748
    {
Sergei Morozov's avatar
Sergei Morozov committed
749
        return ['ALTER TABLE mytable ' .
750 751 752 753 754
            "CHANGE unquoted1 unquoted1 VARCHAR(255) NOT NULL COMMENT 'Unquoted 1', " .
            "CHANGE unquoted2 unquoted2 VARCHAR(255) NOT NULL COMMENT 'Unquoted 2', " .
            "CHANGE unquoted3 unquoted3 VARCHAR(255) NOT NULL COMMENT 'Unquoted 3', " .
            "CHANGE `create` `create` VARCHAR(255) NOT NULL COMMENT 'Reserved keyword 1', " .
            "CHANGE `table` `table` VARCHAR(255) NOT NULL COMMENT 'Reserved keyword 2', " .
Sergei Morozov's avatar
Sergei Morozov committed
755 756
            "CHANGE `select` `select` VARCHAR(255) NOT NULL COMMENT 'Reserved keyword 3'",
        ];
757
    }
758 759 760 761

    /**
     * @group DBAL-423
     */
762
    public function testReturnsGuidTypeDeclarationSQL() : void
763
    {
Sergei Morozov's avatar
Sergei Morozov committed
764
        self::assertSame('CHAR(36)', $this->platform->getGuidTypeDeclarationSQL([]));
765
    }
766 767 768 769

    /**
     * {@inheritdoc}
     */
770
    public function getAlterTableRenameColumnSQL() : array
771
    {
Sergei Morozov's avatar
Sergei Morozov committed
772
        return ["ALTER TABLE foo CHANGE bar baz INT DEFAULT 666 NOT NULL COMMENT 'rename test'"];
773
    }
774 775 776 777

    /**
     * {@inheritdoc}
     */
778
    protected function getQuotesTableIdentifiersInAlterTableSQL() : array
779
    {
Sergei Morozov's avatar
Sergei Morozov committed
780
        return [
781 782 783 784 785 786
            'ALTER TABLE `foo` DROP FOREIGN KEY fk1',
            'ALTER TABLE `foo` DROP FOREIGN KEY fk2',
            'ALTER TABLE `foo` RENAME TO `table`, ADD bloo INT NOT NULL, DROP baz, CHANGE bar bar INT DEFAULT NULL, ' .
            'CHANGE id war INT NOT NULL',
            'ALTER TABLE `table` ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id)',
            'ALTER TABLE `table` ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id)',
Sergei Morozov's avatar
Sergei Morozov committed
787
        ];
788
    }
789 790 791 792

    /**
     * {@inheritdoc}
     */
793
    protected function getCommentOnColumnSQL() : array
794
    {
Sergei Morozov's avatar
Sergei Morozov committed
795
        return [
796 797 798
            "COMMENT ON COLUMN foo.bar IS 'comment'",
            "COMMENT ON COLUMN `Foo`.`BAR` IS 'comment'",
            "COMMENT ON COLUMN `select`.`from` IS 'comment'",
Sergei Morozov's avatar
Sergei Morozov committed
799
        ];
800
    }
801 802 803 804

    /**
     * {@inheritdoc}
     */
805
    protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL() : string
806 807 808 809 810 811 812
    {
        return 'CONSTRAINT `select` UNIQUE (foo)';
    }

    /**
     * {@inheritdoc}
     */
813
    protected function getQuotesReservedKeywordInIndexDeclarationSQL() : string
814 815 816
    {
        return 'INDEX `select` (foo)';
    }
817

818 819 820
    /**
     * {@inheritdoc}
     */
821
    protected function getQuotesReservedKeywordInTruncateTableSQL() : string
822 823 824 825
    {
        return 'TRUNCATE `select`';
    }

826 827 828
    /**
     * {@inheritdoc}
     */
829
    protected function getAlterStringToFixedStringSQL() : array
830
    {
Sergei Morozov's avatar
Sergei Morozov committed
831
        return ['ALTER TABLE mytable CHANGE name name CHAR(2) NOT NULL'];
832
    }
833 834 835 836

    /**
     * {@inheritdoc}
     */
837
    protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL() : array
838
    {
Sergei Morozov's avatar
Sergei Morozov committed
839
        return [
840 841 842 843
            'ALTER TABLE mytable DROP FOREIGN KEY fk_foo',
            'DROP INDEX idx_foo ON mytable',
            'CREATE INDEX idx_foo_renamed ON mytable (foo)',
            'ALTER TABLE mytable ADD CONSTRAINT fk_foo FOREIGN KEY (foo) REFERENCES foreign_table (id)',
Sergei Morozov's avatar
Sergei Morozov committed
844
        ];
845
    }
846 847 848 849

    /**
     * {@inheritdoc}
     */
850
    public static function getGeneratesDecimalTypeDeclarationSQL() : iterable
851
    {
Sergei Morozov's avatar
Sergei Morozov committed
852 853 854 855 856 857 858 859
        return [
            [[], 'NUMERIC(10, 0)'],
            [['unsigned' => true], 'NUMERIC(10, 0) UNSIGNED'],
            [['unsigned' => false], 'NUMERIC(10, 0)'],
            [['precision' => 5], 'NUMERIC(5, 0)'],
            [['scale' => 5], 'NUMERIC(10, 5)'],
            [['precision' => 8, 'scale' => 2], 'NUMERIC(8, 2)'],
        ];
860 861 862 863 864
    }

    /**
     * {@inheritdoc}
     */
865
    public static function getGeneratesFloatDeclarationSQL() : iterable
866
    {
Sergei Morozov's avatar
Sergei Morozov committed
867 868 869 870 871 872 873 874
        return [
            [[], 'DOUBLE PRECISION'],
            [['unsigned' => true], 'DOUBLE PRECISION UNSIGNED'],
            [['unsigned' => false], 'DOUBLE PRECISION'],
            [['precision' => 5], 'DOUBLE PRECISION'],
            [['scale' => 5], 'DOUBLE PRECISION'],
            [['precision' => 8, 'scale' => 2], 'DOUBLE PRECISION'],
        ];
875
    }
876 877 878 879

    /**
     * @group DBAL-2436
     */
880
    public function testQuotesTableNameInListTableIndexesSQL() : void
881
    {
882 883 884 885
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableIndexesSQL("Foo'Bar\\", 'foo_db')
        );
886 887 888 889 890
    }

    /**
     * @group DBAL-2436
     */
891
    public function testQuotesDatabaseNameInListTableIndexesSQL() : void
892
    {
893 894 895 896
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableIndexesSQL('foo_table', "Foo'Bar\\")
        );
897 898 899 900 901
    }

    /**
     * @group DBAL-2436
     */
902
    public function testQuotesDatabaseNameInListViewsSQL() : void
903
    {
904 905 906 907
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListViewsSQL("Foo'Bar\\")
        );
908 909 910 911 912
    }

    /**
     * @group DBAL-2436
     */
913
    public function testQuotesTableNameInListTableForeignKeysSQL() : void
914
    {
915 916 917 918
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableForeignKeysSQL("Foo'Bar\\")
        );
919 920 921 922 923
    }

    /**
     * @group DBAL-2436
     */
924
    public function testQuotesDatabaseNameInListTableForeignKeysSQL() : void
925
    {
926 927 928 929
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableForeignKeysSQL('foo_table', "Foo'Bar\\")
        );
930 931 932 933 934
    }

    /**
     * @group DBAL-2436
     */
935
    public function testQuotesTableNameInListTableColumnsSQL() : void
936
    {
937 938 939 940
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableColumnsSQL("Foo'Bar\\")
        );
941 942 943 944 945
    }

    /**
     * @group DBAL-2436
     */
946
    public function testQuotesDatabaseNameInListTableColumnsSQL() : void
947
    {
948 949 950 951
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableColumnsSQL('foo_table', "Foo'Bar\\")
        );
952
    }
953

954
    public function testListTableForeignKeysSQLEvaluatesDatabase() : void
955
    {
Sergei Morozov's avatar
Sergei Morozov committed
956
        $sql = $this->platform->getListTableForeignKeysSQL('foo');
957

958
        self::assertStringContainsString('DATABASE()', $sql);
959

Sergei Morozov's avatar
Sergei Morozov committed
960
        $sql = $this->platform->getListTableForeignKeysSQL('foo', 'bar');
961

962 963
        self::assertStringContainsString('bar', $sql);
        self::assertStringNotContainsString('DATABASE()', $sql);
964
    }
965

966 967 968 969 970 971 972 973
    public function testColumnCharsetDeclarationSQL() : void
    {
        self::assertSame(
            'CHARACTER SET ascii',
            $this->platform->getColumnCharsetDeclarationSQL('ascii')
        );
    }

974 975
    public function testSupportsColumnCollation() : void
    {
Sergei Morozov's avatar
Sergei Morozov committed
976
        self::assertTrue($this->platform->supportsColumnCollation());
977 978 979 980 981
    }

    public function testColumnCollationDeclarationSQL() : void
    {
        self::assertSame(
982
            'COLLATE `ascii_general_ci`',
Sergei Morozov's avatar
Sergei Morozov committed
983
            $this->platform->getColumnCollationDeclarationSQL('ascii_general_ci')
984 985 986 987 988 989 990 991 992 993
        );
    }

    public function testGetCreateTableSQLWithColumnCollation() : void
    {
        $table = new Table('foo');
        $table->addColumn('no_collation', 'string');
        $table->addColumn('column_collation', 'string')->setPlatformOption('collation', 'ascii_general_ci');

        self::assertSame(
994
            ['CREATE TABLE foo (no_collation VARCHAR(255) NOT NULL, column_collation VARCHAR(255) NOT NULL COLLATE `ascii_general_ci`) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'],
Sergei Morozov's avatar
Sergei Morozov committed
995
            $this->platform->getCreateTableSQL($table),
996 997 998
            'Column "no_collation" will use the default collation from the table/database and "column_collation" overwrites the collation on this column'
        );
    }
999
}