Passed
Pull Request — master (#3120)
by Sergei
12:25
created

SQLAnywherePlatformTest   F

Complexity

Total Complexity 102

Size/Duplication

Total Lines 1054
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 102
dl 0
loc 1054
rs 0.9221
c 0
b 0
f 0

How to fix   Complexity   

Complex Class

Complex classes like SQLAnywherePlatformTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SQLAnywherePlatformTest, and based on these observations, apply Extract Interface, too.

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