Cancelled
Pull Request — master (#3679)
by
unknown
03:10
created

ConnectionTest::testConnectWithoutExplicitDatabaseName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 18
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\ConnectionException;
7
use Doctrine\DBAL\Driver\Connection as DriverConnection;
8
use Doctrine\DBAL\DriverManager;
9
use Doctrine\DBAL\ParameterType;
10
use Doctrine\DBAL\Platforms\AbstractPlatform;
11
use Doctrine\DBAL\Types\Types;
12
use Doctrine\Tests\DbalFunctionalTestCase;
13
use Error;
14
use Exception;
15
use PDO;
16
use RuntimeException;
17
use Throwable;
18
use function in_array;
19
20
class ConnectionTest extends DbalFunctionalTestCase
21
{
22
    protected function setUp() : void
23
    {
24
        $this->resetSharedConn();
25
        parent::setUp();
26
    }
27
28
    protected function tearDown() : void
29
    {
30
        parent::tearDown();
31
        $this->resetSharedConn();
32
    }
33
34
    public function testGetWrappedConnection() : void
35
    {
36
        self::assertInstanceOf(DriverConnection::class, $this->connection->getWrappedConnection());
37
    }
38
39
    public function testCommitWithRollbackOnlyThrowsException() : void
40
    {
41
        $this->connection->beginTransaction();
42
        $this->connection->setRollbackOnly();
43
44
        $this->expectException(ConnectionException::class);
45
        $this->connection->commit();
46
    }
47
48
    public function testTransactionNestingBehavior() : void
49
    {
50
        try {
51
            $this->connection->beginTransaction();
52
            self::assertEquals(1, $this->connection->getTransactionNestingLevel());
53
54
            try {
55
                $this->connection->beginTransaction();
56
                self::assertEquals(2, $this->connection->getTransactionNestingLevel());
57
                throw new Exception();
58
                $this->connection->commit(); // never reached
59
            } catch (Throwable $e) {
60
                $this->connection->rollBack();
61
                self::assertEquals(1, $this->connection->getTransactionNestingLevel());
62
                //no rethrow
63
            }
64
            self::assertTrue($this->connection->isRollbackOnly());
65
66
            $this->connection->commit(); // should throw exception
67
            $this->fail('Transaction commit after failed nested transaction should fail.');
68
        } catch (ConnectionException $e) {
69
            self::assertEquals(1, $this->connection->getTransactionNestingLevel());
70
            $this->connection->rollBack();
71
            self::assertEquals(0, $this->connection->getTransactionNestingLevel());
72
        }
73
    }
74
75
    public function testTransactionNestingLevelIsResetOnReconnect() : void
76
    {
77
        $this->connection->executeQuery('CREATE TABLE if not exists test_nesting(test int not null)');
78
        $this->connection->executeQuery('truncate table test_nesting')
79
80
        $this->connection->beginTransaction();
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_VARIABLE on line 80 at column 8
Loading history...
81
        $this->connection->beginTransaction();
82
        $this->connection->close(); // connection is lost
83
84
        $this->connection->beginTransaction(); // should connect, reset nesting level and increase it once
85
        $this->connection->executeQuery('insert into test_nesting values (33)');
86
        $this->connection->rollback();
87
        
88
        self::assertEquals(0, $this->connection->fetchOne('select count(*) from test_nesting' ));
89
90
    }
91
92
    public function testTransactionNestingBehaviorWithSavepoints() : void
93
    {
94
        if (! $this->connection->getDatabasePlatform()->supportsSavepoints()) {
95
            $this->markTestSkipped('This test requires the platform to support savepoints.');
96
        }
97
98
        $this->connection->setNestTransactionsWithSavepoints(true);
99
        try {
100
            $this->connection->beginTransaction();
101
            self::assertEquals(1, $this->connection->getTransactionNestingLevel());
102
103
            try {
104
                $this->connection->beginTransaction();
105
                self::assertEquals(2, $this->connection->getTransactionNestingLevel());
106
                $this->connection->beginTransaction();
107
                self::assertEquals(3, $this->connection->getTransactionNestingLevel());
108
                self::assertTrue($this->connection->commit());
109
                self::assertEquals(2, $this->connection->getTransactionNestingLevel());
110
                throw new Exception();
111
                $this->connection->commit(); // never reached
112
            } catch (Throwable $e) {
113
                $this->connection->rollBack();
114
                self::assertEquals(1, $this->connection->getTransactionNestingLevel());
115
                //no rethrow
116
            }
117
            self::assertFalse($this->connection->isRollbackOnly());
118
            try {
119
                $this->connection->setNestTransactionsWithSavepoints(false);
120
                $this->fail('Should not be able to disable savepoints in usage for nested transactions inside an open transaction.');
121
            } catch (ConnectionException $e) {
122
                self::assertTrue($this->connection->getNestTransactionsWithSavepoints());
123
            }
124
            $this->connection->commit(); // should not throw exception
125
        } catch (ConnectionException $e) {
126
            $this->fail('Transaction commit after failed nested transaction should not fail when using savepoints.');
127
            $this->connection->rollBack();
128
        }
129
    }
130
131
    public function testTransactionNestingBehaviorCantBeChangedInActiveTransaction() : void
132
    {
133
        if (! $this->connection->getDatabasePlatform()->supportsSavepoints()) {
134
            $this->markTestSkipped('This test requires the platform to support savepoints.');
135
        }
136
137
        $this->connection->beginTransaction();
138
        $this->expectException(ConnectionException::class);
139
        $this->connection->setNestTransactionsWithSavepoints(true);
140
    }
141
142
    public function testSetNestedTransactionsThroughSavepointsNotSupportedThrowsException() : void
143
    {
144
        if ($this->connection->getDatabasePlatform()->supportsSavepoints()) {
145
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
146
        }
147
148
        $this->expectException(ConnectionException::class);
149
        $this->expectExceptionMessage('Savepoints are not supported by this driver.');
150
151
        $this->connection->setNestTransactionsWithSavepoints(true);
152
    }
153
154
    public function testCreateSavepointsNotSupportedThrowsException() : void
155
    {
156
        if ($this->connection->getDatabasePlatform()->supportsSavepoints()) {
157
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
158
        }
159
160
        $this->expectException(ConnectionException::class);
161
        $this->expectExceptionMessage('Savepoints are not supported by this driver.');
162
163
        $this->connection->createSavepoint('foo');
164
    }
165
166
    public function testReleaseSavepointsNotSupportedThrowsException() : void
167
    {
168
        if ($this->connection->getDatabasePlatform()->supportsSavepoints()) {
169
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
170
        }
171
172
        $this->expectException(ConnectionException::class);
173
        $this->expectExceptionMessage('Savepoints are not supported by this driver.');
174
175
        $this->connection->releaseSavepoint('foo');
176
    }
177
178
    public function testRollbackSavepointsNotSupportedThrowsException() : void
179
    {
180
        if ($this->connection->getDatabasePlatform()->supportsSavepoints()) {
181
            $this->markTestSkipped('This test requires the platform not to support savepoints.');
182
        }
183
184
        $this->expectException(ConnectionException::class);
185
        $this->expectExceptionMessage('Savepoints are not supported by this driver.');
186
187
        $this->connection->rollbackSavepoint('foo');
188
    }
189
190
    public function testTransactionBehaviorWithRollback() : void
191
    {
192
        try {
193
            $this->connection->beginTransaction();
194
            self::assertEquals(1, $this->connection->getTransactionNestingLevel());
195
196
            throw new Exception();
197
198
            $this->connection->commit(); // never reached
199
        } catch (Throwable $e) {
200
            self::assertEquals(1, $this->connection->getTransactionNestingLevel());
201
            $this->connection->rollBack();
202
            self::assertEquals(0, $this->connection->getTransactionNestingLevel());
203
        }
204
    }
205
206
    public function testTransactionBehaviour() : void
207
    {
208
        try {
209
            $this->connection->beginTransaction();
210
            self::assertEquals(1, $this->connection->getTransactionNestingLevel());
211
            $this->connection->commit();
212
        } catch (Throwable $e) {
213
            $this->connection->rollBack();
214
            self::assertEquals(0, $this->connection->getTransactionNestingLevel());
215
        }
216
217
        self::assertEquals(0, $this->connection->getTransactionNestingLevel());
218
    }
219
220
    public function testTransactionalWithException() : void
221
    {
222
        try {
223
            $this->connection->transactional(static function ($conn) : void {
224
                /** @var Connection $conn */
225
                $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL());
226
                throw new RuntimeException('Ooops!');
227
            });
228
            $this->fail('Expected exception');
229
        } catch (RuntimeException $expected) {
230
            self::assertEquals(0, $this->connection->getTransactionNestingLevel());
231
        }
232
    }
233
234
    public function testTransactionalWithThrowable() : void
235
    {
236
        try {
237
            $this->connection->transactional(static function ($conn) : void {
238
                /** @var Connection $conn */
239
                $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL());
240
                throw new Error('Ooops!');
241
            });
242
            $this->fail('Expected exception');
243
        } catch (Error $expected) {
244
            self::assertEquals(0, $this->connection->getTransactionNestingLevel());
245
        }
246
    }
247
248
    public function testTransactional() : void
249
    {
250
        $res = $this->connection->transactional(static function ($conn) : void {
251
            /** @var Connection $conn */
252
            $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL());
253
        });
254
255
        self::assertNull($res);
256
    }
257
258
    public function testTransactionalReturnValue() : void
259
    {
260
        $res = $this->connection->transactional(static function () {
261
            return 42;
262
        });
263
264
        self::assertEquals(42, $res);
265
    }
266
267
    /**
268
     * Tests that the quote function accepts DBAL and PDO types.
269
     */
270
    public function testQuote() : void
271
    {
272
        self::assertEquals(
273
            $this->connection->quote('foo', Types::STRING),
274
            $this->connection->quote('foo', ParameterType::STRING)
275
        );
276
    }
277
278
    public function testPingDoesTriggersConnect() : void
279
    {
280
        self::assertTrue($this->connection->ping());
281
        self::assertTrue($this->connection->isConnected());
282
    }
283
284
    /**
285
     * @group DBAL-1025
286
     */
287
    public function testConnectWithoutExplicitDatabaseName() : void
288
    {
289
        if (in_array($this->connection->getDatabasePlatform()->getName(), ['oracle', 'db2'], true)) {
290
            $this->markTestSkipped('Platform does not support connecting without database name.');
291
        }
292
293
        $params = $this->connection->getParams();
294
        unset($params['dbname']);
295
296
        $connection = DriverManager::getConnection(
297
            $params,
298
            $this->connection->getConfiguration(),
299
            $this->connection->getEventManager()
300
        );
301
302
        self::assertTrue($connection->connect());
303
304
        $connection->close();
305
    }
306
307
    /**
308
     * @group DBAL-990
309
     */
310
    public function testDeterminesDatabasePlatformWhenConnectingToNonExistentDatabase() : void
311
    {
312
        if (in_array($this->connection->getDatabasePlatform()->getName(), ['oracle', 'db2'], true)) {
313
            $this->markTestSkipped('Platform does not support connecting without database name.');
314
        }
315
316
        $params = $this->connection->getParams();
317
318
        $params['dbname'] = 'foo_bar';
319
320
        $connection = DriverManager::getConnection(
321
            $params,
322
            $this->connection->getConfiguration(),
323
            $this->connection->getEventManager()
324
        );
325
326
        self::assertInstanceOf(AbstractPlatform::class, $connection->getDatabasePlatform());
327
        self::assertFalse($connection->isConnected());
328
        self::assertSame($params, $connection->getParams());
329
330
        $connection->close();
331
    }
332
333
    /**
334
     * @requires extension pdo_sqlite
335
     */
336
    public function testUserProvidedPDOConnection() : void
337
    {
338
        self::assertTrue(
339
            DriverManager::getConnection([
340
                'pdo' => new PDO('sqlite::memory:'),
341
            ])->ping()
342
        );
343
    }
344
}
345