ExceptionTest.php 13.5 KB
Newer Older
1 2 3
<?php
namespace Doctrine\Tests\DBAL\Functional;

4
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
Luís Cobucci's avatar
Luís Cobucci committed
5
use Doctrine\DBAL\Exception;
6
use Doctrine\DBAL\Schema\Table;
7 8 9 10 11 12 13 14
use function array_merge;
use function chmod;
use function defined;
use function file_exists;
use function sprintf;
use function sys_get_temp_dir;
use function touch;
use function unlink;
15 16 17

class ExceptionTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
18
    protected function setUp()
19 20 21
    {
        parent::setUp();

22
        if ( !($this->_conn->getDriver() instanceof ExceptionConverterDriver)) {
23 24 25 26
            $this->markTestSkipped('Driver does not support special exception handling.');
        }
    }

27
    public function testPrimaryConstraintViolationException()
28 29 30 31 32
    {
        $table = new \Doctrine\DBAL\Schema\Table("duplicatekey_table");
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

33
        $this->_conn->getSchemaManager()->createTable($table);
34 35 36

        $this->_conn->insert("duplicatekey_table", array('id' => 1));

Luís Cobucci's avatar
Luís Cobucci committed
37
        $this->expectException(Exception\UniqueConstraintViolationException::class);
38 39
        $this->_conn->insert("duplicatekey_table", array('id' => 1));
    }
40

41
    public function testTableNotFoundException()
42 43 44
    {
        $sql = "SELECT * FROM unknown_table";

Luís Cobucci's avatar
Luís Cobucci committed
45
        $this->expectException(Exception\TableNotFoundException::class);
46 47
        $this->_conn->executeQuery($sql);
    }
48

49
    public function testTableExistsException()
50
    {
51
        $schemaManager = $this->_conn->getSchemaManager();
52
        $table = new \Doctrine\DBAL\Schema\Table("alreadyexist_table");
53 54 55
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

Luís Cobucci's avatar
Luís Cobucci committed
56
        $this->expectException(Exception\TableExistsException::class);
57 58
        $schemaManager->createTable($table);
        $schemaManager->createTable($table);
59
    }
60

Possum's avatar
Possum committed
61
    public function testForeignKeyConstraintViolationExceptionOnInsert()
62 63 64 65 66
    {
        if ( ! $this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
        }

67
        $this->setUpForeignKeyConstraintViolationExceptionTest();
68

69 70 71 72 73 74 75 76
        try {
            $this->_conn->insert("constraint_error_table", array('id' => 1));
            $this->_conn->insert("owning_table", array('id' => 1, 'constraint_id' => 1));
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

            throw $exception;
        }
77

Luís Cobucci's avatar
Luís Cobucci committed
78
        $this->expectException(Exception\ForeignKeyConstraintViolationException::class);
79 80 81

        try {
            $this->_conn->insert('owning_table', array('id' => 2, 'constraint_id' => 2));
Luís Cobucci's avatar
Luís Cobucci committed
82
        } catch (Exception\ForeignKeyConstraintViolationException $exception) {
83 84
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

85 86 87 88
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

89 90
            throw $exception;
        }
91

92 93 94
        $this->tearDownForeignKeyConstraintViolationExceptionTest();
    }

Possum's avatar
Possum committed
95
    public function testForeignKeyConstraintViolationExceptionOnUpdate()
96 97 98
    {
        if ( ! $this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
99 100
        }

101 102
        $this->setUpForeignKeyConstraintViolationExceptionTest();

103 104 105 106 107 108 109 110
        try {
            $this->_conn->insert("constraint_error_table", array('id' => 1));
            $this->_conn->insert("owning_table", array('id' => 1, 'constraint_id' => 1));
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

            throw $exception;
        }
111

Luís Cobucci's avatar
Luís Cobucci committed
112
        $this->expectException(Exception\ForeignKeyConstraintViolationException::class);
113 114 115

        try {
            $this->_conn->update('constraint_error_table', array('id' => 2), array('id' => 1));
Luís Cobucci's avatar
Luís Cobucci committed
116
        } catch (Exception\ForeignKeyConstraintViolationException $exception) {
117 118
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

119 120 121 122
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

123 124
            throw $exception;
        }
125 126 127 128

        $this->tearDownForeignKeyConstraintViolationExceptionTest();
    }

Possum's avatar
Possum committed
129
    public function testForeignKeyConstraintViolationExceptionOnDelete()
130 131 132 133 134 135 136
    {
        if ( ! $this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
        }

        $this->setUpForeignKeyConstraintViolationExceptionTest();

137 138 139 140 141 142 143 144
        try {
            $this->_conn->insert("constraint_error_table", array('id' => 1));
            $this->_conn->insert("owning_table", array('id' => 1, 'constraint_id' => 1));
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

            throw $exception;
        }
145

Luís Cobucci's avatar
Luís Cobucci committed
146
        $this->expectException(Exception\ForeignKeyConstraintViolationException::class);
147 148 149

        try {
            $this->_conn->delete('constraint_error_table', array('id' => 1));
Luís Cobucci's avatar
Luís Cobucci committed
150
        } catch (Exception\ForeignKeyConstraintViolationException $exception) {
151 152
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

153 154 155 156
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

157 158
            throw $exception;
        }
159 160 161 162

        $this->tearDownForeignKeyConstraintViolationExceptionTest();
    }

Possum's avatar
Possum committed
163
    public function testForeignKeyConstraintViolationExceptionOnTruncate()
164 165 166
    {
        $platform = $this->_conn->getDatabasePlatform();

167
        if (!$platform->supportsForeignKeyConstraints()) {
168 169 170 171 172
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
        }

        $this->setUpForeignKeyConstraintViolationExceptionTest();

173 174 175 176 177 178 179 180
        try {
            $this->_conn->insert("constraint_error_table", array('id' => 1));
            $this->_conn->insert("owning_table", array('id' => 1, 'constraint_id' => 1));
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

            throw $exception;
        }
181

Luís Cobucci's avatar
Luís Cobucci committed
182
        $this->expectException(Exception\ForeignKeyConstraintViolationException::class);
183 184 185

        try {
            $this->_conn->executeUpdate($platform->getTruncateTableSQL('constraint_error_table'));
Luís Cobucci's avatar
Luís Cobucci committed
186
        } catch (Exception\ForeignKeyConstraintViolationException $exception) {
187 188
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

189 190 191 192
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

193 194
            throw $exception;
        }
195 196

        $this->tearDownForeignKeyConstraintViolationExceptionTest();
197
    }
198

199
    public function testNotNullConstraintViolationException()
200 201 202 203 204 205 206 207
    {
        $schema = new \Doctrine\DBAL\Schema\Schema();

        $table = $schema->createTable("notnull_table");
        $table->addColumn('id', 'integer', array());
        $table->addColumn('value', 'integer', array('notnull' => true));
        $table->setPrimaryKey(array('id'));

jeroendedauw's avatar
jeroendedauw committed
208
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
209
            $this->_conn->exec($sql);
210 211
        }

Luís Cobucci's avatar
Luís Cobucci committed
212
        $this->expectException(Exception\NotNullConstraintViolationException::class);
213
        $this->_conn->insert("notnull_table", array('id' => 1, 'value' => null));
214
    }
215

216
    public function testInvalidFieldNameException()
217 218 219
    {
        $schema = new \Doctrine\DBAL\Schema\Schema();

220 221
        $table = $schema->createTable("bad_fieldname_table");
        $table->addColumn('id', 'integer', array());
222

jeroendedauw's avatar
jeroendedauw committed
223
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
224
            $this->_conn->exec($sql);
225 226
        }

Luís Cobucci's avatar
Luís Cobucci committed
227
        $this->expectException(Exception\InvalidFieldNameException::class);
228 229 230 231 232 233 234 235 236 237 238 239 240
        $this->_conn->insert("bad_fieldname_table", array('name' => 5));
    }

    public function testNonUniqueFieldNameException()
    {
        $schema = new \Doctrine\DBAL\Schema\Schema();

        $table = $schema->createTable("ambiguous_list_table");
        $table->addColumn('id', 'integer');

        $table2 = $schema->createTable("ambiguous_list_table_2");
        $table2->addColumn('id', 'integer');

jeroendedauw's avatar
jeroendedauw committed
241
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
242
            $this->_conn->exec($sql);
243 244 245
        }

        $sql = 'SELECT id FROM ambiguous_list_table, ambiguous_list_table_2';
Luís Cobucci's avatar
Luís Cobucci committed
246
        $this->expectException(Exception\NonUniqueFieldNameException::class);
247
        $this->_conn->executeQuery($sql);
248 249
    }

250
    public function testUniqueConstraintViolationException()
251 252 253 254 255 256 257
    {
        $schema = new \Doctrine\DBAL\Schema\Schema();

        $table = $schema->createTable("unique_field_table");
        $table->addColumn('id', 'integer');
        $table->addUniqueIndex(array('id'));

jeroendedauw's avatar
jeroendedauw committed
258
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
259
            $this->_conn->exec($sql);
260
        }
261

262
        $this->_conn->insert("unique_field_table", array('id' => 5));
Luís Cobucci's avatar
Luís Cobucci committed
263
        $this->expectException(Exception\UniqueConstraintViolationException::class);
264
        $this->_conn->insert("unique_field_table", array('id' => 5));
265 266
    }

267 268 269 270 271 272
    public function testSyntaxErrorException()
    {
        $table = new \Doctrine\DBAL\Schema\Table("syntax_error_table");
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

273
        $this->_conn->getSchemaManager()->createTable($table);
274 275

        $sql = 'SELECT id FRO syntax_error_table';
Luís Cobucci's avatar
Luís Cobucci committed
276
        $this->expectException(Exception\SyntaxErrorException::class);
277 278 279
        $this->_conn->executeQuery($sql);
    }

280 281 282
    /**
     * @dataProvider getSqLiteOpenConnection
     */
283
    public function testConnectionExceptionSqLite($mode, $exceptionClass)
284 285 286 287 288
    {
        if ($this->_conn->getDatabasePlatform()->getName() != 'sqlite') {
            $this->markTestSkipped("Only fails this way on sqlite");
        }

289
        $filename = sprintf('%s/%s', sys_get_temp_dir(), 'doctrine_failed_connection_'.$mode.'.db');
290 291

        if (file_exists($filename)) {
292
            chmod($filename, 0200); // make the file writable again, so it can be removed on Windows
293 294
            unlink($filename);
        }
295 296 297 298 299

        touch($filename);
        chmod($filename, $mode);

        $params = array(
300 301 302
            'driver' => 'pdo_sqlite',
            'path'   => $filename,
        );
303 304 305 306 307 308
        $conn = \Doctrine\DBAL\DriverManager::getConnection($params);

        $schema = new \Doctrine\DBAL\Schema\Schema();
        $table = $schema->createTable("no_connection");
        $table->addColumn('id', 'integer');

Luís Cobucci's avatar
Luís Cobucci committed
309
        $this->expectException($exceptionClass);
jeroendedauw's avatar
jeroendedauw committed
310
        foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
311
            $conn->exec($sql);
312
        }
313 314
    }

315 316 317
    public function getSqLiteOpenConnection()
    {
        return array(
318
            // mode 0 is considered read-only on Windows
Luís Cobucci's avatar
Luís Cobucci committed
319 320
            array(0000, defined('PHP_WINDOWS_VERSION_BUILD') ? Exception\ReadOnlyException::class : Exception\ConnectionException::class),
            array(0444, Exception\ReadOnlyException::class),
321
        );
322 323
    }

324 325 326
    /**
     * @dataProvider getConnectionParams
     */
327
    public function testConnectionException($params)
328 329 330 331 332
    {
        if ($this->_conn->getDatabasePlatform()->getName() == 'sqlite') {
            $this->markTestSkipped("Only skipped if platform is not sqlite");
        }

333 334 335 336
        if ($this->_conn->getDatabasePlatform()->getName() == 'drizzle') {
            $this->markTestSkipped("Drizzle does not always support authentication");
        }

337
        if ($this->_conn->getDatabasePlatform()->getName() == 'postgresql' && isset($params['password'])) {
Benjamin Eberlei's avatar
Benjamin Eberlei committed
338 339 340
            $this->markTestSkipped("Does not work on Travis");
        }

341 342 343 344 345 346 347 348 349
        $defaultParams = $this->_conn->getParams();
        $params = array_merge($defaultParams, $params);

        $conn = \Doctrine\DBAL\DriverManager::getConnection($params);

        $schema = new \Doctrine\DBAL\Schema\Schema();
        $table = $schema->createTable("no_connection");
        $table->addColumn('id', 'integer');

Luís Cobucci's avatar
Luís Cobucci committed
350
        $this->expectException(Exception\ConnectionException::class);
351

jeroendedauw's avatar
jeroendedauw committed
352
        foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
353
            $conn->exec($sql);
354
        }
355 356 357 358
    }

    public function getConnectionParams()
    {
359
        return array(
360 361 362
            array(array('user' => 'not_existing')),
            array(array('password' => 'really_not')),
            array(array('host' => 'localnope')),
363
        );
364
    }
365

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
    private function setUpForeignKeyConstraintViolationExceptionTest()
    {
        $schemaManager = $this->_conn->getSchemaManager();

        $table = new Table("constraint_error_table");
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

        $owningTable = new Table("owning_table");
        $owningTable->addColumn('id', 'integer', array());
        $owningTable->addColumn('constraint_id', 'integer', array());
        $owningTable->setPrimaryKey(array('id'));
        $owningTable->addForeignKeyConstraint($table, array('constraint_id'), array('id'));

        $schemaManager->createTable($table);
        $schemaManager->createTable($owningTable);
    }

    private function tearDownForeignKeyConstraintViolationExceptionTest()
    {
        $schemaManager = $this->_conn->getSchemaManager();

        $schemaManager->dropTable('owning_table');
        $schemaManager->dropTable('constraint_error_table');
    }
}