ConnectionTest.php 10.5 KB
Newer Older
1 2 3 4 5
<?php

namespace Doctrine\Tests\DBAL\Functional;

use Doctrine\DBAL\ConnectionException;
6
use Doctrine\DBAL\DriverManager;
7
use Doctrine\DBAL\ParameterType;
8
use Doctrine\DBAL\Platforms\AbstractPlatform;
9
use Doctrine\DBAL\Types\Type;
10
use function in_array;
11 12 13

class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
14
    protected function setUp()
15 16 17 18 19
    {
        $this->resetSharedConn();
        parent::setUp();
    }

20
    protected function tearDown()
21 22 23 24 25
    {
        parent::tearDown();
        $this->resetSharedConn();
    }

26 27
    public function testGetWrappedConnection()
    {
28
        self::assertInstanceOf('Doctrine\DBAL\Driver\Connection', $this->_conn->getWrappedConnection());
29 30 31 32 33 34
    }

    public function testCommitWithRollbackOnlyThrowsException()
    {
        $this->_conn->beginTransaction();
        $this->_conn->setRollbackOnly();
Luís Cobucci's avatar
Luís Cobucci committed
35 36

        $this->expectException(ConnectionException::class);
37 38 39
        $this->_conn->commit();
    }

40 41 42 43
    public function testTransactionNestingBehavior()
    {
        try {
            $this->_conn->beginTransaction();
44
            self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
45

46 47
            try {
                $this->_conn->beginTransaction();
48
                self::assertEquals(2, $this->_conn->getTransactionNestingLevel());
49 50 51
                throw new \Exception;
                $this->_conn->commit(); // never reached
            } catch (\Exception $e) {
52
                $this->_conn->rollBack();
53
                self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
54
                //no rethrow
55
            }
56
            self::assertTrue($this->_conn->isRollbackOnly());
57

58 59
            $this->_conn->commit(); // should throw exception
            $this->fail('Transaction commit after failed nested transaction should fail.');
60
        } catch (ConnectionException $e) {
61
            self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
62
            $this->_conn->rollBack();
63
            self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
64 65
        }
    }
66 67 68

    public function testTransactionNestingBehaviorWithSavepoints()
    {
69 70 71 72 73 74 75
        if (!$this->_conn->getDatabasePlatform()->supportsSavepoints()) {
            $this->markTestSkipped('This test requires the platform to support savepoints.');
        }

        $this->_conn->setNestTransactionsWithSavepoints(true);
        try {
            $this->_conn->beginTransaction();
76
            self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
77

78 79
            try {
                $this->_conn->beginTransaction();
80
                self::assertEquals(2, $this->_conn->getTransactionNestingLevel());
81
                $this->_conn->beginTransaction();
82
                self::assertEquals(3, $this->_conn->getTransactionNestingLevel());
83
                $this->_conn->commit();
84
                self::assertEquals(2, $this->_conn->getTransactionNestingLevel());
85 86 87
                throw new \Exception;
                $this->_conn->commit(); // never reached
            } catch (\Exception $e) {
88
                $this->_conn->rollBack();
89
                self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
90 91
                //no rethrow
            }
92
            self::assertFalse($this->_conn->isRollbackOnly());
93 94 95
            try {
                $this->_conn->setNestTransactionsWithSavepoints(false);
                $this->fail('Should not be able to disable savepoints in usage for nested transactions inside an open transaction.');
96
            } catch (ConnectionException $e) {
97
                self::assertTrue($this->_conn->getNestTransactionsWithSavepoints());
98
            }
99 100 101
            $this->_conn->commit(); // should not throw exception
        } catch (ConnectionException $e) {
            $this->fail('Transaction commit after failed nested transaction should not fail when using savepoints.');
102
            $this->_conn->rollBack();
103 104 105
        }
    }

106 107 108 109 110 111 112
    public function testTransactionNestingBehaviorCantBeChangedInActiveTransaction()
    {
        if (!$this->_conn->getDatabasePlatform()->supportsSavepoints()) {
            $this->markTestSkipped('This test requires the platform to support savepoints.');
        }

        $this->_conn->beginTransaction();
Luís Cobucci's avatar
Luís Cobucci committed
113 114
        $this->expectException(ConnectionException::class);
        $this->_conn->setNestTransactionsWithSavepoints(true);
115 116 117 118 119 120 121 122
    }

    public function testSetNestedTransactionsThroughSavepointsNotSupportedThrowsException()
    {
        if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
        }

Luís Cobucci's avatar
Luís Cobucci committed
123 124
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
125 126 127 128 129 130 131 132 133 134

        $this->_conn->setNestTransactionsWithSavepoints(true);
    }

    public function testCreateSavepointsNotSupportedThrowsException()
    {
        if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
        }

Luís Cobucci's avatar
Luís Cobucci committed
135 136
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
137 138 139 140 141 142 143 144 145 146

        $this->_conn->createSavepoint('foo');
    }

    public function testReleaseSavepointsNotSupportedThrowsException()
    {
        if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
        }

Luís Cobucci's avatar
Luís Cobucci committed
147 148
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
149 150 151 152 153 154 155 156 157 158

        $this->_conn->releaseSavepoint('foo');
    }

    public function testRollbackSavepointsNotSupportedThrowsException()
    {
        if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
        }

Luís Cobucci's avatar
Luís Cobucci committed
159 160
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
161 162 163 164

        $this->_conn->rollbackSavepoint('foo');
    }

165
    public function testTransactionBehaviorWithRollback()
166 167 168
    {
        try {
            $this->_conn->beginTransaction();
169
            self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
170

171
            throw new \Exception;
172

173
            $this->_conn->commit(); // never reached
174
        } catch (\Exception $e) {
175
            self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
176
            $this->_conn->rollBack();
177
            self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
178
        }
179 180 181 182
    }

    public function testTransactionBehaviour()
    {
183 184
        try {
            $this->_conn->beginTransaction();
185
            self::assertEquals(1, $this->_conn->getTransactionNestingLevel());
186 187
            $this->_conn->commit();
        } catch (\Exception $e) {
188
            $this->_conn->rollBack();
189
            self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
190
        }
191

192
        self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
193 194 195 196
    }

    public function testTransactionalWithException()
    {
197 198
        try {
            $this->_conn->transactional(function($conn) {
till's avatar
till committed
199
                /* @var $conn \Doctrine\DBAL\Connection */
200
                $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL());
201 202
                throw new \RuntimeException("Ooops!");
            });
203
            $this->fail('Expected exception');
204
        } catch (\RuntimeException $expected) {
205
            self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
206
        }
207
    }
208

209 210 211 212 213 214 215 216 217 218
    public function testTransactionalWithThrowable()
    {
        try {
            $this->_conn->transactional(function($conn) {
                /* @var $conn \Doctrine\DBAL\Connection */
                $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL());
                throw new \Error("Ooops!");
            });
            $this->fail('Expected exception');
        } catch (\Error $expected) {
219
            self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
220 221 222
        }
    }

223 224
    public function testTransactional()
    {
Luís Cobucci's avatar
Luís Cobucci committed
225
        $res = $this->_conn->transactional(function($conn) {
till's avatar
till committed
226
            /* @var $conn \Doctrine\DBAL\Connection */
227
            $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL());
228
        });
Luís Cobucci's avatar
Luís Cobucci committed
229 230

        self::assertNull($res);
231
    }
232

233 234
    public function testTransactionalReturnValue()
    {
Luís Cobucci's avatar
Luís Cobucci committed
235
        $res = $this->_conn->transactional(function() {
236 237
            return 42;
        });
Luís Cobucci's avatar
Luís Cobucci committed
238

239
        self::assertEquals(42, $res);
240 241
    }

242 243 244 245 246
    /**
     * Tests that the quote function accepts DBAL and PDO types.
     */
    public function testQuote()
    {
247
        self::assertEquals(
248 249
            $this->_conn->quote('foo', Type::STRING),
            $this->_conn->quote('foo', ParameterType::STRING)
250
        );
251
    }
252

253
    public function testPingDoesTriggersConnect()
254
    {
255 256
        self::assertTrue($this->_conn->ping());
        self::assertTrue($this->_conn->isConnected());
257
    }
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276

    /**
     * @group DBAL-1025
     */
    public function testConnectWithoutExplicitDatabaseName()
    {
        if (in_array($this->_conn->getDatabasePlatform()->getName(), array('oracle', 'db2'), true)) {
            $this->markTestSkipped('Platform does not support connecting without database name.');
        }

        $params = $this->_conn->getParams();
        unset($params['dbname']);

        $connection = DriverManager::getConnection(
            $params,
            $this->_conn->getConfiguration(),
            $this->_conn->getEventManager()
        );

277
        self::assertTrue($connection->connect());
278 279

        $connection->close();
280
    }
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

    /**
     * @group DBAL-990
     */
    public function testDeterminesDatabasePlatformWhenConnectingToNonExistentDatabase()
    {
        if (in_array($this->_conn->getDatabasePlatform()->getName(), ['oracle', 'db2'], true)) {
            $this->markTestSkipped('Platform does not support connecting without database name.');
        }

        $params = $this->_conn->getParams();
        $params['dbname'] = 'foo_bar';

        $connection = DriverManager::getConnection(
            $params,
            $this->_conn->getConfiguration(),
            $this->_conn->getEventManager()
        );

300 301 302
        self::assertInstanceOf(AbstractPlatform::class, $connection->getDatabasePlatform());
        self::assertFalse($connection->isConnected());
        self::assertSame($params, $connection->getParams());
303 304 305

        $connection->close();
    }
306
}