Failed Conditions
Push — master ( 8d18a3...24b4eb )
by Marco
13s
created

hasElementWithName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 2
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional\Schema;
4
5
use Doctrine\Common\EventManager;
6
use Doctrine\DBAL\Events;
7
use Doctrine\DBAL\Platforms\OraclePlatform;
8
use Doctrine\DBAL\Schema\Column;
9
use Doctrine\DBAL\Schema\ColumnDiff;
10
use Doctrine\DBAL\Schema\Comparator;
11
use Doctrine\DBAL\Schema\Table;
12
use Doctrine\DBAL\Schema\TableDiff;
13
use Doctrine\DBAL\Types\Type;
14
15
class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTestCase
16
{
17
    /**
18
     * @var \Doctrine\DBAL\Schema\AbstractSchemaManager
19
     */
20
    protected $_sm;
21
22
    protected function getPlatformName()
23
    {
24
        $class = get_class($this);
25
        $e = explode('\\', $class);
26
        $testClass = end($e);
27
        $dbms = strtolower(str_replace('SchemaManagerTest', null, $testClass));
28
        return $dbms;
29
    }
30
31
    protected function setUp()
32
    {
33
        parent::setUp();
34
35
        $dbms = $this->getPlatformName();
36
37
        if ($this->_conn->getDatabasePlatform()->getName() !== $dbms) {
38
            $this->markTestSkipped(get_class($this) . ' requires the use of ' . $dbms);
39
        }
40
41
        $this->_sm = $this->_conn->getSchemaManager();
42
    }
43
44
    /**
45
     * @group DBAL-1220
46
     */
47
    public function testDropsDatabaseWithActiveConnections()
48
    {
49
        if (! $this->_sm->getDatabasePlatform()->supportsCreateDropDatabase()) {
50
            $this->markTestSkipped('Cannot drop Database client side with this Driver.');
51
        }
52
53
        $this->_sm->dropAndCreateDatabase('test_drop_database');
54
55
        $knownDatabases = $this->_sm->listDatabases();
56
        if ($this->_conn->getDatabasePlatform() instanceof OraclePlatform) {
57
            self::assertContains('TEST_DROP_DATABASE', $knownDatabases);
58
        } else {
59
            self::assertContains('test_drop_database', $knownDatabases);
60
        }
61
62
        $params = $this->_conn->getParams();
63
        if ($this->_conn->getDatabasePlatform() instanceof OraclePlatform) {
64
            $params['user'] = 'test_drop_database';
65
        } else {
66
            $params['dbname'] = 'test_drop_database';
67
        }
68
69
        $user = isset($params['user']) ? $params['user'] : null;
70
        $password = isset($params['password']) ? $params['password'] : null;
71
72
        $connection = $this->_conn->getDriver()->connect($params, $user, $password);
73
74
        self::assertInstanceOf('Doctrine\DBAL\Driver\Connection', $connection);
75
76
        $this->_sm->dropDatabase('test_drop_database');
77
78
        self::assertNotContains('test_drop_database', $this->_sm->listDatabases());
79
    }
80
81
    /**
82
     * @group DBAL-195
83
     */
84
    public function testDropAndCreateSequence()
85
    {
86
        if ( ! $this->_conn->getDatabasePlatform()->supportsSequences()) {
87
            $this->markTestSkipped($this->_conn->getDriver()->getName().' does not support sequences.');
88
        }
89
90
        $name = 'dropcreate_sequences_test_seq';
91
92
        $this->_sm->dropAndCreateSequence(new \Doctrine\DBAL\Schema\Sequence($name, 20, 10));
93
94
        self::assertTrue($this->hasElementWithName($this->_sm->listSequences(), $name));
95
    }
96
97
    private function hasElementWithName(array $items, string $name) : bool
98
    {
99
        $filteredList = array_filter(
100
            $items,
101
            function (\Doctrine\DBAL\Schema\AbstractAsset $item) use ($name) : bool {
102
                return $item->getShortestName($item->getNamespaceName()) === $name;
103
            }
104
        );
105
106
        return count($filteredList) === 1;
107
    }
108
109
    public function testListSequences()
110
    {
111
        if(!$this->_conn->getDatabasePlatform()->supportsSequences()) {
112
            $this->markTestSkipped($this->_conn->getDriver()->getName().' does not support sequences.');
113
        }
114
115
        $sequence = new \Doctrine\DBAL\Schema\Sequence('list_sequences_test_seq', 20, 10);
116
        $this->_sm->createSequence($sequence);
117
118
        $sequences = $this->_sm->listSequences();
119
120
        self::assertInternalType('array', $sequences, 'listSequences() should return an array.');
121
122
        $foundSequence = null;
123
        foreach($sequences as $sequence) {
124
            self::assertInstanceOf('Doctrine\DBAL\Schema\Sequence', $sequence, 'Array elements of listSequences() should be Sequence instances.');
125
            if(strtolower($sequence->getName()) == 'list_sequences_test_seq') {
126
                $foundSequence = $sequence;
127
            }
128
        }
129
130
        self::assertNotNull($foundSequence, "Sequence with name 'list_sequences_test_seq' was not found.");
131
        self::assertEquals(20, $foundSequence->getAllocationSize(), "Allocation Size is expected to be 20.");
132
        self::assertEquals(10, $foundSequence->getInitialValue(), "Initial Value is expected to be 10.");
133
    }
134
135
    public function testListDatabases()
136
    {
137
        if (!$this->_sm->getDatabasePlatform()->supportsCreateDropDatabase()) {
138
            $this->markTestSkipped('Cannot drop Database client side with this Driver.');
139
        }
140
141
        $this->_sm->dropAndCreateDatabase('test_create_database');
142
        $databases = $this->_sm->listDatabases();
143
144
        $databases = array_map('strtolower', $databases);
145
146
        self::assertContains('test_create_database', $databases);
147
    }
148
149
    /**
150
     * @group DBAL-1058
151
     */
152
    public function testListNamespaceNames()
153
    {
154
        if (!$this->_sm->getDatabasePlatform()->supportsSchemas()) {
155
            $this->markTestSkipped('Platform does not support schemas.');
156
        }
157
158
        // Currently dropping schemas is not supported, so we have to workaround here.
159
        $namespaces = $this->_sm->listNamespaceNames();
160
        $namespaces = array_map('strtolower', $namespaces);
161
162
        if (!in_array('test_create_schema', $namespaces)) {
163
            $this->_conn->executeUpdate($this->_sm->getDatabasePlatform()->getCreateSchemaSQL('test_create_schema'));
164
165
            $namespaces = $this->_sm->listNamespaceNames();
166
            $namespaces = array_map('strtolower', $namespaces);
167
        }
168
169
        self::assertContains('test_create_schema', $namespaces);
170
    }
171
172
    public function testListTables()
173
    {
174
        $this->createTestTable('list_tables_test');
175
        $tables = $this->_sm->listTables();
176
177
        self::assertInternalType('array', $tables);
178
        self::assertTrue(count($tables) > 0, "List Tables has to find at least one table named 'list_tables_test'.");
179
180
        $foundTable = false;
181
        foreach ($tables as $table) {
182
            self::assertInstanceOf('Doctrine\DBAL\Schema\Table', $table);
183
            if (strtolower($table->getName()) == 'list_tables_test') {
184
                $foundTable = true;
185
186
                self::assertTrue($table->hasColumn('id'));
187
                self::assertTrue($table->hasColumn('test'));
188
                self::assertTrue($table->hasColumn('foreign_key_test'));
189
            }
190
        }
191
192
        self::assertTrue( $foundTable , "The 'list_tables_test' table has to be found.");
193
    }
194
195
    public function createListTableColumns()
196
    {
197
        $table = new Table('list_table_columns');
198
        $table->addColumn('id', 'integer', array('notnull' => true));
199
        $table->addColumn('test', 'string', array('length' => 255, 'notnull' => false, 'default' => 'expected default'));
200
        $table->addColumn('foo', 'text', array('notnull' => true));
201
        $table->addColumn('bar', 'decimal', array('precision' => 10, 'scale' => 4, 'notnull' => false));
202
        $table->addColumn('baz1', 'datetime');
203
        $table->addColumn('baz2', 'time');
204
        $table->addColumn('baz3', 'date');
205
        $table->setPrimaryKey(array('id'));
206
207
        return $table;
208
    }
209
210
    public function testListTableColumns()
211
    {
212
        $table = $this->createListTableColumns();
213
214
        $this->_sm->dropAndCreateTable($table);
215
216
        $columns = $this->_sm->listTableColumns('list_table_columns');
217
        $columnsKeys = array_keys($columns);
218
219
        self::assertArrayHasKey('id', $columns);
220
        self::assertEquals(0, array_search('id', $columnsKeys));
221
        self::assertEquals('id',   strtolower($columns['id']->getname()));
222
        self::assertInstanceOf('Doctrine\DBAL\Types\IntegerType', $columns['id']->gettype());
223
        self::assertEquals(false,  $columns['id']->getunsigned());
224
        self::assertEquals(true,   $columns['id']->getnotnull());
225
        self::assertEquals(null,   $columns['id']->getdefault());
226
        self::assertInternalType('array',  $columns['id']->getPlatformOptions());
227
228
        self::assertArrayHasKey('test', $columns);
229
        self::assertEquals(1, array_search('test', $columnsKeys));
230
        self::assertEquals('test', strtolower($columns['test']->getname()));
231
        self::assertInstanceOf('Doctrine\DBAL\Types\StringType', $columns['test']->gettype());
232
        self::assertEquals(255,    $columns['test']->getlength());
233
        self::assertEquals(false,  $columns['test']->getfixed());
234
        self::assertEquals(false,  $columns['test']->getnotnull());
235
        self::assertEquals('expected default',   $columns['test']->getdefault());
236
        self::assertInternalType('array',  $columns['test']->getPlatformOptions());
237
238
        self::assertEquals('foo',  strtolower($columns['foo']->getname()));
239
        self::assertEquals(2, array_search('foo', $columnsKeys));
240
        self::assertInstanceOf('Doctrine\DBAL\Types\TextType', $columns['foo']->gettype());
241
        self::assertEquals(false,  $columns['foo']->getunsigned());
242
        self::assertEquals(false,  $columns['foo']->getfixed());
243
        self::assertEquals(true,   $columns['foo']->getnotnull());
244
        self::assertEquals(null,   $columns['foo']->getdefault());
245
        self::assertInternalType('array',  $columns['foo']->getPlatformOptions());
246
247
        self::assertEquals('bar',  strtolower($columns['bar']->getname()));
248
        self::assertEquals(3, array_search('bar', $columnsKeys));
249
        self::assertInstanceOf('Doctrine\DBAL\Types\DecimalType', $columns['bar']->gettype());
250
        self::assertEquals(null,   $columns['bar']->getlength());
251
        self::assertEquals(10,     $columns['bar']->getprecision());
252
        self::assertEquals(4,      $columns['bar']->getscale());
253
        self::assertEquals(false,  $columns['bar']->getunsigned());
254
        self::assertEquals(false,  $columns['bar']->getfixed());
255
        self::assertEquals(false,  $columns['bar']->getnotnull());
256
        self::assertEquals(null,   $columns['bar']->getdefault());
257
        self::assertInternalType('array',  $columns['bar']->getPlatformOptions());
258
259
        self::assertEquals('baz1', strtolower($columns['baz1']->getname()));
260
        self::assertEquals(4, array_search('baz1', $columnsKeys));
261
        self::assertInstanceOf('Doctrine\DBAL\Types\DateTimeType', $columns['baz1']->gettype());
262
        self::assertEquals(true,   $columns['baz1']->getnotnull());
263
        self::assertEquals(null,   $columns['baz1']->getdefault());
264
        self::assertInternalType('array',  $columns['baz1']->getPlatformOptions());
265
266
        self::assertEquals('baz2', strtolower($columns['baz2']->getname()));
267
        self::assertEquals(5, array_search('baz2', $columnsKeys));
268
        self::assertContains($columns['baz2']->gettype()->getName(), array('time', 'date', 'datetime'));
269
        self::assertEquals(true,   $columns['baz2']->getnotnull());
270
        self::assertEquals(null,   $columns['baz2']->getdefault());
271
        self::assertInternalType('array',  $columns['baz2']->getPlatformOptions());
272
273
        self::assertEquals('baz3', strtolower($columns['baz3']->getname()));
274
        self::assertEquals(6, array_search('baz3', $columnsKeys));
275
        self::assertContains($columns['baz3']->gettype()->getName(), array('time', 'date', 'datetime'));
276
        self::assertEquals(true,   $columns['baz3']->getnotnull());
277
        self::assertEquals(null,   $columns['baz3']->getdefault());
278
        self::assertInternalType('array',  $columns['baz3']->getPlatformOptions());
279
    }
280
281
    /**
282
     * @group DBAL-1078
283
     */
284 View Code Duplication
    public function testListTableColumnsWithFixedStringColumn()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
285
    {
286
        $tableName = 'test_list_table_fixed_string';
287
288
        $table = new Table($tableName);
289
        $table->addColumn('column_char', 'string', array('fixed' => true, 'length' => 2));
290
291
        $this->_sm->createTable($table);
292
293
        $columns = $this->_sm->listTableColumns($tableName);
294
295
        self::assertArrayHasKey('column_char', $columns);
296
        self::assertInstanceOf('Doctrine\DBAL\Types\StringType', $columns['column_char']->getType());
297
        self::assertTrue($columns['column_char']->getFixed());
298
        self::assertSame(2, $columns['column_char']->getLength());
299
    }
300
301
    public function testListTableColumnsDispatchEvent()
302
    {
303
        $table = $this->createListTableColumns();
304
305
        $this->_sm->dropAndCreateTable($table);
306
307
        $listenerMock = $this
308
            ->getMockBuilder('ListTableColumnsDispatchEventListener')
309
            ->setMethods(['onSchemaColumnDefinition'])
310
            ->getMock();
311
        $listenerMock
312
            ->expects($this->exactly(7))
313
            ->method('onSchemaColumnDefinition');
314
315
        $oldEventManager = $this->_sm->getDatabasePlatform()->getEventManager();
316
317
        $eventManager = new EventManager();
318
        $eventManager->addEventListener(array(Events::onSchemaColumnDefinition), $listenerMock);
319
320
        $this->_sm->getDatabasePlatform()->setEventManager($eventManager);
321
322
        $this->_sm->listTableColumns('list_table_columns');
323
324
        $this->_sm->getDatabasePlatform()->setEventManager($oldEventManager);
325
    }
326
327
    public function testListTableIndexesDispatchEvent()
328
    {
329
        $table = $this->getTestTable('list_table_indexes_test');
330
        $table->addUniqueIndex(array('test'), 'test_index_name');
331
        $table->addIndex(array('id', 'test'), 'test_composite_idx');
332
333
        $this->_sm->dropAndCreateTable($table);
334
335
        $listenerMock = $this
336
            ->getMockBuilder('ListTableIndexesDispatchEventListener')
337
            ->setMethods(['onSchemaIndexDefinition'])
338
            ->getMock();
339
        $listenerMock
340
            ->expects($this->exactly(3))
341
            ->method('onSchemaIndexDefinition');
342
343
        $oldEventManager = $this->_sm->getDatabasePlatform()->getEventManager();
344
345
        $eventManager = new EventManager();
346
        $eventManager->addEventListener(array(Events::onSchemaIndexDefinition), $listenerMock);
347
348
        $this->_sm->getDatabasePlatform()->setEventManager($eventManager);
349
350
        $this->_sm->listTableIndexes('list_table_indexes_test');
351
352
        $this->_sm->getDatabasePlatform()->setEventManager($oldEventManager);
353
    }
354
355
    public function testDiffListTableColumns()
356
    {
357
        if ($this->_sm->getDatabasePlatform()->getName() == 'oracle') {
358
            $this->markTestSkipped('Does not work with Oracle, since it cannot detect DateTime, Date and Time differenecs (at the moment).');
359
        }
360
361
        $offlineTable = $this->createListTableColumns();
362
        $this->_sm->dropAndCreateTable($offlineTable);
363
        $onlineTable = $this->_sm->listTableDetails('list_table_columns');
364
365
        $comparator = new \Doctrine\DBAL\Schema\Comparator();
366
        $diff = $comparator->diffTable($offlineTable, $onlineTable);
367
368
        self::assertFalse($diff, "No differences should be detected with the offline vs online schema.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($...ineTable, $onlineTable) on line 366 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
369
    }
370
371
    public function testListTableIndexes()
372
    {
373
        $table = $this->getTestCompositeTable('list_table_indexes_test');
374
        $table->addUniqueIndex(array('test'), 'test_index_name');
375
        $table->addIndex(array('id', 'test'), 'test_composite_idx');
376
377
        $this->_sm->dropAndCreateTable($table);
378
379
        $tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test');
380
381
        self::assertEquals(3, count($tableIndexes));
382
383
        self::assertArrayHasKey('primary', $tableIndexes, 'listTableIndexes() has to return a "primary" array key.');
384
        self::assertEquals(array('id', 'other_id'), array_map('strtolower', $tableIndexes['primary']->getColumns()));
385
        self::assertTrue($tableIndexes['primary']->isUnique());
386
        self::assertTrue($tableIndexes['primary']->isPrimary());
387
388
        self::assertEquals('test_index_name', strtolower($tableIndexes['test_index_name']->getName()));
389
        self::assertEquals(array('test'), array_map('strtolower', $tableIndexes['test_index_name']->getColumns()));
390
        self::assertTrue($tableIndexes['test_index_name']->isUnique());
391
        self::assertFalse($tableIndexes['test_index_name']->isPrimary());
392
393
        self::assertEquals('test_composite_idx', strtolower($tableIndexes['test_composite_idx']->getName()));
394
        self::assertEquals(array('id', 'test'), array_map('strtolower', $tableIndexes['test_composite_idx']->getColumns()));
395
        self::assertFalse($tableIndexes['test_composite_idx']->isUnique());
396
        self::assertFalse($tableIndexes['test_composite_idx']->isPrimary());
397
    }
398
399
    public function testDropAndCreateIndex()
400
    {
401
        $table = $this->getTestTable('test_create_index');
402
        $table->addUniqueIndex(array('test'), 'test');
403
        $this->_sm->dropAndCreateTable($table);
404
405
        $this->_sm->dropAndCreateIndex($table->getIndex('test'), $table);
406
        $tableIndexes = $this->_sm->listTableIndexes('test_create_index');
407
        self::assertInternalType('array', $tableIndexes);
408
409
        self::assertEquals('test',        strtolower($tableIndexes['test']->getName()));
410
        self::assertEquals(array('test'), array_map('strtolower', $tableIndexes['test']->getColumns()));
411
        self::assertTrue($tableIndexes['test']->isUnique());
412
        self::assertFalse($tableIndexes['test']->isPrimary());
413
    }
414
415
    public function testCreateTableWithForeignKeys()
416
    {
417
        if(!$this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
418
            $this->markTestSkipped('Platform does not support foreign keys.');
419
        }
420
421
        $tableB = $this->getTestTable('test_foreign');
422
423
        $this->_sm->dropAndCreateTable($tableB);
424
425
        $tableA = $this->getTestTable('test_create_fk');
426
        $tableA->addForeignKeyConstraint('test_foreign', array('foreign_key_test'), array('id'));
427
428
        $this->_sm->dropAndCreateTable($tableA);
429
430
        $fkTable = $this->_sm->listTableDetails('test_create_fk');
431
        $fkConstraints = $fkTable->getForeignKeys();
432
        self::assertEquals(1, count($fkConstraints), "Table 'test_create_fk1' has to have one foreign key.");
433
434
        $fkConstraint = current($fkConstraints);
435
        self::assertInstanceOf('\Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkConstraint);
436
        self::assertEquals('test_foreign',             strtolower($fkConstraint->getForeignTableName()));
437
        self::assertEquals(array('foreign_key_test'),  array_map('strtolower', $fkConstraint->getColumns()));
438
        self::assertEquals(array('id'),                array_map('strtolower', $fkConstraint->getForeignColumns()));
439
440
        self::assertTrue($fkTable->columnsAreIndexed($fkConstraint->getColumns()), "The columns of a foreign key constraint should always be indexed.");
441
    }
442
443
    public function testListForeignKeys()
444
    {
445
        if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
446
            $this->markTestSkipped('Does not support foreign key constraints.');
447
        }
448
449
        $this->createTestTable('test_create_fk1');
450
        $this->createTestTable('test_create_fk2');
451
452
        $foreignKey = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
453
            array('foreign_key_test'), 'test_create_fk2', array('id'), 'foreign_key_test_fk', array('onDelete' => 'CASCADE')
454
        );
455
456
        $this->_sm->createForeignKey($foreignKey, 'test_create_fk1');
457
458
        $fkeys = $this->_sm->listTableForeignKeys('test_create_fk1');
459
460
        self::assertEquals(1, count($fkeys), "Table 'test_create_fk1' has to have one foreign key.");
461
462
        self::assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]);
463
        self::assertEquals(array('foreign_key_test'),  array_map('strtolower', $fkeys[0]->getLocalColumns()));
464
        self::assertEquals(array('id'),                array_map('strtolower', $fkeys[0]->getForeignColumns()));
465
        self::assertEquals('test_create_fk2',          strtolower($fkeys[0]->getForeignTableName()));
466
467
        if($fkeys[0]->hasOption('onDelete')) {
468
            self::assertEquals('CASCADE', $fkeys[0]->getOption('onDelete'));
469
        }
470
    }
471
472
    protected function getCreateExampleViewSql()
473
    {
474
        $this->markTestSkipped('No Create Example View SQL was defined for this SchemaManager');
475
    }
476
477
    public function testCreateSchema()
478
    {
479
        $this->createTestTable('test_table');
480
481
        $schema = $this->_sm->createSchema();
482
        self::assertTrue($schema->hasTable('test_table'));
483
    }
484
485
    public function testAlterTableScenario()
486
    {
487
        if(!$this->_sm->getDatabasePlatform()->supportsAlterTable()) {
488
            $this->markTestSkipped('Alter Table is not supported by this platform.');
489
        }
490
491
        $alterTable = $this->createTestTable('alter_table');
492
        $this->createTestTable('alter_table_foreign');
493
494
        $table = $this->_sm->listTableDetails('alter_table');
495
        self::assertTrue($table->hasColumn('id'));
496
        self::assertTrue($table->hasColumn('test'));
497
        self::assertTrue($table->hasColumn('foreign_key_test'));
498
        self::assertEquals(0, count($table->getForeignKeys()));
499
        self::assertEquals(1, count($table->getIndexes()));
500
501
        $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
502
        $tableDiff->fromTable = $alterTable;
503
        $tableDiff->addedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', Type::getType('integer'));
504
        $tableDiff->removedColumns['test'] = $table->getColumn('test');
505
506
        $this->_sm->alterTable($tableDiff);
507
508
        $table = $this->_sm->listTableDetails('alter_table');
509
        self::assertFalse($table->hasColumn('test'));
510
        self::assertTrue($table->hasColumn('foo'));
511
512
        $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
513
        $tableDiff->fromTable = $table;
514
        $tableDiff->addedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo'));
515
516
        $this->_sm->alterTable($tableDiff);
517
518
        $table = $this->_sm->listTableDetails('alter_table');
519
        self::assertEquals(2, count($table->getIndexes()));
520
        self::assertTrue($table->hasIndex('foo_idx'));
521
        self::assertEquals(array('foo'), array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
522
        self::assertFalse($table->getIndex('foo_idx')->isPrimary());
523
        self::assertFalse($table->getIndex('foo_idx')->isUnique());
524
525
        $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
526
        $tableDiff->fromTable = $table;
527
        $tableDiff->changedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test'));
528
529
        $this->_sm->alterTable($tableDiff);
530
531
        $table = $this->_sm->listTableDetails('alter_table');
532
        self::assertEquals(2, count($table->getIndexes()));
533
        self::assertTrue($table->hasIndex('foo_idx'));
534
        self::assertEquals(array('foo', 'foreign_key_test'), array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
535
536
        $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
537
        $tableDiff->fromTable = $table;
538
        $tableDiff->renamedIndexes['foo_idx'] = new \Doctrine\DBAL\Schema\Index('bar_idx', array('foo', 'foreign_key_test'));
539
540
        $this->_sm->alterTable($tableDiff);
541
542
        $table = $this->_sm->listTableDetails('alter_table');
543
        self::assertEquals(2, count($table->getIndexes()));
544
        self::assertTrue($table->hasIndex('bar_idx'));
545
        self::assertFalse($table->hasIndex('foo_idx'));
546
        self::assertEquals(array('foo', 'foreign_key_test'), array_map('strtolower', $table->getIndex('bar_idx')->getColumns()));
547
        self::assertFalse($table->getIndex('bar_idx')->isPrimary());
548
        self::assertFalse($table->getIndex('bar_idx')->isUnique());
549
550
        $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
551
        $tableDiff->fromTable = $table;
552
        $tableDiff->removedIndexes[] = new \Doctrine\DBAL\Schema\Index('bar_idx', array('foo', 'foreign_key_test'));
553
        $fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('foreign_key_test'), 'alter_table_foreign', array('id'));
554
        $tableDiff->addedForeignKeys[] = $fk;
555
556
        $this->_sm->alterTable($tableDiff);
557
        $table = $this->_sm->listTableDetails('alter_table');
558
559
        // dont check for index size here, some platforms automatically add indexes for foreign keys.
560
        self::assertFalse($table->hasIndex('bar_idx'));
561
562
        if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
563
            $fks = $table->getForeignKeys();
564
            self::assertCount(1, $fks);
565
            $foreignKey = current($fks);
566
            self::assertEquals('alter_table_foreign', strtolower($foreignKey->getForeignTableName()));
567
            self::assertEquals(array('foreign_key_test'), array_map('strtolower', $foreignKey->getColumns()));
568
            self::assertEquals(array('id'), array_map('strtolower', $foreignKey->getForeignColumns()));
569
        }
570
    }
571
572
    public function testCreateAndListViews()
573
    {
574
        if (!$this->_sm->getDatabasePlatform()->supportsViews()) {
575
            $this->markTestSkipped('Views is not supported by this platform.');
576
        }
577
578
        $this->createTestTable('view_test_table');
579
580
        $name = "doctrine_test_view";
581
        $sql = "SELECT * FROM view_test_table";
582
583
        $view = new \Doctrine\DBAL\Schema\View($name, $sql);
584
585
        $this->_sm->dropAndCreateView($view);
586
587
        self::assertTrue($this->hasElementWithName($this->_sm->listViews(), $name));
588
    }
589
590 View Code Duplication
    public function testAutoincrementDetection()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
591
    {
592
        if (!$this->_sm->getDatabasePlatform()->supportsIdentityColumns()) {
593
            $this->markTestSkipped('This test is only supported on platforms that have autoincrement');
594
        }
595
596
        $table = new Table('test_autoincrement');
597
        $table->setSchemaConfig($this->_sm->createSchemaConfig());
598
        $table->addColumn('id', 'integer', array('autoincrement' => true));
599
        $table->setPrimaryKey(array('id'));
600
601
        $this->_sm->createTable($table);
602
603
        $inferredTable = $this->_sm->listTableDetails('test_autoincrement');
604
        self::assertTrue($inferredTable->hasColumn('id'));
605
        self::assertTrue($inferredTable->getColumn('id')->getAutoincrement());
606
    }
607
608
    /**
609
     * @group DBAL-792
610
     */
611 View Code Duplication
    public function testAutoincrementDetectionMulticolumns()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
612
    {
613
        if (!$this->_sm->getDatabasePlatform()->supportsIdentityColumns()) {
614
            $this->markTestSkipped('This test is only supported on platforms that have autoincrement');
615
        }
616
617
        $table = new Table('test_not_autoincrement');
618
        $table->setSchemaConfig($this->_sm->createSchemaConfig());
619
        $table->addColumn('id', 'integer');
620
        $table->addColumn('other_id', 'integer');
621
        $table->setPrimaryKey(array('id', 'other_id'));
622
623
        $this->_sm->createTable($table);
624
625
        $inferredTable = $this->_sm->listTableDetails('test_not_autoincrement');
626
        self::assertTrue($inferredTable->hasColumn('id'));
627
        self::assertFalse($inferredTable->getColumn('id')->getAutoincrement());
628
    }
629
630
    /**
631
     * @group DDC-887
632
     */
633
    public function testUpdateSchemaWithForeignKeyRenaming()
634
    {
635
        if (!$this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
636
            $this->markTestSkipped('This test is only supported on platforms that have foreign keys.');
637
        }
638
639
        $table = new Table('test_fk_base');
640
        $table->addColumn('id', 'integer');
641
        $table->setPrimaryKey(array('id'));
642
643
        $tableFK = new Table('test_fk_rename');
644
        $tableFK->setSchemaConfig($this->_sm->createSchemaConfig());
645
        $tableFK->addColumn('id', 'integer');
646
        $tableFK->addColumn('fk_id', 'integer');
647
        $tableFK->setPrimaryKey(array('id'));
648
        $tableFK->addIndex(array('fk_id'), 'fk_idx');
649
        $tableFK->addForeignKeyConstraint('test_fk_base', array('fk_id'), array('id'));
650
651
        $this->_sm->createTable($table);
652
        $this->_sm->createTable($tableFK);
653
654
        $tableFKNew = new Table('test_fk_rename');
655
        $tableFKNew->setSchemaConfig($this->_sm->createSchemaConfig());
656
        $tableFKNew->addColumn('id', 'integer');
657
        $tableFKNew->addColumn('rename_fk_id', 'integer');
658
        $tableFKNew->setPrimaryKey(array('id'));
659
        $tableFKNew->addIndex(array('rename_fk_id'), 'fk_idx');
660
        $tableFKNew->addForeignKeyConstraint('test_fk_base', array('rename_fk_id'), array('id'));
661
662
        $c = new \Doctrine\DBAL\Schema\Comparator();
663
        $tableDiff = $c->diffTable($tableFK, $tableFKNew);
664
665
        $this->_sm->alterTable($tableDiff);
0 ignored issues
show
Security Bug introduced by
It seems like $tableDiff defined by $c->diffTable($tableFK, $tableFKNew) on line 663 can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
666
667
        $table       = $this->_sm->listTableDetails('test_fk_rename');
668
        $foreignKeys = $table->getForeignKeys();
669
670
        self::assertTrue($table->hasColumn('rename_fk_id'));
671
        self::assertCount(1, $foreignKeys);
672
        self::assertSame(['rename_fk_id'], array_map('strtolower', current($foreignKeys)->getColumns()));
673
    }
674
675
    /**
676
     * @group DBAL-1062
677
     */
678
    public function testRenameIndexUsedInForeignKeyConstraint()
679
    {
680
        if (! $this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
681
            $this->markTestSkipped('This test is only supported on platforms that have foreign keys.');
682
        }
683
684
        $primaryTable = new Table('test_rename_index_primary');
685
        $primaryTable->addColumn('id', 'integer');
686
        $primaryTable->setPrimaryKey(array('id'));
687
688
        $foreignTable = new Table('test_rename_index_foreign');
689
        $foreignTable->addColumn('fk', 'integer');
690
        $foreignTable->addIndex(array('fk'), 'rename_index_fk_idx');
691
        $foreignTable->addForeignKeyConstraint(
692
            'test_rename_index_primary',
693
            array('fk'),
694
            array('id'),
695
            array(),
696
            'fk_constraint'
697
        );
698
699
        $this->_sm->dropAndCreateTable($primaryTable);
700
        $this->_sm->dropAndCreateTable($foreignTable);
701
702
        $foreignTable2 = clone $foreignTable;
703
        $foreignTable2->renameIndex('rename_index_fk_idx', 'renamed_index_fk_idx');
704
705
        $comparator = new Comparator();
706
707
        $this->_sm->alterTable($comparator->diffTable($foreignTable, $foreignTable2));
0 ignored issues
show
Security Bug introduced by
It seems like $comparator->diffTable($...nTable, $foreignTable2) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?
Loading history...
708
709
        $foreignTable = $this->_sm->listTableDetails('test_rename_index_foreign');
710
711
        self::assertFalse($foreignTable->hasIndex('rename_index_fk_idx'));
712
        self::assertTrue($foreignTable->hasIndex('renamed_index_fk_idx'));
713
        self::assertTrue($foreignTable->hasForeignKey('fk_constraint'));
714
    }
715
716
    /**
717
     * @group DBAL-42
718
     */
719
    public function testGetColumnComment()
720
    {
721 View Code Duplication
        if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
722
             ! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
723
            $this->_conn->getDatabasePlatform()->getName() != 'mssql') {
724
            $this->markTestSkipped('Database does not support column comments.');
725
        }
726
727
        $table = new Table('column_comment_test');
728
        $table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
729
        $table->setPrimaryKey(array('id'));
730
731
        $this->_sm->createTable($table);
732
733
        $columns = $this->_sm->listTableColumns("column_comment_test");
734
        self::assertEquals(1, count($columns));
735
        self::assertEquals('This is a comment', $columns['id']->getComment());
736
737
        $tableDiff = new \Doctrine\DBAL\Schema\TableDiff('column_comment_test');
738
        $tableDiff->fromTable = $table;
739
        $tableDiff->changedColumns['id'] = new \Doctrine\DBAL\Schema\ColumnDiff(
740
            'id', new \Doctrine\DBAL\Schema\Column(
741
                'id', \Doctrine\DBAL\Types\Type::getType('integer'), array('primary' => true)
742
            ),
743
            array('comment'),
744
            new \Doctrine\DBAL\Schema\Column(
745
                'id', \Doctrine\DBAL\Types\Type::getType('integer'), array('comment' => 'This is a comment')
746
            )
747
        );
748
749
        $this->_sm->alterTable($tableDiff);
750
751
        $columns = $this->_sm->listTableColumns("column_comment_test");
752
        self::assertEquals(1, count($columns));
753
        self::assertEmpty($columns['id']->getComment());
754
    }
755
756
    /**
757
     * @group DBAL-42
758
     */
759
    public function testAutomaticallyAppendCommentOnMarkedColumns()
760
    {
761 View Code Duplication
        if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
762
             ! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
763
            $this->_conn->getDatabasePlatform()->getName() != 'mssql') {
764
            $this->markTestSkipped('Database does not support column comments.');
765
        }
766
767
        $table = new Table('column_comment_test2');
768
        $table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
769
        $table->addColumn('obj', 'object', array('comment' => 'This is a comment'));
770
        $table->addColumn('arr', 'array', array('comment' => 'This is a comment'));
771
        $table->setPrimaryKey(array('id'));
772
773
        $this->_sm->createTable($table);
774
775
        $columns = $this->_sm->listTableColumns("column_comment_test2");
776
        self::assertEquals(3, count($columns));
777
        self::assertEquals('This is a comment', $columns['id']->getComment());
778
        self::assertEquals('This is a comment', $columns['obj']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
779
        self::assertInstanceOf('Doctrine\DBAL\Types\ObjectType', $columns['obj']->getType(), "The Doctrine2 should be detected from comment hint.");
780
        self::assertEquals('This is a comment', $columns['arr']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
781
        self::assertInstanceOf('Doctrine\DBAL\Types\ArrayType', $columns['arr']->getType(), "The Doctrine2 should be detected from comment hint.");
782
    }
783
784
    /**
785
     * @group DBAL-1228
786
     */
787
    public function testCommentHintOnDateIntervalTypeColumn()
788
    {
789 View Code Duplication
        if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
790
            ! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
791
            $this->_conn->getDatabasePlatform()->getName() != 'mssql') {
792
            $this->markTestSkipped('Database does not support column comments.');
793
        }
794
795
        $table = new Table('column_dateinterval_comment');
796
        $table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
797
        $table->addColumn('date_interval', 'dateinterval', array('comment' => 'This is a comment'));
798
        $table->setPrimaryKey(array('id'));
799
800
        $this->_sm->createTable($table);
801
802
        $columns = $this->_sm->listTableColumns("column_dateinterval_comment");
803
        self::assertEquals(2, count($columns));
804
        self::assertEquals('This is a comment', $columns['id']->getComment());
805
        self::assertEquals('This is a comment', $columns['date_interval']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
806
        self::assertInstanceOf('Doctrine\DBAL\Types\DateIntervalType', $columns['date_interval']->getType(), "The Doctrine2 should be detected from comment hint.");
807
    }
808
809
    /**
810
     * @group DBAL-825
811
     */
812
    public function testChangeColumnsTypeWithDefaultValue()
813
    {
814
        $tableName = 'column_def_change_type';
815
        $table     = new Table($tableName);
816
817
        $table->addColumn('col_int', 'smallint', array('default' => 666));
818
        $table->addColumn('col_string', 'string', array('default' => 'foo'));
819
820
        $this->_sm->dropAndCreateTable($table);
821
822
        $tableDiff = new TableDiff($tableName);
823
        $tableDiff->fromTable = $table;
824
        $tableDiff->changedColumns['col_int'] = new ColumnDiff(
825
            'col_int',
826
            new Column('col_int', Type::getType('integer'), array('default' => 666)),
827
            array('type'),
828
            new Column('col_int', Type::getType('smallint'), array('default' => 666))
829
        );
830
831
        $tableDiff->changedColumns['col_string'] = new ColumnDiff(
832
            'col_string',
833
            new Column('col_string', Type::getType('string'), array('default' => 'foo', 'fixed' => true)),
834
            array('fixed'),
835
            new Column('col_string', Type::getType('string'), array('default' => 'foo'))
836
        );
837
838
        $this->_sm->alterTable($tableDiff);
839
840
        $columns = $this->_sm->listTableColumns($tableName);
841
842
        self::assertInstanceOf('Doctrine\DBAL\Types\IntegerType', $columns['col_int']->getType());
843
        self::assertEquals(666, $columns['col_int']->getDefault());
844
845
        self::assertInstanceOf('Doctrine\DBAL\Types\StringType', $columns['col_string']->getType());
846
        self::assertEquals('foo', $columns['col_string']->getDefault());
847
    }
848
849
    /**
850
     * @group DBAL-197
851
     */
852
    public function testListTableWithBlob()
853
    {
854
        $table = new Table('test_blob_table');
855
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
856
        $table->addColumn('binarydata', 'blob', []);
857
        $table->setPrimaryKey(['id']);
858
859
        $this->_sm->createTable($table);
860
861
        $created = $this->_sm->listTableDetails('test_blob_table');
862
863
        self::assertTrue($created->hasColumn('id'));
864
        self::assertTrue($created->hasColumn('binarydata'));
865
        self::assertTrue($created->hasPrimaryKey());
866
    }
867
868
    /**
869
     * @param string $name
870
     * @param array $data
871
     * @return Table
872
     */
873
    protected function createTestTable($name = 'test_table', $data = array())
874
    {
875
        $options = array();
876
        if (isset($data['options'])) {
877
            $options = $data['options'];
878
        }
879
880
        $table = $this->getTestTable($name, $options);
881
882
        $this->_sm->dropAndCreateTable($table);
883
884
        return $table;
885
    }
886
887
    protected function getTestTable($name, $options=array())
888
    {
889
        $table = new Table($name, array(), array(), array(), false, $options);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
890
        $table->setSchemaConfig($this->_sm->createSchemaConfig());
891
        $table->addColumn('id', 'integer', array('notnull' => true));
892
        $table->setPrimaryKey(array('id'));
893
        $table->addColumn('test', 'string', array('length' => 255));
894
        $table->addColumn('foreign_key_test', 'integer');
895
        return $table;
896
    }
897
898
    protected function getTestCompositeTable($name)
899
    {
900
        $table = new Table($name, array(), array(), array(), false, array());
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
901
        $table->setSchemaConfig($this->_sm->createSchemaConfig());
902
        $table->addColumn('id', 'integer', array('notnull' => true));
903
        $table->addColumn('other_id', 'integer', array('notnull' => true));
904
        $table->setPrimaryKey(array('id', 'other_id'));
905
        $table->addColumn('test', 'string', array('length' => 255));
906
        return $table;
907
    }
908
909
    protected function assertHasTable($tables, $tableName)
0 ignored issues
show
Unused Code introduced by
The parameter $tableName is not used and could be removed.

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

Loading history...
910
    {
911
        $foundTable = false;
912 View Code Duplication
        foreach ($tables as $table) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
913
            self::assertInstanceOf('Doctrine\DBAL\Schema\Table', $table, 'No Table instance was found in tables array.');
914
            if (strtolower($table->getName()) == 'list_tables_test_new_name') {
915
                $foundTable = true;
916
            }
917
        }
918
        self::assertTrue($foundTable, "Could not find new table");
919
    }
920
921
    public function testListForeignKeysComposite()
922
    {
923
        if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
924
            $this->markTestSkipped('Does not support foreign key constraints.');
925
        }
926
927
        $this->_sm->createTable($this->getTestTable('test_create_fk3'));
928
        $this->_sm->createTable($this->getTestCompositeTable('test_create_fk4'));
929
930
        $foreignKey = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
931
            array('id', 'foreign_key_test'), 'test_create_fk4', array('id', 'other_id'), 'foreign_key_test_fk2'
932
        );
933
934
        $this->_sm->createForeignKey($foreignKey, 'test_create_fk3');
935
936
        $fkeys = $this->_sm->listTableForeignKeys('test_create_fk3');
937
938
        self::assertEquals(1, count($fkeys), "Table 'test_create_fk3' has to have one foreign key.");
939
940
        self::assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]);
941
        self::assertEquals(array('id', 'foreign_key_test'), array_map('strtolower', $fkeys[0]->getLocalColumns()));
942
        self::assertEquals(array('id', 'other_id'),         array_map('strtolower', $fkeys[0]->getForeignColumns()));
943
    }
944
945
    /**
946
     * @group DBAL-44
947
     */
948
    public function testColumnDefaultLifecycle()
949
    {
950
        $table = new Table("col_def_lifecycle");
951
        $table->addColumn('id', 'integer', array('primary' => true, 'autoincrement' => true));
952
        $table->addColumn('column1', 'string', array('default' => null));
953
        $table->addColumn('column2', 'string', array('default' => false));
954
        $table->addColumn('column3', 'string', array('default' => true));
955
        $table->addColumn('column4', 'string', array('default' => 0));
956
        $table->addColumn('column5', 'string', array('default' => ''));
957
        $table->addColumn('column6', 'string', array('default' => 'def'));
958
        $table->addColumn('column7', 'integer', array('default' => 0));
959
        $table->setPrimaryKey(array('id'));
960
961
        $this->_sm->dropAndCreateTable($table);
962
963
        $columns = $this->_sm->listTableColumns('col_def_lifecycle');
964
965
        self::assertNull($columns['id']->getDefault());
966
        self::assertNull($columns['column1']->getDefault());
967
        self::assertSame('', $columns['column2']->getDefault());
968
        self::assertSame('1', $columns['column3']->getDefault());
969
        self::assertSame('0', $columns['column4']->getDefault());
970
        self::assertSame('', $columns['column5']->getDefault());
971
        self::assertSame('def', $columns['column6']->getDefault());
972
        self::assertSame('0', $columns['column7']->getDefault());
973
974
        $diffTable = clone $table;
975
976
        $diffTable->changeColumn('column1', array('default' => false));
977
        $diffTable->changeColumn('column2', array('default' => null));
978
        $diffTable->changeColumn('column3', array('default' => false));
979
        $diffTable->changeColumn('column4', array('default' => null));
980
        $diffTable->changeColumn('column5', array('default' => false));
981
        $diffTable->changeColumn('column6', array('default' => 666));
982
        $diffTable->changeColumn('column7', array('default' => null));
983
984
        $comparator = new Comparator();
985
986
        $this->_sm->alterTable($comparator->diffTable($table, $diffTable));
0 ignored issues
show
Security Bug introduced by
It seems like $comparator->diffTable($table, $diffTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?
Loading history...
987
988
        $columns = $this->_sm->listTableColumns('col_def_lifecycle');
989
990
        self::assertSame('', $columns['column1']->getDefault());
991
        self::assertNull($columns['column2']->getDefault());
992
        self::assertSame('', $columns['column3']->getDefault());
993
        self::assertNull($columns['column4']->getDefault());
994
        self::assertSame('', $columns['column5']->getDefault());
995
        self::assertSame('666', $columns['column6']->getDefault());
996
        self::assertNull($columns['column7']->getDefault());
997
    }
998
999 View Code Duplication
    public function testListTableWithBinary()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1000
    {
1001
        $tableName = 'test_binary_table';
1002
1003
        $table = new Table($tableName);
1004
        $table->addColumn('id', 'integer');
1005
        $table->addColumn('column_varbinary', 'binary', array());
1006
        $table->addColumn('column_binary', 'binary', array('fixed' => true));
1007
        $table->setPrimaryKey(array('id'));
1008
1009
        $this->_sm->createTable($table);
1010
1011
        $table = $this->_sm->listTableDetails($tableName);
1012
1013
        self::assertInstanceOf('Doctrine\DBAL\Types\BinaryType', $table->getColumn('column_varbinary')->getType());
1014
        self::assertFalse($table->getColumn('column_varbinary')->getFixed());
1015
1016
        self::assertInstanceOf('Doctrine\DBAL\Types\BinaryType', $table->getColumn('column_binary')->getType());
1017
        self::assertTrue($table->getColumn('column_binary')->getFixed());
1018
    }
1019
1020
    public function testListTableDetailsWithFullQualifiedTableName()
1021
    {
1022
        if ( ! $this->_sm->getDatabasePlatform()->supportsSchemas()) {
1023
            $this->markTestSkipped('Test only works on platforms that support schemas.');
1024
        }
1025
1026
        $defaultSchemaName = $this->_sm->getDatabasePlatform()->getDefaultSchemaName();
1027
        $primaryTableName  = 'primary_table';
1028
        $foreignTableName  = 'foreign_table';
1029
1030
        $table = new Table($foreignTableName);
1031
        $table->addColumn('id', 'integer', array('autoincrement' => true));
1032
        $table->setPrimaryKey(array('id'));
1033
1034
        $this->_sm->dropAndCreateTable($table);
1035
1036
        $table = new Table($primaryTableName);
1037
        $table->addColumn('id', 'integer', array('autoincrement' => true));
1038
        $table->addColumn('foo', 'integer');
1039
        $table->addColumn('bar', 'string');
1040
        $table->addForeignKeyConstraint($foreignTableName, array('foo'), array('id'));
1041
        $table->addIndex(array('bar'));
1042
        $table->setPrimaryKey(array('id'));
1043
1044
        $this->_sm->dropAndCreateTable($table);
1045
1046
        self::assertEquals(
1047
            $this->_sm->listTableColumns($primaryTableName),
1048
            $this->_sm->listTableColumns($defaultSchemaName . '.' . $primaryTableName)
1049
        );
1050
        self::assertEquals(
1051
            $this->_sm->listTableIndexes($primaryTableName),
1052
            $this->_sm->listTableIndexes($defaultSchemaName . '.' . $primaryTableName)
1053
        );
1054
        self::assertEquals(
1055
            $this->_sm->listTableForeignKeys($primaryTableName),
1056
            $this->_sm->listTableForeignKeys($defaultSchemaName . '.' . $primaryTableName)
1057
        );
1058
    }
1059
1060
    public function testCommentStringsAreQuoted()
1061
    {
1062 View Code Duplication
        if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1063
            ! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
1064
            $this->_conn->getDatabasePlatform()->getName() != 'mssql') {
1065
            $this->markTestSkipped('Database does not support column comments.');
1066
        }
1067
1068
        $table = new Table('my_table');
1069
        $table->addColumn('id', 'integer', array('comment' => "It's a comment with a quote"));
1070
        $table->setPrimaryKey(array('id'));
1071
1072
        $this->_sm->createTable($table);
1073
1074
        $columns = $this->_sm->listTableColumns("my_table");
1075
        self::assertEquals("It's a comment with a quote", $columns['id']->getComment());
1076
    }
1077
1078
    public function testCommentNotDuplicated()
1079
    {
1080
        if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments()) {
1081
            $this->markTestSkipped('Database does not support column comments.');
1082
        }
1083
1084
        $options = array(
1085
            'type' => Type::getType('integer'),
1086
            'default' => 0,
1087
            'notnull' => true,
1088
            'comment' => 'expected+column+comment',
1089
        );
1090
        $columnDefinition = substr($this->_conn->getDatabasePlatform()->getColumnDeclarationSQL('id', $options), strlen('id') + 1);
1091
1092
        $table = new Table('my_table');
1093
        $table->addColumn('id', 'integer', array('columnDefinition' => $columnDefinition, 'comment' => 'unexpected_column_comment'));
1094
        $sql = $this->_conn->getDatabasePlatform()->getCreateTableSQL($table);
1095
1096
        self::assertContains('expected+column+comment', $sql[0]);
1097
        self::assertNotContains('unexpected_column_comment', $sql[0]);
1098
    }
1099
1100
    /**
1101
     * @group DBAL-1009
1102
     *
1103
     * @dataProvider getAlterColumnComment
1104
     */
1105
    public function testAlterColumnComment($comment1, $expectedComment1, $comment2, $expectedComment2)
1106
    {
1107 View Code Duplication
        if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1108
            ! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
1109
            $this->_conn->getDatabasePlatform()->getName() != 'mssql') {
1110
            $this->markTestSkipped('Database does not support column comments.');
1111
        }
1112
1113
        $offlineTable = new Table('alter_column_comment_test');
1114
        $offlineTable->addColumn('comment1', 'integer', array('comment' => $comment1));
1115
        $offlineTable->addColumn('comment2', 'integer', array('comment' => $comment2));
1116
        $offlineTable->addColumn('no_comment1', 'integer');
1117
        $offlineTable->addColumn('no_comment2', 'integer');
1118
        $this->_sm->dropAndCreateTable($offlineTable);
1119
1120
        $onlineTable = $this->_sm->listTableDetails("alter_column_comment_test");
1121
1122
        self::assertSame($expectedComment1, $onlineTable->getColumn('comment1')->getComment());
1123
        self::assertSame($expectedComment2, $onlineTable->getColumn('comment2')->getComment());
1124
        self::assertNull($onlineTable->getColumn('no_comment1')->getComment());
1125
        self::assertNull($onlineTable->getColumn('no_comment2')->getComment());
1126
1127
        $onlineTable->changeColumn('comment1', array('comment' => $comment2));
1128
        $onlineTable->changeColumn('comment2', array('comment' => $comment1));
1129
        $onlineTable->changeColumn('no_comment1', array('comment' => $comment1));
1130
        $onlineTable->changeColumn('no_comment2', array('comment' => $comment2));
1131
1132
        $comparator = new Comparator();
1133
1134
        $tableDiff = $comparator->diffTable($offlineTable, $onlineTable);
1135
1136
        self::assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $tableDiff);
1137
1138
        $this->_sm->alterTable($tableDiff);
0 ignored issues
show
Security Bug introduced by
It seems like $tableDiff defined by $comparator->diffTable($...ineTable, $onlineTable) on line 1134 can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1139
1140
        $onlineTable = $this->_sm->listTableDetails("alter_column_comment_test");
1141
1142
        self::assertSame($expectedComment2, $onlineTable->getColumn('comment1')->getComment());
1143
        self::assertSame($expectedComment1, $onlineTable->getColumn('comment2')->getComment());
1144
        self::assertSame($expectedComment1, $onlineTable->getColumn('no_comment1')->getComment());
1145
        self::assertSame($expectedComment2, $onlineTable->getColumn('no_comment2')->getComment());
1146
    }
1147
1148
    public function getAlterColumnComment()
1149
    {
1150
        return array(
1151
            array(null, null, ' ', ' '),
1152
            array(null, null, '0', '0'),
1153
            array(null, null, 'foo', 'foo'),
1154
1155
            array('', null, ' ', ' '),
1156
            array('', null, '0', '0'),
1157
            array('', null, 'foo', 'foo'),
1158
1159
            array(' ', ' ', '0', '0'),
1160
            array(' ', ' ', 'foo', 'foo'),
1161
1162
            array('0', '0', 'foo', 'foo'),
1163
        );
1164
    }
1165
1166
    /**
1167
     * @group DBAL-1095
1168
     */
1169
    public function testDoesNotListIndexesImplicitlyCreatedByForeignKeys()
1170
    {
1171
        if (! $this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
1172
            $this->markTestSkipped('This test is only supported on platforms that have foreign keys.');
1173
        }
1174
1175
        $primaryTable = new Table('test_list_index_impl_primary');
1176
        $primaryTable->addColumn('id', 'integer');
1177
        $primaryTable->setPrimaryKey(array('id'));
1178
1179
        $foreignTable = new Table('test_list_index_impl_foreign');
1180
        $foreignTable->addColumn('fk1', 'integer');
1181
        $foreignTable->addColumn('fk2', 'integer');
1182
        $foreignTable->addIndex(array('fk1'), 'explicit_fk1_idx');
1183
        $foreignTable->addForeignKeyConstraint('test_list_index_impl_primary', array('fk1'), array('id'));
1184
        $foreignTable->addForeignKeyConstraint('test_list_index_impl_primary', array('fk2'), array('id'));
1185
1186
        $this->_sm->dropAndCreateTable($primaryTable);
1187
        $this->_sm->dropAndCreateTable($foreignTable);
1188
1189
        $indexes = $this->_sm->listTableIndexes('test_list_index_impl_foreign');
1190
1191
        self::assertCount(2, $indexes);
1192
        self::assertArrayHasKey('explicit_fk1_idx', $indexes);
1193
        self::assertArrayHasKey('idx_3d6c147fdc58d6c', $indexes);
1194
    }
1195
}
1196