Passed
Push — master ( 38a76a...6fb7a4 )
by Marco
04:33
created

jsonbColumnTypeProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
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
        $this->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
        $this->assertInternalType('array', $names);
42
        $this->assertTrue(count($names) > 0);
43
        $this->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
        $this->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
        $this->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
        $this->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
        $this->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
        $this->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
        $this->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
        $this->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
        $this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
128
        $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 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
        $this->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
        $this->assertContains('nested.schematable', $tables, "The table should be detected with its non-public schema.");
158
159
        $nestedSchemaTable = $this->_sm->listTableDetails('nested.schematable');
160
        $this->assertTrue($nestedSchemaTable->hasColumn('id'));
161
        $this->assertEquals(array('id'), $nestedSchemaTable->getPrimaryKey()->getColumns());
162
163
        $relatedFks = $nestedSchemaTable->getForeignKeys();
164
        $this->assertEquals(1, count($relatedFks));
165
        $relatedFk = array_pop($relatedFks);
166
        $this->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
        $this->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
        $this->assertEquals(2, count($names));
207
208
        $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_test#');
209
        $names = $this->_sm->listTableNames();
210
        $this->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
        $this->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
            $this->assertEquals(array("foreign_key_test$i"), array_map('strtolower', $fkeys[$i]->getLocalColumns()));
237
            $this->assertEquals(array('id'), array_map('strtolower', $fkeys[$i]->getForeignColumns()));
238
            $this->assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
239
            if ($foreignKeys[$i]->getOption('onDelete') == 'NO ACTION') {
240
                $this->assertFalse($fkeys[$i]->hasOption('onDelete'), 'Unexpected option: '. $fkeys[$i]->getOption('onDelete'));
241
            } else {
242
                $this->assertEquals($foreignKeys[$i]->getOption('onDelete'), $fkeys[$i]->getOption('onDelete'));
243
            }
244
        }
245
    }
246
247
    /**
248
     * @group DBAL-511
249
     */
250 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...
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
        $this->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
        $this->assertFalse($diff);
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
        $this->assertInstanceOf('Doctrine\DBAL\Types\BlobType', $table->getColumn('column_varbinary')->getType());
298
        $this->assertFalse($table->getColumn('column_varbinary')->getFixed());
299
300
        $this->assertInstanceOf('Doctrine\DBAL\Types\BlobType', $table->getColumn('column_binary')->getType());
301
        $this->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
        $this->assertFalse($comparator->diffTable($offlineTable, $onlineTable));
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
            $this->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
        $this->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
        $this->assertFalse($comparator->diffTable($offlineTable, $onlineTable));
364
        $this->assertTrue($onlineTable->hasIndex('simple_partial_index'));
365
        $this->assertTrue($onlineTable->getIndex('simple_partial_index')->hasOption('where'));
366
        $this->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
        $this->assertSame(TYPE::JSON, $columns['foo']->getType()->getName());
387
        $this->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
        $this->assertEquals(-1, $columns['col_smallint']->getDefault());
416
        $this->assertEquals(-1, $columns['col_integer']->getDefault());
417
        $this->assertEquals(-1, $columns['col_bigint']->getDefault());
418
        $this->assertEquals(-1.1, $columns['col_float']->getDefault());
419
        $this->assertEquals(-1.1, $columns['col_decimal']->getDefault());
420
        $this->assertEquals('(-1)', $columns['col_string']->getDefault());
421
    }
422
}
423
424
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...
425
{
426
427
    public function getName()
428
    {
429
        return "MyMoney";
430
    }
431
432
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
433
    {
434
        return 'MyMoney';
435
    }
436
437
}
438