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

4
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
5
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
6
use Doctrine\DBAL\Schema\Table;
7 8 9

class ExceptionTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
10
    protected function setUp()
11 12 13
    {
        parent::setUp();

14
        if ( !($this->_conn->getDriver() instanceof ExceptionConverterDriver)) {
15 16 17 18
            $this->markTestSkipped('Driver does not support special exception handling.');
        }
    }

19
    public function testPrimaryConstraintViolationException()
20 21 22 23 24
    {
        $table = new \Doctrine\DBAL\Schema\Table("duplicatekey_table");
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

25
        $this->_conn->getSchemaManager()->createTable($table);
26 27 28

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

29 30
        $this->setExpectedException(
            '\Doctrine\DBAL\Exception\UniqueConstraintViolationException');
31 32
        $this->_conn->insert("duplicatekey_table", array('id' => 1));
    }
33

34
    public function testTableNotFoundException()
35 36 37
    {
        $sql = "SELECT * FROM unknown_table";

38
        $this->setExpectedException('\Doctrine\DBAL\Exception\TableNotFoundException');
39 40
        $this->_conn->executeQuery($sql);
    }
41

42
    public function testTableExistsException()
43
    {
44
        $schemaManager = $this->_conn->getSchemaManager();
45
        $table = new \Doctrine\DBAL\Schema\Table("alreadyexist_table");
46 47 48
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

49
        $this->setExpectedException('\Doctrine\DBAL\Exception\TableExistsException');
50 51
        $schemaManager->createTable($table);
        $schemaManager->createTable($table);
52
    }
53

Possum's avatar
Possum committed
54
    public function testForeignKeyConstraintViolationExceptionOnInsert()
55 56 57 58 59
    {
        if ( ! $this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
        }

60
        $this->setUpForeignKeyConstraintViolationExceptionTest();
61

62 63 64 65 66 67 68 69
        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;
        }
70

71
        $this->setExpectedException('\Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException');
72 73 74 75 76 77

        try {
            $this->_conn->insert('owning_table', array('id' => 2, 'constraint_id' => 2));
        } catch (ForeignKeyConstraintViolationException $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

78 79 80 81
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

82 83
            throw $exception;
        }
84

85 86 87
        $this->tearDownForeignKeyConstraintViolationExceptionTest();
    }

Possum's avatar
Possum committed
88
    public function testForeignKeyConstraintViolationExceptionOnUpdate()
89 90 91
    {
        if ( ! $this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
92 93
        }

94 95
        $this->setUpForeignKeyConstraintViolationExceptionTest();

96 97 98 99 100 101 102 103
        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;
        }
104 105

        $this->setExpectedException('\Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException');
106 107 108 109 110 111

        try {
            $this->_conn->update('constraint_error_table', array('id' => 2), array('id' => 1));
        } catch (ForeignKeyConstraintViolationException $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

112 113 114 115
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

116 117
            throw $exception;
        }
118 119 120 121

        $this->tearDownForeignKeyConstraintViolationExceptionTest();
    }

Possum's avatar
Possum committed
122
    public function testForeignKeyConstraintViolationExceptionOnDelete()
123 124 125 126 127 128 129
    {
        if ( ! $this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
        }

        $this->setUpForeignKeyConstraintViolationExceptionTest();

130 131 132 133 134 135 136 137
        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;
        }
138

139
        $this->setExpectedException('\Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException');
140 141 142 143 144 145

        try {
            $this->_conn->delete('constraint_error_table', array('id' => 1));
        } catch (ForeignKeyConstraintViolationException $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

146 147 148 149
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

150 151
            throw $exception;
        }
152 153 154 155

        $this->tearDownForeignKeyConstraintViolationExceptionTest();
    }

Possum's avatar
Possum committed
156
    public function testForeignKeyConstraintViolationExceptionOnTruncate()
157 158 159
    {
        $platform = $this->_conn->getDatabasePlatform();

160
        if (!$platform->supportsForeignKeyConstraints()) {
161 162 163 164 165
            $this->markTestSkipped("Only fails on platforms with foreign key constraints.");
        }

        $this->setUpForeignKeyConstraintViolationExceptionTest();

166 167 168 169 170 171 172 173
        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;
        }
174 175

        $this->setExpectedException('\Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException');
176 177 178 179 180 181

        try {
            $this->_conn->executeUpdate($platform->getTruncateTableSQL('constraint_error_table'));
        } catch (ForeignKeyConstraintViolationException $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

182 183 184 185
            throw $exception;
        } catch (\Exception $exception) {
            $this->tearDownForeignKeyConstraintViolationExceptionTest();

186 187
            throw $exception;
        }
188 189

        $this->tearDownForeignKeyConstraintViolationExceptionTest();
190
    }
191

192
    public function testNotNullConstraintViolationException()
193 194 195 196 197 198 199 200
    {
        $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
201
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
202
            $this->_conn->exec($sql);
203 204
        }

205
        $this->setExpectedException('\Doctrine\DBAL\Exception\NotNullConstraintViolationException');
206
        $this->_conn->insert("notnull_table", array('id' => 1, 'value' => null));
207
    }
208

209
    public function testInvalidFieldNameException()
210 211 212
    {
        $schema = new \Doctrine\DBAL\Schema\Schema();

213 214
        $table = $schema->createTable("bad_fieldname_table");
        $table->addColumn('id', 'integer', array());
215

jeroendedauw's avatar
jeroendedauw committed
216
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
217
            $this->_conn->exec($sql);
218 219
        }

220
        $this->setExpectedException('\Doctrine\DBAL\Exception\InvalidFieldNameException');
221 222 223 224 225 226 227 228 229 230 231 232 233
        $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
234
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
235
            $this->_conn->exec($sql);
236 237 238
        }

        $sql = 'SELECT id FROM ambiguous_list_table, ambiguous_list_table_2';
239
        $this->setExpectedException('\Doctrine\DBAL\Exception\NonUniqueFieldNameException');
240
        $this->_conn->executeQuery($sql);
241 242
    }

243
    public function testUniqueConstraintViolationException()
244 245 246 247 248 249 250
    {
        $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
251
        foreach ($schema->toSql($this->_conn->getDatabasePlatform()) as $sql) {
252
            $this->_conn->exec($sql);
253
        }
254

255
        $this->_conn->insert("unique_field_table", array('id' => 5));
256
        $this->setExpectedException('\Doctrine\DBAL\Exception\UniqueConstraintViolationException');
257
        $this->_conn->insert("unique_field_table", array('id' => 5));
258 259
    }

260 261 262 263 264 265
    public function testSyntaxErrorException()
    {
        $table = new \Doctrine\DBAL\Schema\Table("syntax_error_table");
        $table->addColumn('id', 'integer', array());
        $table->setPrimaryKey(array('id'));

266
        $this->_conn->getSchemaManager()->createTable($table);
267 268

        $sql = 'SELECT id FRO syntax_error_table';
269
        $this->setExpectedException('\Doctrine\DBAL\Exception\SyntaxErrorException');
270 271 272
        $this->_conn->executeQuery($sql);
    }

273 274 275
    /**
     * @dataProvider getSqLiteOpenConnection
     */
276
    public function testConnectionExceptionSqLite($mode, $exceptionClass)
277 278 279 280 281
    {
        if ($this->_conn->getDatabasePlatform()->getName() != 'sqlite') {
            $this->markTestSkipped("Only fails this way on sqlite");
        }

282
        $filename = sprintf('%s/%s', sys_get_temp_dir(), 'doctrine_failed_connection_'.$mode.'.db');
283 284

        if (file_exists($filename)) {
285
            chmod($filename, 0200); // make the file writable again, so it can be removed on Windows
286 287
            unlink($filename);
        }
288 289 290 291 292

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

        $params = array(
293 294 295
            'driver' => 'pdo_sqlite',
            'path'   => $filename,
        );
296 297 298 299 300 301
        $conn = \Doctrine\DBAL\DriverManager::getConnection($params);

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

302
        $this->setExpectedException($exceptionClass);
jeroendedauw's avatar
jeroendedauw committed
303
        foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
304
            $conn->exec($sql);
305
        }
306 307
    }

308 309 310
    public function getSqLiteOpenConnection()
    {
        return array(
311 312
            // mode 0 is considered read-only on Windows
            array(0000, defined('PHP_WINDOWS_VERSION_BUILD') ? '\Doctrine\DBAL\Exception\ReadOnlyException' : '\Doctrine\DBAL\Exception\ConnectionException'),
313
            array(0444, '\Doctrine\DBAL\Exception\ReadOnlyException'),
314
        );
315 316
    }

317 318 319
    /**
     * @dataProvider getConnectionParams
     */
320
    public function testConnectionException($params)
321 322 323 324 325
    {
        if ($this->_conn->getDatabasePlatform()->getName() == 'sqlite') {
            $this->markTestSkipped("Only skipped if platform is not sqlite");
        }

326 327 328 329
        if ($this->_conn->getDatabasePlatform()->getName() == 'drizzle') {
            $this->markTestSkipped("Drizzle does not always support authentication");
        }

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

334 335 336 337 338 339 340 341 342
        $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');

343
        $this->setExpectedException('Doctrine\DBAL\Exception\ConnectionException');
344

jeroendedauw's avatar
jeroendedauw committed
345
        foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
346
            $conn->exec($sql);
347
        }
348 349 350 351
    }

    public function getConnectionParams()
    {
352
        return array(
353 354 355
            array(array('user' => 'not_existing')),
            array(array('password' => 'really_not')),
            array(array('host' => 'localnope')),
356
        );
357
    }
358

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
    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');
    }
}