Test Failed
Pull Request — master (#2916)
by Robin
64:40
created

testAlterTableAutoIncrementBigInt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 17

Duplication

Lines 22
Ratio 100 %

Importance

Changes 0
Metric Value
dl 22
loc 22
rs 9.2
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 0
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\Types\Type;
9
10
class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
11
{
12
    protected function tearDown()
13
    {
14
        parent::tearDown();
15
16
        if (!$this->_conn) {
17
            return;
18
        }
19
20
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression(null);
21
    }
22
23
    /**
24
     * @group DBAL-177
25
     */
26
    public function testGetSearchPath()
27
    {
28
        $params = $this->_conn->getParams();
29
30
        $paths = $this->_sm->getSchemaSearchPaths();
31
        self::assertEquals([$params['user'], 'public'], $paths);
32
    }
33
34
    /**
35
     * @group DBAL-244
36
     */
37
    public function testGetSchemaNames()
38
    {
39
        $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...
40
41
        self::assertInternalType('array', $names);
42
        self::assertTrue(count($names) > 0);
43
        self::assertContains('public', $names, 'The public schema should be found.');
44
    }
45
46
    /**
47
     * @group DBAL-21
48
     */
49
    public function testSupportDomainTypeFallback()
50
    {
51
        $createDomainTypeSQL = "CREATE DOMAIN MyMoney AS DECIMAL(18,2)";
52
        $this->_conn->exec($createDomainTypeSQL);
53
54
        $createTableSQL = "CREATE TABLE domain_type_test (id INT PRIMARY KEY, value MyMoney)";
55
        $this->_conn->exec($createTableSQL);
56
57
        $table = $this->_conn->getSchemaManager()->listTableDetails('domain_type_test');
58
        self::assertInstanceOf('Doctrine\DBAL\Types\DecimalType', $table->getColumn('value')->getType());
59
60
        Type::addType('MyMoney', 'Doctrine\Tests\DBAL\Functional\Schema\MoneyType');
61
        $this->_conn->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'MyMoney');
62
63
        $table = $this->_conn->getSchemaManager()->listTableDetails('domain_type_test');
64
        self::assertInstanceOf('Doctrine\Tests\DBAL\Functional\Schema\MoneyType', $table->getColumn('value')->getType());
65
    }
66
67
    /**
68
     * @group DBAL-37
69
     */
70
    public function testDetectsAutoIncrement()
71
    {
72
        $autoincTable = new \Doctrine\DBAL\Schema\Table('autoinc_table');
73
        $column = $autoincTable->addColumn('id', 'integer');
74
        $column->setAutoincrement(true);
75
        $this->_sm->createTable($autoincTable);
76
        $autoincTable = $this->_sm->listTableDetails('autoinc_table');
77
78
        self::assertTrue($autoincTable->getColumn('id')->getAutoincrement());
79
    }
80
81
    /**
82
     * @group DBAL-37
83
     */
84 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...
85
    {
86
        $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_add');
87
        $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...
88
        $this->_sm->createTable($tableFrom);
89
        $tableFrom = $this->_sm->listTableDetails('autoinc_table_add');
90
        self::assertFalse($tableFrom->getColumn('id')->getAutoincrement());
91
92
        $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_add');
93
        $column = $tableTo->addColumn('id', 'integer');
94
        $column->setAutoincrement(true);
95
96
        $c = new \Doctrine\DBAL\Schema\Comparator();
97
        $diff = $c->diffTable($tableFrom, $tableTo);
98
        $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 97 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...
99
        self::assertEquals(array(
100
            "CREATE SEQUENCE autoinc_table_add_id_seq",
101
            "SELECT setval('autoinc_table_add_id_seq', (SELECT MAX(id) FROM autoinc_table_add))",
102
            "ALTER TABLE autoinc_table_add ALTER id SET DEFAULT nextval('autoinc_table_add_id_seq')",
103
        ), $sql);
104
105
        $this->_sm->alterTable($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 97 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...
106
        $tableFinal = $this->_sm->listTableDetails('autoinc_table_add');
107
        self::assertTrue($tableFinal->getColumn('id')->getAutoincrement());
108
    }
109
110
    /**
111
     * @group DBAL-37
112
     */
113 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...
114
    {
115
        $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_drop');
116
        $column = $tableFrom->addColumn('id', 'integer');
117
        $column->setAutoincrement(true);
118
        $this->_sm->createTable($tableFrom);
119
        $tableFrom = $this->_sm->listTableDetails('autoinc_table_drop');
120
        self::assertTrue($tableFrom->getColumn('id')->getAutoincrement());
121
122
        $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_drop');
123
        $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...
124
125
        $c = new \Doctrine\DBAL\Schema\Comparator();
126
        $diff = $c->diffTable($tableFrom, $tableTo);
127
        self::assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
128
        self::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 126 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...
129
130
        $this->_sm->alterTable($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 126 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...
131
        $tableFinal = $this->_sm->listTableDetails('autoinc_table_drop');
132
        self::assertFalse($tableFinal->getColumn('id')->getAutoincrement());
133
    }
134
135
    /**
136
     * @group DBAL-75
137
     */
138
    public function testTableWithSchema()
139
    {
140
        $this->_conn->exec('CREATE SCHEMA nested');
141
142
        $nestedRelatedTable = new \Doctrine\DBAL\Schema\Table('nested.schemarelated');
143
        $column = $nestedRelatedTable->addColumn('id', 'integer');
144
        $column->setAutoincrement(true);
145
        $nestedRelatedTable->setPrimaryKey(array('id'));
146
147
        $nestedSchemaTable = new \Doctrine\DBAL\Schema\Table('nested.schematable');
148
        $column = $nestedSchemaTable->addColumn('id', 'integer');
149
        $column->setAutoincrement(true);
150
        $nestedSchemaTable->setPrimaryKey(array('id'));
151
        $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...
152
153
        $this->_sm->createTable($nestedRelatedTable);
154
        $this->_sm->createTable($nestedSchemaTable);
155
156
        $tables = $this->_sm->listTableNames();
157
        self::assertContains('nested.schematable', $tables, "The table should be detected with its non-public schema.");
158
159
        $nestedSchemaTable = $this->_sm->listTableDetails('nested.schematable');
160
        self::assertTrue($nestedSchemaTable->hasColumn('id'));
161
        self::assertEquals(array('id'), $nestedSchemaTable->getPrimaryKey()->getColumns());
162
163
        $relatedFks = $nestedSchemaTable->getForeignKeys();
164
        self::assertEquals(1, count($relatedFks));
165
        $relatedFk = array_pop($relatedFks);
166
        self::assertEquals("nested.schemarelated", $relatedFk->getForeignTableName());
167
    }
168
169
    /**
170
     * @group DBAL-91
171
     * @group DBAL-88
172
     */
173
    public function testReturnQuotedAssets()
174
    {
175
        $sql = 'create table dbal91_something ( id integer  CONSTRAINT id_something PRIMARY KEY NOT NULL  ,"table"   integer );';
176
        $this->_conn->exec($sql);
177
178
        $sql = 'ALTER TABLE dbal91_something ADD CONSTRAINT something_input FOREIGN KEY( "table" ) REFERENCES dbal91_something ON UPDATE CASCADE;';
179
        $this->_conn->exec($sql);
180
181
        $table = $this->_sm->listTableDetails('dbal91_something');
182
183
        self::assertEquals(
184
            array(
185
                "CREATE TABLE dbal91_something (id INT NOT NULL, \"table\" INT DEFAULT NULL, PRIMARY KEY(id))",
186
                "CREATE INDEX IDX_A9401304ECA7352B ON dbal91_something (\"table\")",
187
            ),
188
            $this->_conn->getDatabasePlatform()->getCreateTableSQL($table)
189
        );
190
    }
191
192
    /**
193
     * @group DBAL-204
194
     */
195
    public function testFilterSchemaExpression()
196
    {
197
        $testTable = new \Doctrine\DBAL\Schema\Table('dbal204_test_prefix');
198
        $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...
199
        $this->_sm->createTable($testTable);
200
        $testTable = new \Doctrine\DBAL\Schema\Table('dbal204_without_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
204
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_#');
205
        $names = $this->_sm->listTableNames();
206
        self::assertEquals(2, count($names));
207
208
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_test#');
209
        $names = $this->_sm->listTableNames();
210
        self::assertEquals(1, count($names));
211
    }
212
213
    public function testListForeignKeys()
214
    {
215
        if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
216
            $this->markTestSkipped('Does not support foreign key constraints.');
217
        }
218
219
        $fkOptions = array('SET NULL', 'SET DEFAULT', 'NO ACTION','CASCADE', 'RESTRICT');
220
        $foreignKeys = array();
221
        $fkTable = $this->getTestTable('test_create_fk1');
222
        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...
223
            $fkTable->addColumn("foreign_key_test$i", 'integer');
224
            $foreignKeys[] = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
225
                                 array("foreign_key_test$i"), 'test_create_fk2', array('id'), "foreign_key_test_$i"."_fk", array('onDelete' => $fkOptions[$i]));
226
        }
227
        $this->_sm->dropAndCreateTable($fkTable);
228
        $this->createTestTable('test_create_fk2');
229
230
        foreach($foreignKeys as $foreignKey) {
231
            $this->_sm->createForeignKey($foreignKey, 'test_create_fk1');
232
        }
233
        $fkeys = $this->_sm->listTableForeignKeys('test_create_fk1');
234
        self::assertEquals(count($foreignKeys), count($fkeys), "Table 'test_create_fk1' has to have " . count($foreignKeys) . " foreign keys.");
235
        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...
236
            self::assertEquals(array("foreign_key_test$i"), array_map('strtolower', $fkeys[$i]->getLocalColumns()));
237
            self::assertEquals(array('id'), array_map('strtolower', $fkeys[$i]->getForeignColumns()));
238
            self::assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
239
            if ($foreignKeys[$i]->getOption('onDelete') == 'NO ACTION') {
240
                self::assertFalse($fkeys[$i]->hasOption('onDelete'), 'Unexpected option: '. $fkeys[$i]->getOption('onDelete'));
241
            } else {
242
                self::assertEquals($foreignKeys[$i]->getOption('onDelete'), $fkeys[$i]->getOption('onDelete'));
243
            }
244
        }
245
    }
246
247
    /**
248
     * @group DBAL-511
249
     */
250
    public function testDefaultValueCharacterVarying()
251
    {
252
        $testTable = new \Doctrine\DBAL\Schema\Table('dbal511_default');
253
        $testTable->addColumn('id', 'integer');
254
        $testTable->addColumn('def', 'string', array('default' => 'foo'));
255
        $testTable->setPrimaryKey(array('id'));
256
257
        $this->_sm->createTable($testTable);
258
259
        $databaseTable = $this->_sm->listTableDetails($testTable->getName());
260
261
        self::assertEquals('foo', $databaseTable->getColumn('def')->getDefault());
262
    }
263
264
    /**
265
     * @group DDC-2843
266
     */
267 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...
268
    {
269
        $table = new \Doctrine\DBAL\Schema\Table('ddc2843_bools');
270
        $table->addColumn('id', 'integer');
271
        $table->addColumn('checked', 'boolean', array('default' => false));
272
273
        $this->_sm->createTable($table);
274
275
        $databaseTable = $this->_sm->listTableDetails($table->getName());
276
277
        $c = new \Doctrine\DBAL\Schema\Comparator();
278
        $diff = $c->diffTable($table, $databaseTable);
279
280
        self::assertFalse($diff);
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $c->diffTable($table, $databaseTable) on line 278 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...
281
    }
282
283 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...
284
    {
285
        $tableName = 'test_binary_table';
286
287
        $table = new \Doctrine\DBAL\Schema\Table($tableName);
288
        $table->addColumn('id', 'integer');
289
        $table->addColumn('column_varbinary', 'binary', array());
290
        $table->addColumn('column_binary', 'binary', array('fixed' => true));
291
        $table->setPrimaryKey(array('id'));
292
293
        $this->_sm->createTable($table);
294
295
        $table = $this->_sm->listTableDetails($tableName);
296
297
        self::assertInstanceOf('Doctrine\DBAL\Types\BlobType', $table->getColumn('column_varbinary')->getType());
298
        self::assertFalse($table->getColumn('column_varbinary')->getFixed());
299
300
        self::assertInstanceOf('Doctrine\DBAL\Types\BlobType', $table->getColumn('column_binary')->getType());
301
        self::assertFalse($table->getColumn('column_binary')->getFixed());
302
    }
303
304
    public function testListQuotedTable()
305
    {
306
        $offlineTable = new Schema\Table('user');
307
        $offlineTable->addColumn('id', 'integer');
308
        $offlineTable->addColumn('username', 'string', array('unique' => true));
309
        $offlineTable->addColumn('fk', 'integer');
310
        $offlineTable->setPrimaryKey(array('id'));
311
        $offlineTable->addForeignKeyConstraint($offlineTable, array('fk'), array('id'));
312
313
        $this->_sm->dropAndCreateTable($offlineTable);
314
315
        $onlineTable = $this->_sm->listTableDetails('"user"');
316
317
        $comparator = new Schema\Comparator();
318
319
        self::assertFalse($comparator->diffTable($offlineTable, $onlineTable));
0 ignored issues
show
Bug introduced by
It seems like $comparator->diffTable($...ineTable, $onlineTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() 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?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
320
    }
321
322
    public function testListTablesExcludesViews()
323
    {
324
        $this->createTestTable('list_tables_excludes_views');
325
326
        $name = "list_tables_excludes_views_test_view";
327
        $sql = "SELECT * from list_tables_excludes_views";
328
329
        $view = new Schema\View($name, $sql);
330
331
        $this->_sm->dropAndCreateView($view);
332
333
        $tables = $this->_sm->listTables();
334
335
        $foundTable = false;
336 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...
337
            self::assertInstanceOf('Doctrine\DBAL\Schema\Table', $table, 'No Table instance was found in tables array.');
338
            if (strtolower($table->getName()) == 'list_tables_excludes_views_test_view') {
339
                $foundTable = true;
340
            }
341
        }
342
343
        self::assertFalse($foundTable, 'View "list_tables_excludes_views_test_view" must not be found in table list');
344
    }
345
346
    /**
347
     * @group DBAL-1033
348
     */
349
    public function testPartialIndexes()
350
    {
351
        $offlineTable = new Schema\Table('person');
352
        $offlineTable->addColumn('id', 'integer');
353
        $offlineTable->addColumn('name', 'string');
354
        $offlineTable->addColumn('email', 'string');
355
        $offlineTable->addUniqueIndex(array('id', 'name'), 'simple_partial_index', array('where' => '(id IS NULL)'));
356
357
        $this->_sm->dropAndCreateTable($offlineTable);
358
359
        $onlineTable = $this->_sm->listTableDetails('person');
360
361
        $comparator = new Schema\Comparator();
362
363
        self::assertFalse($comparator->diffTable($offlineTable, $onlineTable));
0 ignored issues
show
Bug introduced by
It seems like $comparator->diffTable($...ineTable, $onlineTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() 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?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
364
        self::assertTrue($onlineTable->hasIndex('simple_partial_index'));
365
        self::assertTrue($onlineTable->getIndex('simple_partial_index')->hasOption('where'));
366
        self::assertSame('(id IS NULL)', $onlineTable->getIndex('simple_partial_index')->getOption('where'));
367
    }
368
369
    /**
370
     * @dataProvider jsonbColumnTypeProvider
371
     */
372
    public function testJsonbColumn(string $type): void
373
    {
374
        if (!$this->_sm->getDatabasePlatform() instanceof PostgreSQL94Platform) {
375
            $this->markTestSkipped("Requires PostgresSQL 9.4+");
376
            return;
377
        }
378
379
        $table = new Schema\Table('test_jsonb');
380
        $table->addColumn('foo', $type)->setPlatformOption('jsonb', true);
381
        $this->_sm->dropAndCreateTable($table);
382
383
        /** @var Schema\Column[] $columns */
384
        $columns = $this->_sm->listTableColumns('test_jsonb');
385
386
        self::assertSame(TYPE::JSON, $columns['foo']->getType()->getName());
387
        self::assertTrue(true, $columns['foo']->getPlatformOption('jsonb'));
388
    }
389
390
    public function jsonbColumnTypeProvider(): array
391
    {
392
        return [
393
            [Type::JSON],
394
            [Type::JSON_ARRAY],
395
        ];
396
    }
397
398
    /**
399
     * @group DBAL-2427
400
     */
401
    public function testListNegativeColumnDefaultValue()
402
    {
403
        $table = new Schema\Table('test_default_negative');
404
        $table->addColumn('col_smallint', 'smallint', array('default' => -1));
405
        $table->addColumn('col_integer', 'integer', array('default' => -1));
406
        $table->addColumn('col_bigint', 'bigint', array('default' => -1));
407
        $table->addColumn('col_float', 'float', array('default' => -1.1));
408
        $table->addColumn('col_decimal', 'decimal', array('default' => -1.1));
409
        $table->addColumn('col_string', 'string', array('default' => '(-1)'));
410
411
        $this->_sm->dropAndCreateTable($table);
412
413
        $columns = $this->_sm->listTableColumns('test_default_negative');
414
415
        self::assertEquals(-1, $columns['col_smallint']->getDefault());
416
        self::assertEquals(-1, $columns['col_integer']->getDefault());
417
        self::assertEquals(-1, $columns['col_bigint']->getDefault());
418
        self::assertEquals(-1.1, $columns['col_float']->getDefault());
419
        self::assertEquals(-1.1, $columns['col_decimal']->getDefault());
420
        self::assertEquals('(-1)', $columns['col_string']->getDefault());
421
    }
422
423 View Code Duplication
    public function testAlterTableAutoIncrementBigInt()
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...
424
    {
425
        $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_bitgint');
426
        $column = $tableFrom->addColumn('id', 'integer');
427
        $column->setAutoincrement(true);
428
        $this->_sm->createTable($tableFrom);
429
        $tableFrom = $this->_sm->listTableDetails('autoinc_table_bitgint');
430
        self::assertTrue($tableFrom->getColumn('id')->getAutoincrement());
431
432
        $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_bitgint');
433
        $column = $tableTo->addColumn('id', 'bigint');
434
        $column->setAutoincrement(true);
435
436
        $c = new \Doctrine\DBAL\Schema\Comparator();
437
        $diff = $c->diffTable($tableFrom, $tableTo);
438
        self::assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
439
        self::assertEquals(array("ALTER TABLE autoinc_table_bitgint ALTER id TYPE BIGINT"), $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 437 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...
440
441
        $this->_sm->alterTable($diff);
0 ignored issues
show
Security Bug introduced by
It seems like $diff defined by $c->diffTable($tableFrom, $tableTo) on line 437 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...
442
        $tableFinal = $this->_sm->listTableDetails('autoinc_table_bitgint');
443
        self::assertTrue($tableFinal->getColumn('id')->getAutoincrement());
444
    }
445
}
446
447
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...
448
{
449
450
    public function getName()
451
    {
452
        return "MyMoney";
453
    }
454
455
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
456
    {
457
        return 'MyMoney';
458
    }
459
460
}
461