Failed Conditions
Push — 2.6 ( 2202ad...830203 )
by Luís
04:38
created

testAlterTableAutoIncrementIntToBigInt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 9.2
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 3
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional\Schema;
4
5
use Doctrine\DBAL\Platforms\AbstractPlatform;
6
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
7
use Doctrine\DBAL\Schema;
8
use Doctrine\DBAL\Schema\Comparator;
9
use Doctrine\DBAL\Schema\Table;
10
use Doctrine\DBAL\Schema\TableDiff;
11
use Doctrine\DBAL\Types\Type;
12
13
class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
14
{
15
    protected function tearDown()
16
    {
17
        parent::tearDown();
18
19
        if (!$this->_conn) {
20
            return;
21
        }
22
23
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression(null);
24
    }
25
26
    /**
27
     * @group DBAL-177
28
     */
29
    public function testGetSearchPath()
30
    {
31
        $params = $this->_conn->getParams();
32
33
        $paths = $this->_sm->getSchemaSearchPaths();
34
        $this->assertEquals([$params['user'], 'public'], $paths);
35
    }
36
37
    /**
38
     * @group DBAL-244
39
     */
40
    public function testGetSchemaNames()
41
    {
42
        $names = $this->_sm->getSchemaNames();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Doctrine\DBAL\Schema\AbstractSchemaManager as the method getSchemaNames() does only exist in the following sub-classes of Doctrine\DBAL\Schema\AbstractSchemaManager: Doctrine\DBAL\Schema\PostgreSqlSchemaManager. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
43
44
        $this->assertInternalType('array', $names);
45
        $this->assertTrue(count($names) > 0);
46
        $this->assertContains('public', $names, 'The public schema should be found.');
47
    }
48
49
    /**
50
     * @group DBAL-21
51
     */
52
    public function testSupportDomainTypeFallback()
53
    {
54
        $createDomainTypeSQL = "CREATE DOMAIN MyMoney AS DECIMAL(18,2)";
55
        $this->_conn->exec($createDomainTypeSQL);
56
57
        $createTableSQL = "CREATE TABLE domain_type_test (id INT PRIMARY KEY, value MyMoney)";
58
        $this->_conn->exec($createTableSQL);
59
60
        $table = $this->_conn->getSchemaManager()->listTableDetails('domain_type_test');
61
        $this->assertInstanceOf('Doctrine\DBAL\Types\DecimalType', $table->getColumn('value')->getType());
62
63
        Type::addType('MyMoney', 'Doctrine\Tests\DBAL\Functional\Schema\MoneyType');
64
        $this->_conn->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'MyMoney');
65
66
        $table = $this->_conn->getSchemaManager()->listTableDetails('domain_type_test');
67
        $this->assertInstanceOf('Doctrine\Tests\DBAL\Functional\Schema\MoneyType', $table->getColumn('value')->getType());
68
    }
69
70
    /**
71
     * @group DBAL-37
72
     */
73
    public function testDetectsAutoIncrement()
74
    {
75
        $autoincTable = new \Doctrine\DBAL\Schema\Table('autoinc_table');
76
        $column = $autoincTable->addColumn('id', 'integer');
77
        $column->setAutoincrement(true);
78
        $this->_sm->createTable($autoincTable);
79
        $autoincTable = $this->_sm->listTableDetails('autoinc_table');
80
81
        $this->assertTrue($autoincTable->getColumn('id')->getAutoincrement());
82
    }
83
84
    /**
85
     * @group DBAL-37
86
     */
87 View Code Duplication
    public function testAlterTableAutoIncrementAdd()
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...
88
    {
89
        $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_add');
90
        $column = $tableFrom->addColumn('id', 'integer');
0 ignored issues
show
Unused Code introduced by
$column is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
91
        $this->_sm->createTable($tableFrom);
92
        $tableFrom = $this->_sm->listTableDetails('autoinc_table_add');
93
        $this->assertFalse($tableFrom->getColumn('id')->getAutoincrement());
94
95
        $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_add');
96
        $column = $tableTo->addColumn('id', 'integer');
97
        $column->setAutoincrement(true);
98
99
        $c = new \Doctrine\DBAL\Schema\Comparator();
100
        $diff = $c->diffTable($tableFrom, $tableTo);
101
        $sql = $this->_conn->getDatabasePlatform()->getAlterTableSQL($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 100 can also be of type false; however, Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() 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...
102
        $this->assertEquals(array(
103
            "CREATE SEQUENCE autoinc_table_add_id_seq",
104
            "SELECT setval('autoinc_table_add_id_seq', (SELECT MAX(id) FROM autoinc_table_add))",
105
            "ALTER TABLE autoinc_table_add ALTER id SET DEFAULT nextval('autoinc_table_add_id_seq')",
106
        ), $sql);
107
108
        $this->_sm->alterTable($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 100 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...
109
        $tableFinal = $this->_sm->listTableDetails('autoinc_table_add');
110
        $this->assertTrue($tableFinal->getColumn('id')->getAutoincrement());
111
    }
112
113
    /**
114
     * @group DBAL-37
115
     */
116 View Code Duplication
    public function testAlterTableAutoIncrementDrop()
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...
117
    {
118
        $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_drop');
119
        $column = $tableFrom->addColumn('id', 'integer');
120
        $column->setAutoincrement(true);
121
        $this->_sm->createTable($tableFrom);
122
        $tableFrom = $this->_sm->listTableDetails('autoinc_table_drop');
123
        $this->assertTrue($tableFrom->getColumn('id')->getAutoincrement());
124
125
        $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_drop');
126
        $column = $tableTo->addColumn('id', 'integer');
0 ignored issues
show
Unused Code introduced by
$column is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
127
128
        $c = new \Doctrine\DBAL\Schema\Comparator();
129
        $diff = $c->diffTable($tableFrom, $tableTo);
130
        $this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
131
        $this->assertEquals(array("ALTER TABLE autoinc_table_drop ALTER id DROP DEFAULT"), $this->_conn->getDatabasePlatform()->getAlterTableSQL($diff));
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 129 can also be of type false; however, Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() 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...
132
133
        $this->_sm->alterTable($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 129 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...
134
        $tableFinal = $this->_sm->listTableDetails('autoinc_table_drop');
135
        $this->assertFalse($tableFinal->getColumn('id')->getAutoincrement());
136
    }
137
138
    /**
139
     * @group DBAL-75
140
     */
141
    public function testTableWithSchema()
142
    {
143
        $this->_conn->exec('CREATE SCHEMA nested');
144
145
        $nestedRelatedTable = new \Doctrine\DBAL\Schema\Table('nested.schemarelated');
146
        $column = $nestedRelatedTable->addColumn('id', 'integer');
147
        $column->setAutoincrement(true);
148
        $nestedRelatedTable->setPrimaryKey(array('id'));
149
150
        $nestedSchemaTable = new \Doctrine\DBAL\Schema\Table('nested.schematable');
151
        $column = $nestedSchemaTable->addColumn('id', 'integer');
152
        $column->setAutoincrement(true);
153
        $nestedSchemaTable->setPrimaryKey(array('id'));
154
        $nestedSchemaTable->addUnnamedForeignKeyConstraint($nestedRelatedTable, array('id'), array('id'));
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\DBAL\Schema\Tab...dForeignKeyConstraint() has been deprecated with message: Use {@link addForeignKeyConstraint}

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

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

Loading history...
155
156
        $this->_sm->createTable($nestedRelatedTable);
157
        $this->_sm->createTable($nestedSchemaTable);
158
159
        $tables = $this->_sm->listTableNames();
160
        $this->assertContains('nested.schematable', $tables, "The table should be detected with its non-public schema.");
161
162
        $nestedSchemaTable = $this->_sm->listTableDetails('nested.schematable');
163
        $this->assertTrue($nestedSchemaTable->hasColumn('id'));
164
        $this->assertEquals(array('id'), $nestedSchemaTable->getPrimaryKey()->getColumns());
165
166
        $relatedFks = $nestedSchemaTable->getForeignKeys();
167
        $this->assertEquals(1, count($relatedFks));
168
        $relatedFk = array_pop($relatedFks);
169
        $this->assertEquals("nested.schemarelated", $relatedFk->getForeignTableName());
170
    }
171
172
    /**
173
     * @group DBAL-91
174
     * @group DBAL-88
175
     */
176
    public function testReturnQuotedAssets()
177
    {
178
        $sql = 'create table dbal91_something ( id integer  CONSTRAINT id_something PRIMARY KEY NOT NULL  ,"table"   integer );';
179
        $this->_conn->exec($sql);
180
181
        $sql = 'ALTER TABLE dbal91_something ADD CONSTRAINT something_input FOREIGN KEY( "table" ) REFERENCES dbal91_something ON UPDATE CASCADE;';
182
        $this->_conn->exec($sql);
183
184
        $table = $this->_sm->listTableDetails('dbal91_something');
185
186
        $this->assertEquals(
187
            array(
188
                "CREATE TABLE dbal91_something (id INT NOT NULL, \"table\" INT DEFAULT NULL, PRIMARY KEY(id))",
189
                "CREATE INDEX IDX_A9401304ECA7352B ON dbal91_something (\"table\")",
190
            ),
191
            $this->_conn->getDatabasePlatform()->getCreateTableSQL($table)
192
        );
193
    }
194
195
    /**
196
     * @group DBAL-204
197
     */
198
    public function testFilterSchemaExpression()
199
    {
200
        $testTable = new \Doctrine\DBAL\Schema\Table('dbal204_test_prefix');
201
        $column = $testTable->addColumn('id', 'integer');
0 ignored issues
show
Unused Code introduced by
$column is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
202
        $this->_sm->createTable($testTable);
203
        $testTable = new \Doctrine\DBAL\Schema\Table('dbal204_without_prefix');
204
        $column = $testTable->addColumn('id', 'integer');
0 ignored issues
show
Unused Code introduced by
$column is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
205
        $this->_sm->createTable($testTable);
206
207
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_#');
208
        $names = $this->_sm->listTableNames();
209
        $this->assertEquals(2, count($names));
210
211
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_test#');
212
        $names = $this->_sm->listTableNames();
213
        $this->assertEquals(1, count($names));
214
    }
215
216
    public function testListForeignKeys()
217
    {
218
        if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
219
            $this->markTestSkipped('Does not support foreign key constraints.');
220
        }
221
222
        $fkOptions = array('SET NULL', 'SET DEFAULT', 'NO ACTION','CASCADE', 'RESTRICT');
223
        $foreignKeys = array();
224
        $fkTable = $this->getTestTable('test_create_fk1');
225
        for($i = 0; $i < count($fkOptions); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
226
            $fkTable->addColumn("foreign_key_test$i", 'integer');
227
            $foreignKeys[] = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
228
                                 array("foreign_key_test$i"), 'test_create_fk2', array('id'), "foreign_key_test_$i"."_fk", array('onDelete' => $fkOptions[$i]));
229
        }
230
        $this->_sm->dropAndCreateTable($fkTable);
231
        $this->createTestTable('test_create_fk2');
232
233
        foreach($foreignKeys as $foreignKey) {
234
            $this->_sm->createForeignKey($foreignKey, 'test_create_fk1');
235
        }
236
        $fkeys = $this->_sm->listTableForeignKeys('test_create_fk1');
237
        $this->assertEquals(count($foreignKeys), count($fkeys), "Table 'test_create_fk1' has to have " . count($foreignKeys) . " foreign keys.");
238
        for ($i = 0; $i < count($fkeys); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
239
            $this->assertEquals(array("foreign_key_test$i"), array_map('strtolower', $fkeys[$i]->getLocalColumns()));
240
            $this->assertEquals(array('id'), array_map('strtolower', $fkeys[$i]->getForeignColumns()));
241
            $this->assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
242
            if ($foreignKeys[$i]->getOption('onDelete') == 'NO ACTION') {
243
                $this->assertFalse($fkeys[$i]->hasOption('onDelete'), 'Unexpected option: '. $fkeys[$i]->getOption('onDelete'));
244
            } else {
245
                $this->assertEquals($foreignKeys[$i]->getOption('onDelete'), $fkeys[$i]->getOption('onDelete'));
246
            }
247
        }
248
    }
249
250
    /**
251
     * @group DBAL-511
252
     */
253 View Code Duplication
    public function testDefaultValueCharacterVarying()
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...
254
    {
255
        $testTable = new \Doctrine\DBAL\Schema\Table('dbal511_default');
256
        $testTable->addColumn('id', 'integer');
257
        $testTable->addColumn('def', 'string', array('default' => 'foo'));
258
        $testTable->setPrimaryKey(array('id'));
259
260
        $this->_sm->createTable($testTable);
261
262
        $databaseTable = $this->_sm->listTableDetails($testTable->getName());
263
264
        $this->assertEquals('foo', $databaseTable->getColumn('def')->getDefault());
265
    }
266
267
    /**
268
     * @group DDC-2843
269
     */
270 View Code Duplication
    public function testBooleanDefault()
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...
271
    {
272
        $table = new \Doctrine\DBAL\Schema\Table('ddc2843_bools');
273
        $table->addColumn('id', 'integer');
274
        $table->addColumn('checked', 'boolean', array('default' => false));
275
276
        $this->_sm->createTable($table);
277
278
        $databaseTable = $this->_sm->listTableDetails($table->getName());
279
280
        $c = new \Doctrine\DBAL\Schema\Comparator();
281
        $diff = $c->diffTable($table, $databaseTable);
282
283
        $this->assertFalse($diff);
284
    }
285
286 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...
287
    {
288
        $tableName = 'test_binary_table';
289
290
        $table = new \Doctrine\DBAL\Schema\Table($tableName);
291
        $table->addColumn('id', 'integer');
292
        $table->addColumn('column_varbinary', 'binary', array());
293
        $table->addColumn('column_binary', 'binary', array('fixed' => true));
294
        $table->setPrimaryKey(array('id'));
295
296
        $this->_sm->createTable($table);
297
298
        $table = $this->_sm->listTableDetails($tableName);
299
300
        $this->assertInstanceOf('Doctrine\DBAL\Types\BlobType', $table->getColumn('column_varbinary')->getType());
301
        $this->assertFalse($table->getColumn('column_varbinary')->getFixed());
302
303
        $this->assertInstanceOf('Doctrine\DBAL\Types\BlobType', $table->getColumn('column_binary')->getType());
304
        $this->assertFalse($table->getColumn('column_binary')->getFixed());
305
    }
306
307
    public function testListQuotedTable()
308
    {
309
        $offlineTable = new Schema\Table('user');
310
        $offlineTable->addColumn('id', 'integer');
311
        $offlineTable->addColumn('username', 'string', array('unique' => true));
312
        $offlineTable->addColumn('fk', 'integer');
313
        $offlineTable->setPrimaryKey(array('id'));
314
        $offlineTable->addForeignKeyConstraint($offlineTable, array('fk'), array('id'));
315
316
        $this->_sm->dropAndCreateTable($offlineTable);
317
318
        $onlineTable = $this->_sm->listTableDetails('"user"');
319
320
        $comparator = new Schema\Comparator();
321
322
        $this->assertFalse($comparator->diffTable($offlineTable, $onlineTable));
323
    }
324
325
    public function testListTablesExcludesViews()
326
    {
327
        $this->createTestTable('list_tables_excludes_views');
328
329
        $name = "list_tables_excludes_views_test_view";
330
        $sql = "SELECT * from list_tables_excludes_views";
331
332
        $view = new Schema\View($name, $sql);
333
334
        $this->_sm->dropAndCreateView($view);
335
336
        $tables = $this->_sm->listTables();
337
338
        $foundTable = false;
339 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...
340
            $this->assertInstanceOf('Doctrine\DBAL\Schema\Table', $table, 'No Table instance was found in tables array.');
341
            if (strtolower($table->getName()) == 'list_tables_excludes_views_test_view') {
342
                $foundTable = true;
343
            }
344
        }
345
346
        $this->assertFalse($foundTable, 'View "list_tables_excludes_views_test_view" must not be found in table list');
347
    }
348
349
    /**
350
     * @group DBAL-1033
351
     */
352
    public function testPartialIndexes()
353
    {
354
        $offlineTable = new Schema\Table('person');
355
        $offlineTable->addColumn('id', 'integer');
356
        $offlineTable->addColumn('name', 'string');
357
        $offlineTable->addColumn('email', 'string');
358
        $offlineTable->addUniqueIndex(array('id', 'name'), 'simple_partial_index', array('where' => '(id IS NULL)'));
359
360
        $this->_sm->dropAndCreateTable($offlineTable);
361
362
        $onlineTable = $this->_sm->listTableDetails('person');
363
364
        $comparator = new Schema\Comparator();
365
366
        $this->assertFalse($comparator->diffTable($offlineTable, $onlineTable));
367
        $this->assertTrue($onlineTable->hasIndex('simple_partial_index'));
368
        $this->assertTrue($onlineTable->getIndex('simple_partial_index')->hasOption('where'));
369
        $this->assertSame('(id IS NULL)', $onlineTable->getIndex('simple_partial_index')->getOption('where'));
370
    }
371
372
    /**
373
     * @dataProvider jsonbColumnTypeProvider
374
     */
375
    public function testJsonbColumn(string $type): void
376
    {
377
        if (!$this->_sm->getDatabasePlatform() instanceof PostgreSQL94Platform) {
378
            $this->markTestSkipped("Requires PostgresSQL 9.4+");
379
            return;
380
        }
381
382
        $table = new Schema\Table('test_jsonb');
383
        $table->addColumn('foo', $type)->setPlatformOption('jsonb', true);
384
        $this->_sm->dropAndCreateTable($table);
385
386
        /** @var Schema\Column[] $columns */
387
        $columns = $this->_sm->listTableColumns('test_jsonb');
388
389
        $this->assertSame($type, $columns['foo']->getType()->getName());
390
        $this->assertTrue(true, $columns['foo']->getPlatformOption('jsonb'));
391
    }
392
393
    public function jsonbColumnTypeProvider(): array
394
    {
395
        return [
396
            [Type::JSON],
397
            [Type::JSON_ARRAY],
398
        ];
399
    }
400
401
    /**
402
     * @group DBAL-2427
403
     */
404
    public function testListNegativeColumnDefaultValue()
405
    {
406
        $table = new Schema\Table('test_default_negative');
407
        $table->addColumn('col_smallint', 'smallint', array('default' => -1));
408
        $table->addColumn('col_integer', 'integer', array('default' => -1));
409
        $table->addColumn('col_bigint', 'bigint', array('default' => -1));
410
        $table->addColumn('col_float', 'float', array('default' => -1.1));
411
        $table->addColumn('col_decimal', 'decimal', array('default' => -1.1));
412
        $table->addColumn('col_string', 'string', array('default' => '(-1)'));
413
414
        $this->_sm->dropAndCreateTable($table);
415
416
        $columns = $this->_sm->listTableColumns('test_default_negative');
417
418
        $this->assertEquals(-1, $columns['col_smallint']->getDefault());
419
        $this->assertEquals(-1, $columns['col_integer']->getDefault());
420
        $this->assertEquals(-1, $columns['col_bigint']->getDefault());
421
        $this->assertEquals(-1.1, $columns['col_float']->getDefault());
422
        $this->assertEquals(-1.1, $columns['col_decimal']->getDefault());
423
        $this->assertEquals('(-1)', $columns['col_string']->getDefault());
424
    }
425
426
    public static function serialTypes() : array
427
    {
428
        return [
429
            ['integer'],
430
            ['bigint'],
431
        ];
432
    }
433
434
    /**
435
     * @dataProvider serialTypes
436
     * @group 2906
437
     */
438 View Code Duplication
    public function testAutoIncrementCreatesSerialDataTypesWithoutADefaultValue(string $type) : void
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...
439
    {
440
        $tableName = "test_serial_type_$type";
441
442
        $table = new Schema\Table($tableName);
443
        $table->addColumn('id', $type, ['autoincrement' => true, 'notnull' => false]);
444
445
        $this->_sm->dropAndCreateTable($table);
446
447
        $columns = $this->_sm->listTableColumns($tableName);
448
449
        self::assertNull($columns['id']->getDefault());
450
    }
451
452
    /**
453
     * @dataProvider serialTypes
454
     * @group 2906
455
     */
456 View Code Duplication
    public function testAutoIncrementCreatesSerialDataTypesWithoutADefaultValueEvenWhenDefaultIsSet(string $type) : void
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...
457
    {
458
        $tableName = "test_serial_type_with_default_$type";
459
460
        $table = new Schema\Table($tableName);
461
        $table->addColumn('id', $type, ['autoincrement' => true, 'notnull' => false, 'default' => 1]);
462
463
        $this->_sm->dropAndCreateTable($table);
464
465
        $columns = $this->_sm->listTableColumns($tableName);
466
467
        self::assertNull($columns['id']->getDefault());
468
    }
469
470
    /**
471
     * @group 2916
472
     *
473
     * @dataProvider autoIncrementTypeMigrations
474
     */
475
    public function testAlterTableAutoIncrementIntToBigInt(string $from, string $to, string $expected) : void
476
    {
477
        $tableFrom = new Table('autoinc_type_modification');
478
        $column = $tableFrom->addColumn('id', $from);
479
        $column->setAutoincrement(true);
480
        $this->_sm->dropAndCreateTable($tableFrom);
481
        $tableFrom = $this->_sm->listTableDetails('autoinc_type_modification');
482
        self::assertTrue($tableFrom->getColumn('id')->getAutoincrement());
483
484
        $tableTo = new Table('autoinc_type_modification');
485
        $column = $tableTo->addColumn('id', $to);
486
        $column->setAutoincrement(true);
487
488
        $c = new Comparator();
489
        $diff = $c->diffTable($tableFrom, $tableTo);
490
        self::assertInstanceOf(TableDiff::class, $diff, "There should be a difference and not false being returned from the table comparison");
491
        self::assertSame(['ALTER TABLE autoinc_type_modification ALTER id TYPE ' . $expected], $this->_conn->getDatabasePlatform()->getAlterTableSQL($diff));
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 489 can also be of type false; however, Doctrine\DBAL\Platforms\...orm::getAlterTableSQL() 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...
492
493
        $this->_sm->alterTable($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 489 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...
494
        $tableFinal = $this->_sm->listTableDetails('autoinc_type_modification');
495
        self::assertTrue($tableFinal->getColumn('id')->getAutoincrement());
496
    }
497
498
    public function autoIncrementTypeMigrations() : array
499
    {
500
        return [
501
            'int->bigint' => ['integer', 'bigint', 'BIGINT'],
502
            'bigint->int' => ['bigint', 'integer', 'INT'],
503
        ];
504
    }
505
}
506
507
class MoneyType extends Type
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
508
{
509
510
    public function getName()
511
    {
512
        return "MyMoney";
513
    }
514
515
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
516
    {
517
        return 'MyMoney';
518
    }
519
520
}
521