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\Platforms\AbstractPlatform;
8
use Doctrine\DBAL\Types\Type;
9 10 11

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

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

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

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

        $this->expectException(ConnectionException::class);
35 36 37
        $this->_conn->commit();
    }

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

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

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

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

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

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

104 105 106 107 108 109 110
    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
111 112
        $this->expectException(ConnectionException::class);
        $this->_conn->setNestTransactionsWithSavepoints(true);
113 114 115 116 117 118 119 120
    }

    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
121 122
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
123 124 125 126 127 128 129 130 131 132

        $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
133 134
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
135 136 137 138 139 140 141 142 143 144

        $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
145 146
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
147 148 149 150 151 152 153 154 155 156

        $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
157 158
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage("Savepoints are not supported by this driver.");
159 160 161 162

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

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

169
            throw new \Exception;
170

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

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

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

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

207 208 209 210 211 212 213 214 215 216
    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) {
217
            self::assertEquals(0, $this->_conn->getTransactionNestingLevel());
218 219 220
        }
    }

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

        self::assertNull($res);
229
    }
230

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

237
        self::assertEquals(42, $res);
238 239
    }

240 241 242 243 244
    /**
     * Tests that the quote function accepts DBAL and PDO types.
     */
    public function testQuote()
    {
245
        self::assertEquals($this->_conn->quote("foo", Type::STRING), $this->_conn->quote("foo", \PDO::PARAM_STR));
246
    }
247

248
    public function testPingDoesTriggersConnect()
249
    {
250 251
        self::assertTrue($this->_conn->ping());
        self::assertTrue($this->_conn->isConnected());
252
    }
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

    /**
     * @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()
        );

272
        self::assertTrue($connection->connect());
273 274

        $connection->close();
275
    }
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

    /**
     * @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()
        );

295 296 297
        self::assertInstanceOf(AbstractPlatform::class, $connection->getDatabasePlatform());
        self::assertFalse($connection->isConnected());
        self::assertSame($params, $connection->getParams());
298 299 300

        $connection->close();
    }
301
}