AbstractMySQLPlatformTestCase.php 36.1 KB
Newer Older
1 2
<?php

3
namespace Doctrine\DBAL\Tests\Platforms;
4 5

use Doctrine\DBAL\Platforms\AbstractPlatform;
6
use Doctrine\DBAL\Platforms\MySqlPlatform;
7 8
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
jeroendedauw's avatar
jeroendedauw committed
9
use Doctrine\DBAL\Schema\Index;
10 11
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
12
use Doctrine\DBAL\TransactionIsolationLevel;
13

14
use function array_shift;
15 16 17

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

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

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

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

39
    public function getGenerateTableSql(): string
40
    {
Sergei Morozov's avatar
Sergei Morozov committed
41 42
        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';
43 44
    }

45 46 47
    /**
     * @return string[]
     */
48
    public function getGenerateTableWithMultiColumnUniqueIndexSql(): array
49
    {
Sergei Morozov's avatar
Sergei Morozov committed
50 51 52 53 54
        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',
        ];
55 56
    }

57 58 59
    /**
     * {@inheritDoc}
     */
60
    public function getGenerateAlterTableSql(): array
61
    {
Sergei Morozov's avatar
Sergei Morozov committed
62 63 64 65 66
        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",
        ];
67 68
    }

69
    public function testGeneratesSqlSnippets(): void
70
    {
71 72
        self::assertEquals('RLIKE', $this->platform->getRegexpExpression());
        self::assertEquals('`', $this->platform->getIdentifierQuoteCharacter());
Sergei Morozov's avatar
Sergei Morozov committed
73 74 75 76 77

        self::assertEquals(
            'CONCAT(column1, column2, column3)',
            $this->platform->getConcatExpression('column1', 'column2', 'column3')
        );
78 79
    }

80
    public function testGeneratesTransactionsCommands(): void
81
    {
82
        self::assertEquals(
83
            'SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED',
Sergei Morozov's avatar
Sergei Morozov committed
84
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_UNCOMMITTED),
85 86
            ''
        );
87
        self::assertEquals(
88
            'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
Sergei Morozov's avatar
Sergei Morozov committed
89
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::READ_COMMITTED)
90
        );
91
        self::assertEquals(
92
            'SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ',
Sergei Morozov's avatar
Sergei Morozov committed
93
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::REPEATABLE_READ)
94
        );
95
        self::assertEquals(
96
            'SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE',
Sergei Morozov's avatar
Sergei Morozov committed
97
            $this->platform->getSetTransactionIsolationSQL(TransactionIsolationLevel::SERIALIZABLE)
98 99 100
        );
    }

101
    public function testGeneratesDDLSnippets(): void
102
    {
Sergei Morozov's avatar
Sergei Morozov committed
103 104 105 106
        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'));
107 108
    }

109
    public function testGeneratesTypeDeclarationForIntegers(): void
110
    {
111
        self::assertEquals(
112
            'INT',
Sergei Morozov's avatar
Sergei Morozov committed
113
            $this->platform->getIntegerTypeDeclarationSQL([])
114
        );
115
        self::assertEquals(
116
            'INT AUTO_INCREMENT',
Sergei Morozov's avatar
Sergei Morozov committed
117
            $this->platform->getIntegerTypeDeclarationSQL(['autoincrement' => true])
Sergei Morozov's avatar
Sergei Morozov committed
118
        );
119
        self::assertEquals(
120
            'INT AUTO_INCREMENT',
Sergei Morozov's avatar
Sergei Morozov committed
121
            $this->platform->getIntegerTypeDeclarationSQL(
Sergei Morozov's avatar
Sergei Morozov committed
122 123 124
                ['autoincrement' => true, 'primary' => true]
            )
        );
125 126
    }

127
    public function testGeneratesTypeDeclarationForStrings(): void
128
    {
129
        self::assertEquals(
130
            'CHAR(10)',
Sergei Morozov's avatar
Sergei Morozov committed
131
            $this->platform->getVarcharTypeDeclarationSQL(
Sergei Morozov's avatar
Sergei Morozov committed
132 133 134
                ['length' => 10, 'fixed' => true]
            )
        );
135
        self::assertEquals(
136
            'VARCHAR(50)',
137
            $this->platform->getVarcharTypeDeclarationSQL(['length' => 50])
138
        );
139
        self::assertEquals(
140
            'VARCHAR(255)',
141
            $this->platform->getVarcharTypeDeclarationSQL([])
142 143 144
        );
    }

145
    public function testPrefersIdentityColumns(): void
146
    {
Sergei Morozov's avatar
Sergei Morozov committed
147
        self::assertTrue($this->platform->prefersIdentityColumns());
148 149
    }

150
    public function testSupportsIdentityColumns(): void
151
    {
Sergei Morozov's avatar
Sergei Morozov committed
152
        self::assertTrue($this->platform->supportsIdentityColumns());
153 154
    }

155
    public function testDoesSupportSavePoints(): void
156
    {
Sergei Morozov's avatar
Sergei Morozov committed
157
        self::assertTrue($this->platform->supportsSavepoints());
158 159
    }

160
    public function getGenerateIndexSql(): string
161 162 163 164
    {
        return 'CREATE INDEX my_idx ON mytable (user_name, last_login)';
    }

165
    public function getGenerateUniqueIndexSql(): string
166 167 168 169
    {
        return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
    }

170
    protected function getGenerateForeignKeySql(): string
171 172 173 174
    {
        return 'ALTER TABLE test ADD FOREIGN KEY (fk_name_id) REFERENCES other_table (id)';
    }

175
    public function testUniquePrimaryKey(): void
176
    {
Sergei Morozov's avatar
Sergei Morozov committed
177 178 179 180 181
        $keyTable = new Table('foo');
        $keyTable->addColumn('bar', 'integer');
        $keyTable->addColumn('baz', 'string');
        $keyTable->setPrimaryKey(['bar']);
        $keyTable->addUniqueIndex(['baz']);
182

Sergei Morozov's avatar
Sergei Morozov committed
183 184 185
        $oldTable = new Table('foo');
        $oldTable->addColumn('bar', 'integer');
        $oldTable->addColumn('baz', 'string');
186

Sergei Morozov's avatar
Sergei Morozov committed
187
        $c    = new Comparator();
188 189
        $diff = $c->diffTable($oldTable, $keyTable);

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

Sergei Morozov's avatar
Sergei Morozov committed
192 193 194 195
        self::assertEquals([
            'ALTER TABLE foo ADD PRIMARY KEY (bar)',
            'CREATE UNIQUE INDEX UNIQ_8C73652178240498 ON foo (baz)',
        ], $sql);
196 197
    }

198
    public function testModifyLimitQuery(): void
199
    {
Sergei Morozov's avatar
Sergei Morozov committed
200
        $sql = $this->platform->modifyLimitQuery('SELECT * FROM user', 10, 0);
201
        self::assertEquals('SELECT * FROM user LIMIT 10', $sql);
202 203
    }

204
    public function testModifyLimitQueryWithEmptyOffset(): void
205
    {
Sergei Morozov's avatar
Sergei Morozov committed
206
        $sql = $this->platform->modifyLimitQuery('SELECT * FROM user', 10);
207
        self::assertEquals('SELECT * FROM user LIMIT 10', $sql);
208 209
    }

210
    public function testGetDateTimeTypeDeclarationSql(): void
211
    {
Sergei Morozov's avatar
Sergei Morozov committed
212 213 214
        self::assertEquals('DATETIME', $this->platform->getDateTimeTypeDeclarationSQL(['version' => false]));
        self::assertEquals('TIMESTAMP', $this->platform->getDateTimeTypeDeclarationSQL(['version' => true]));
        self::assertEquals('DATETIME', $this->platform->getDateTimeTypeDeclarationSQL([]));
215 216
    }

217 218 219
    /**
     * {@inheritDoc}
     */
220
    public function getCreateTableColumnCommentsSQL(): array
221
    {
Sergei Morozov's avatar
Sergei Morozov committed
222 223 224 225
        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',
        ];
226 227
    }

228 229 230
    /**
     * {@inheritDoc}
     */
231
    public function getAlterTableColumnCommentsSQL(): array
232
    {
Sergei Morozov's avatar
Sergei Morozov committed
233 234 235 236 237
        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'",
        ];
238 239
    }

240 241 242
    /**
     * {@inheritDoc}
     */
243
    public function getCreateTableColumnTypeCommentsSQL(): array
244
    {
Sergei Morozov's avatar
Sergei Morozov committed
245 246 247 248
        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',
        ];
249 250
    }

251
    public function testChangeIndexWithForeignKeys(): void
252
    {
Sergei Morozov's avatar
Sergei Morozov committed
253 254
        $index  = new Index('idx', ['col'], false);
        $unique = new Index('uniq', ['col'], true);
255

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

Sergei Morozov's avatar
Sergei Morozov committed
260
        $diff = new TableDiff('test', [], [], [], [$index], [], [$unique]);
Sergei Morozov's avatar
Sergei Morozov committed
261
        $sql  = $this->platform->getAlterTableSQL($diff);
Sergei Morozov's avatar
Sergei Morozov committed
262
        self::assertEquals(['ALTER TABLE test DROP INDEX uniq, ADD INDEX idx (col)'], $sql);
263 264
    }

265 266 267
    /**
     * @return string[]
     */
268
    protected function getQuotedColumnInPrimaryKeySQL(): array
269
    {
Sergei Morozov's avatar
Sergei Morozov committed
270 271 272
        return ['CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, '
                . 'PRIMARY KEY(`create`)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
        ];
273 274
    }

275 276 277
    /**
     * @return string[]
     */
278
    protected function getQuotedColumnInIndexSQL(): array
279
    {
Sergei Morozov's avatar
Sergei Morozov committed
280 281 282 283 284
        return [
            'CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, '
                . 'INDEX IDX_22660D028FD6E0FB (`create`)) '
                . 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
        ];
285 286
    }

287 288 289
    /**
     * @return string[]
     */
290
    protected function getQuotedNameInIndexSQL(): array
Markus Fasselt's avatar
Markus Fasselt committed
291
    {
Sergei Morozov's avatar
Sergei Morozov committed
292 293 294 295
        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
296 297
    }

298 299 300
    /**
     * @return string[]
     */
301
    protected function getQuotedColumnInForeignKeySQL(): array
302
    {
Sergei Morozov's avatar
Sergei Morozov committed
303
        return [
Sergei Morozov's avatar
Sergei Morozov committed
304 305 306 307 308 309 310 311
            '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',
            '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
312
        ];
313 314
    }

315
    public function testCreateTableWithFulltextIndex(): void
316 317 318 319
    {
        $table = new Table('fulltext_table');
        $table->addOption('engine', 'MyISAM');
        $table->addColumn('text', 'text');
Sergei Morozov's avatar
Sergei Morozov committed
320
        $table->addIndex(['text'], 'fulltext_text');
321 322 323 324

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

Sergei Morozov's avatar
Sergei Morozov committed
325
        $sql = $this->platform->getCreateTableSQL($table);
Sergei Morozov's avatar
Sergei Morozov committed
326 327 328 329 330 331 332 333
        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
        );
334 335
    }

336
    public function testCreateTableWithSpatialIndex(): void
337 338 339 340
    {
        $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
341
        $table->addIndex(['point'], 'spatial_text');
342 343 344 345

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

Sergei Morozov's avatar
Sergei Morozov committed
346
        $sql = $this->platform->getCreateTableSQL($table);
Sergei Morozov's avatar
Sergei Morozov committed
347 348 349 350 351 352 353
        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
        );
354 355
    }

356
    public function testClobTypeDeclarationSQL(): void
357
    {
Sergei Morozov's avatar
Sergei Morozov committed
358 359 360 361 362 363 364 365
        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([]));
366 367
    }

368
    public function testBlobTypeDeclarationSQL(): void
369
    {
Sergei Morozov's avatar
Sergei Morozov committed
370 371 372 373 374 375 376 377
        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([]));
378 379
    }

380
    public function testAlterTableAddPrimaryKey(): void
381 382 383 384
    {
        $table = new Table('alter_table_add_pk');
        $table->addColumn('id', 'integer');
        $table->addColumn('foo', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
385
        $table->addIndex(['id'], 'idx_id');
386 387 388 389 390

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

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

393
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
394
            ['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
395
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
396 397 398
        );
    }

399
    public function testAlterPrimaryKeyWithAutoincrementColumn(): void
400
    {
Sergei Morozov's avatar
Sergei Morozov committed
401 402
        $table = new Table('alter_primary_key');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
403
        $table->addColumn('foo', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
404
        $table->setPrimaryKey(['id']);
405 406

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
407
        $diffTable  = clone $table;
408 409

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

412
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
413
            [
Steve Müller's avatar
Steve Müller committed
414 415
                '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
416 417
                'ALTER TABLE alter_primary_key ADD PRIMARY KEY (foo)',
            ],
Sergei Morozov's avatar
Sergei Morozov committed
418
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
419 420 421
        );
    }

422
    public function testDropPrimaryKeyWithAutoincrementColumn(): void
423
    {
Sergei Morozov's avatar
Sergei Morozov committed
424 425
        $table = new Table('drop_primary_key');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
andig's avatar
andig committed
426
        $table->addColumn('foo', 'integer');
427
        $table->addColumn('bar', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
428
        $table->setPrimaryKey(['id', 'foo']);
429 430

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
431
        $diffTable  = clone $table;
432 433 434

        $diffTable->dropPrimaryKey();

435
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
436
            [
437
                'ALTER TABLE drop_primary_key MODIFY id INT NOT NULL',
Sergei Morozov's avatar
Sergei Morozov committed
438 439
                'ALTER TABLE drop_primary_key DROP PRIMARY KEY',
            ],
Sergei Morozov's avatar
Sergei Morozov committed
440
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
441 442 443
        );
    }

444
    public function testDropNonAutoincrementColumnFromCompositePrimaryKeyWithAutoincrementColumn(): void
445
    {
Sergei Morozov's avatar
Sergei Morozov committed
446 447
        $table = new Table('tbl');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
448 449
        $table->addColumn('foo', 'integer');
        $table->addColumn('bar', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
450
        $table->setPrimaryKey(['id', 'foo']);
451 452

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
453
        $diffTable  = clone $table;
454 455

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

458
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
459
            [
460 461 462
                '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
463
            ],
Sergei Morozov's avatar
Sergei Morozov committed
464
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
465 466 467
        );
    }

468
    public function testAddNonAutoincrementColumnToPrimaryKeyWithAutoincrementColumn(): void
469
    {
Sergei Morozov's avatar
Sergei Morozov committed
470 471
        $table = new Table('tbl');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
472 473
        $table->addColumn('foo', 'integer');
        $table->addColumn('bar', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
474
        $table->setPrimaryKey(['id']);
475 476

        $comparator = new Comparator();
Sergei Morozov's avatar
Sergei Morozov committed
477
        $diffTable  = clone $table;
478 479

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

482
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
483
            [
484 485 486
                '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
487
            ],
Sergei Morozov's avatar
Sergei Morozov committed
488
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
489 490 491
        );
    }

492
    public function testAddAutoIncrementPrimaryKey(): void
493
    {
Sergei Morozov's avatar
Sergei Morozov committed
494 495 496 497
        $keyTable = new Table('foo');
        $keyTable->addColumn('id', 'integer', ['autoincrement' => true]);
        $keyTable->addColumn('baz', 'string');
        $keyTable->setPrimaryKey(['id']);
498

Sergei Morozov's avatar
Sergei Morozov committed
499 500
        $oldTable = new Table('foo');
        $oldTable->addColumn('baz', 'string');
501

Sergei Morozov's avatar
Sergei Morozov committed
502
        $c    = new Comparator();
503 504
        $diff = $c->diffTable($oldTable, $keyTable);

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

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

510
    public function testNamedPrimaryKey(): void
511
    {
Sergei Morozov's avatar
Sergei Morozov committed
512 513
        $diff                              = new TableDiff('mytable');
        $diff->changedIndexes['foo_index'] = new Index('foo_index', ['foo'], true, true);
514

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

Sergei Morozov's avatar
Sergei Morozov committed
517 518 519 520
        self::assertEquals([
            'ALTER TABLE mytable DROP PRIMARY KEY',
            'ALTER TABLE mytable ADD PRIMARY KEY (foo)',
        ], $sql);
521
    }
522

523
    public function testAlterPrimaryKeyWithNewColumn(): void
524
    {
Sergei Morozov's avatar
Sergei Morozov committed
525
        $table = new Table('yolo');
526 527
        $table->addColumn('pkc1', 'integer');
        $table->addColumn('col_a', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
528
        $table->setPrimaryKey(['pkc1']);
529 530

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

533 534
        $diffTable->addColumn('pkc2', 'integer');
        $diffTable->dropPrimaryKey();
Sergei Morozov's avatar
Sergei Morozov committed
535
        $diffTable->setPrimaryKey(['pkc1', 'pkc2']);
536

537
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
538
            [
539 540 541
                '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
542
            ],
Sergei Morozov's avatar
Sergei Morozov committed
543
            $this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable))
544
        );
545
    }
546

547
    public function testInitializesDoctrineTypeMappings(): void
548
    {
Sergei Morozov's avatar
Sergei Morozov committed
549 550
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('binary'));
        self::assertSame('binary', $this->platform->getDoctrineTypeMapping('binary'));
551

Sergei Morozov's avatar
Sergei Morozov committed
552 553
        self::assertTrue($this->platform->hasDoctrineTypeMappingFor('varbinary'));
        self::assertSame('binary', $this->platform->getDoctrineTypeMapping('varbinary'));
554 555
    }

556
    protected function getBinaryMaxLength(): int
557 558 559 560
    {
        return 65535;
    }

561
    public function testReturnsBinaryTypeDeclarationSQL(): void
562
    {
Sergei Morozov's avatar
Sergei Morozov committed
563 564 565
        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]));
566

Sergei Morozov's avatar
Sergei Morozov committed
567 568
        self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
        self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0]));
Sergei Morozov's avatar
Sergei Morozov committed
569 570 571 572 573

        self::assertSame('BINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL([
            'fixed' => true,
            'length' => 65535,
        ]));
574 575
    }

576
    public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL(): void
577
    {
Sergei Morozov's avatar
Sergei Morozov committed
578 579 580
        self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65536]));
        self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 16777215]));
        self::assertSame('LONGBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 16777216]));
581

Sergei Morozov's avatar
Sergei Morozov committed
582 583 584 585 586 587 588 589 590 591 592 593 594 595
        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,
        ]));
596 597
    }

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

607
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
608 609 610 611 612
            [
                '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
613
            $this->platform->getCreateTableSQL(
614
                $table,
615
                AbstractPlatform::CREATE_INDEXES | AbstractPlatform::CREATE_FOREIGNKEYS
616 617 618 619 620 621
            )
        );

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

622
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
623
            [
Sergei Morozov's avatar
Sergei Morozov committed
624 625 626 627 628
                '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',
                'ALTER TABLE foreign_table ADD CONSTRAINT FK_5690FFE2A57719D0 FOREIGN KEY (fk_id)'
                    . ' REFERENCES foreign_table (id)',
Sergei Morozov's avatar
Sergei Morozov committed
629
            ],
Sergei Morozov's avatar
Sergei Morozov committed
630
            $this->platform->getCreateTableSQL(
631
                $table,
632
                AbstractPlatform::CREATE_INDEXES | AbstractPlatform::CREATE_FOREIGNKEYS
633 634 635 636
            )
        );
    }

637
    public function testDoesNotPropagateForeignKeyAlterationForNonSupportingEngines(): void
638
    {
Sergei Morozov's avatar
Sergei Morozov committed
639
        $table = new Table('foreign_table');
640 641
        $table->addColumn('id', 'integer');
        $table->addColumn('fk_id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
642 643
        $table->addForeignKeyConstraint('foreign_table', ['fk_id'], ['id']);
        $table->setPrimaryKey(['id']);
644 645
        $table->addOption('engine', 'MyISAM');

Sergei Morozov's avatar
Sergei Morozov committed
646 647 648
        $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')];
649

Sergei Morozov's avatar
Sergei Morozov committed
650 651 652
        $tableDiff                     = new TableDiff('foreign_table');
        $tableDiff->fromTable          = $table;
        $tableDiff->addedForeignKeys   = $addedForeignKeys;
653 654 655
        $tableDiff->changedForeignKeys = $changedForeignKeys;
        $tableDiff->removedForeignKeys = $removedForeignKeys;

Sergei Morozov's avatar
Sergei Morozov committed
656
        self::assertEmpty($this->platform->getAlterTableSQL($tableDiff));
657 658 659

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

Sergei Morozov's avatar
Sergei Morozov committed
660 661 662
        $tableDiff                     = new TableDiff('foreign_table');
        $tableDiff->fromTable          = $table;
        $tableDiff->addedForeignKeys   = $addedForeignKeys;
663 664 665
        $tableDiff->changedForeignKeys = $changedForeignKeys;
        $tableDiff->removedForeignKeys = $removedForeignKeys;

666
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
667
            [
668 669 670 671
                '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
672
            ],
Sergei Morozov's avatar
Sergei Morozov committed
673
            $this->platform->getAlterTableSQL($tableDiff)
674 675 676 677
        );
    }

    /**
678
     * @return string[]
679
     */
680
    protected function getAlterTableRenameIndexSQL(): array
681
    {
Sergei Morozov's avatar
Sergei Morozov committed
682
        return [
683 684
            'DROP INDEX idx_foo ON mytable',
            'CREATE INDEX idx_bar ON mytable (id)',
Sergei Morozov's avatar
Sergei Morozov committed
685
        ];
686 687 688
    }

    /**
689
     * @return string[]
690
     */
691
    protected function getQuotedAlterTableRenameIndexSQL(): array
692
    {
Sergei Morozov's avatar
Sergei Morozov committed
693
        return [
694 695 696 697
            '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
698
        ];
699
    }
700

701
    /**
702
     * @return string[]
703
     */
704
    protected function getAlterTableRenameIndexInSchemaSQL(): array
705
    {
Sergei Morozov's avatar
Sergei Morozov committed
706
        return [
707 708
            'DROP INDEX idx_foo ON myschema.mytable',
            'CREATE INDEX idx_bar ON myschema.mytable (id)',
Sergei Morozov's avatar
Sergei Morozov committed
709
        ];
710 711 712
    }

    /**
713
     * @return string[]
714
     */
715
    protected function getQuotedAlterTableRenameIndexInSchemaSQL(): array
716
    {
Sergei Morozov's avatar
Sergei Morozov committed
717
        return [
718 719 720 721
            '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
722
        ];
723 724
    }

725
    protected function getQuotesDropForeignKeySQL(): string
726 727 728 729
    {
        return 'ALTER TABLE `table` DROP FOREIGN KEY `select`';
    }

730
    protected function getQuotesDropConstraintSQL(): string
731 732 733 734
    {
        return 'ALTER TABLE `table` DROP CONSTRAINT `select`';
    }

735
    public function testDoesNotPropagateDefaultValuesForUnsupportedColumnTypes(): void
736
    {
Sergei Morozov's avatar
Sergei Morozov committed
737 738 739 740 741
        $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']);
742

743
        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
744 745 746 747 748 749 750
            [
                '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
751
            $this->platform->getCreateTableSQL($table)
752 753 754
        );

        $diffTable = clone $table;
Sergei Morozov's avatar
Sergei Morozov committed
755 756 757 758
        $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]);
759 760 761

        $comparator = new Comparator();

Sergei Morozov's avatar
Sergei Morozov committed
762
        self::assertEmpty($this->platform->getAlterTableSQL($comparator->diffTable($table, $diffTable)));
763
    }
764 765 766 767

    /**
     * {@inheritdoc}
     */
768
    protected function getQuotedAlterTableRenameColumnSQL(): array
769
    {
Sergei Morozov's avatar
Sergei Morozov committed
770
        return ['ALTER TABLE mytable ' .
771 772 773 774 775 776 777 778
            "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
779 780
            "CHANGE quoted3 `baz` INT NOT NULL COMMENT 'Quoted 3'",
        ];
781
    }
782 783 784 785

    /**
     * {@inheritdoc}
     */
786
    protected function getQuotedAlterTableChangeColumnLengthSQL(): array
787
    {
Sergei Morozov's avatar
Sergei Morozov committed
788
        return ['ALTER TABLE mytable ' .
789 790 791 792 793
            "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
794 795
            "CHANGE `select` `select` VARCHAR(255) NOT NULL COMMENT 'Reserved keyword 3'",
        ];
796
    }
797

798
    public function testReturnsGuidTypeDeclarationSQL(): void
799
    {
Sergei Morozov's avatar
Sergei Morozov committed
800
        self::assertSame('CHAR(36)', $this->platform->getGuidTypeDeclarationSQL([]));
801
    }
802 803 804 805

    /**
     * {@inheritdoc}
     */
806
    public function getAlterTableRenameColumnSQL(): array
807
    {
Sergei Morozov's avatar
Sergei Morozov committed
808
        return ["ALTER TABLE foo CHANGE bar baz INT DEFAULT 666 NOT NULL COMMENT 'rename test'"];
809
    }
810 811 812 813

    /**
     * {@inheritdoc}
     */
814
    protected function getQuotesTableIdentifiersInAlterTableSQL(): array
815
    {
Sergei Morozov's avatar
Sergei Morozov committed
816
        return [
817 818 819 820 821 822
            '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
823
        ];
824
    }
825 826 827 828

    /**
     * {@inheritdoc}
     */
829
    protected function getCommentOnColumnSQL(): array
830
    {
Sergei Morozov's avatar
Sergei Morozov committed
831
        return [
832 833 834
            "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
835
        ];
836
    }
837

838
    protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL(): string
839 840 841 842
    {
        return 'CONSTRAINT `select` UNIQUE (foo)';
    }

843
    protected function getQuotesReservedKeywordInIndexDeclarationSQL(): string
844 845 846
    {
        return 'INDEX `select` (foo)';
    }
847

848
    protected function getQuotesReservedKeywordInTruncateTableSQL(): string
849 850 851 852
    {
        return 'TRUNCATE `select`';
    }

853 854 855
    /**
     * {@inheritdoc}
     */
856
    protected function getAlterStringToFixedStringSQL(): array
857
    {
Sergei Morozov's avatar
Sergei Morozov committed
858
        return ['ALTER TABLE mytable CHANGE name name CHAR(2) NOT NULL'];
859
    }
860 861 862 863

    /**
     * {@inheritdoc}
     */
864
    protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL(): array
865
    {
Sergei Morozov's avatar
Sergei Morozov committed
866
        return [
867 868 869 870
            '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
871
        ];
872
    }
873 874 875 876

    /**
     * {@inheritdoc}
     */
877
    public static function getGeneratesDecimalTypeDeclarationSQL(): iterable
878
    {
Sergei Morozov's avatar
Sergei Morozov committed
879 880 881 882 883 884 885 886
        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)'],
        ];
887 888 889 890 891
    }

    /**
     * {@inheritdoc}
     */
892
    public static function getGeneratesFloatDeclarationSQL(): iterable
893
    {
Sergei Morozov's avatar
Sergei Morozov committed
894 895 896 897 898 899 900 901
        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'],
        ];
902
    }
903

904
    public function testQuotesTableNameInListTableIndexesSQL(): void
905
    {
906 907 908 909
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableIndexesSQL("Foo'Bar\\", 'foo_db')
        );
910 911
    }

912
    public function testQuotesDatabaseNameInListTableIndexesSQL(): void
913
    {
914 915 916 917
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableIndexesSQL('foo_table', "Foo'Bar\\")
        );
918 919
    }

920
    public function testQuotesDatabaseNameInListViewsSQL(): void
921
    {
922 923 924 925
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListViewsSQL("Foo'Bar\\")
        );
926 927
    }

928
    public function testQuotesTableNameInListTableForeignKeysSQL(): void
929
    {
930 931 932 933
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableForeignKeysSQL("Foo'Bar\\")
        );
934 935
    }

936
    public function testQuotesDatabaseNameInListTableForeignKeysSQL(): void
937
    {
938 939 940 941
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableForeignKeysSQL('foo_table', "Foo'Bar\\")
        );
942 943
    }

944
    public function testQuotesTableNameInListTableColumnsSQL(): void
945
    {
946 947 948 949
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableColumnsSQL("Foo'Bar\\")
        );
950 951
    }

952
    public function testQuotesDatabaseNameInListTableColumnsSQL(): void
953
    {
954 955 956 957
        self::assertStringContainsStringIgnoringCase(
            "'Foo''Bar\\\\'",
            $this->platform->getListTableColumnsSQL('foo_table', "Foo'Bar\\")
        );
958
    }
959

960
    public function testListTableForeignKeysSQLEvaluatesDatabase(): void
961
    {
Sergei Morozov's avatar
Sergei Morozov committed
962
        $sql = $this->platform->getListTableForeignKeysSQL('foo');
963

964
        self::assertStringContainsString('DATABASE()', $sql);
965

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

968 969
        self::assertStringContainsString('bar', $sql);
        self::assertStringNotContainsString('DATABASE()', $sql);
970
    }
971

972
    public function testColumnCharsetDeclarationSQL(): void
973 974 975 976 977 978 979
    {
        self::assertSame(
            'CHARACTER SET ascii',
            $this->platform->getColumnCharsetDeclarationSQL('ascii')
        );
    }

980
    public function testSupportsColumnCollation(): void
981
    {
Sergei Morozov's avatar
Sergei Morozov committed
982
        self::assertTrue($this->platform->supportsColumnCollation());
983 984
    }

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

993
    public function testGetCreateTableSQLWithColumnCollation(): void
994 995 996 997 998 999
    {
        $table = new Table('foo');
        $table->addColumn('no_collation', 'string');
        $table->addColumn('column_collation', 'string')->setPlatformOption('collation', 'ascii_general_ci');

        self::assertSame(
Sergei Morozov's avatar
Sergei Morozov committed
1000 1001 1002 1003 1004 1005
            [
                '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',
            ],
            $this->platform->getCreateTableSQL($table)
1006 1007
        );
    }
1008
}