Failed Conditions
Pull Request — master (#2765)
by Sergei
60:53
created

LastInsertIdTest::testLastInsertIdPrepare()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional;
4
5
use Doctrine\DBAL\Schema\Sequence;
6
use Doctrine\DBAL\Schema\Table;
7
use Doctrine\Tests\TestUtil;
8
9
class LastInsertIdTest extends \Doctrine\Tests\DbalFunctionalTestCase
10
{
11
    /**
12
     * @var \Doctrine\DBAL\Connection
13
     */
14
    private $testConnection;
15
16
    protected function setUp()
17
    {
18
        parent::setUp();
19
20
        $this->testConnection = TestUtil::getConnection();
21
22
        $this->createTable('last_insert_id_table');
23
    }
24
25
    protected function tearDown()
26
    {
27
        $this->testConnection->close();
28
        if ($this->_conn->getDatabasePlatform()->getName() !== 'sqlite') {
29
            $this->_conn->getSchemaManager()->dropTable('last_insert_id_table');
30
        }
31
32
        return parent::tearDown();
0 ignored issues
show
Bug introduced by
Are you sure the usage of parent::tearDown() targeting Doctrine\Tests\DbalFunctionalTestCase::tearDown() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
33
    }
34
35
    private function createTable($tableName)
36
    {
37
        $table = new Table($tableName);
38
        $table->addColumn('id', 'integer', array('autoincrement' => true));
39
        $table->addColumn('foo', 'integer', array('notnull' => false));
40
        $table->setPrimaryKey(array('id'));
41
42
        $connection = $this->_conn->getDatabasePlatform()->getName() === 'sqlite'
43
            ? $this->testConnection
44
            : $this->_conn;
45
46
        $connection->getSchemaManager()->createTable($table);
47
    }
48
49
    public function testLastInsertIdNoInsert()
50
    {
51
        $this->assertSame('0', $this->testConnection->lastInsertId());
52
    }
53
54
    public function testLastInsertIdExec()
55
    {
56
        $this->assertLastInsertId($this->createExecInsertExecutor());
57
    }
58
59
    public function testLastInsertIdPrepare()
60
    {
61
        $this->assertLastInsertId($this->createPrepareInsertExecutor());
62
    }
63
64
    public function testLastInsertIdQuery()
65
    {
66
        $this->assertLastInsertId($this->createQueryInsertExecutor());
67
    }
68
69
    private function assertLastInsertId(callable $insertExecutor)
70
    {
71
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
72
            $this->markTestSkipped('Test only works on platforms with identity columns.');
73
        }
74
75
        $insertExecutor();
76
77
        $this->assertSame('1', $this->testConnection->lastInsertId());
78
    }
79
80
    public function testLastInsertIdAfterUpdateExec()
81
    {
82
        $this->assertLastInsertIdAfterUpdate($this->createExecInsertExecutor());
83
    }
84
85
    public function testLastInsertIdAfterUpdatePrepare()
86
    {
87
        $this->assertLastInsertIdAfterUpdate($this->createPrepareInsertExecutor());
88
    }
89
90
    public function testLastInsertIdAfterUpdateQuery()
91
    {
92
        $this->assertLastInsertIdAfterUpdate($this->createQueryInsertExecutor());
93
    }
94
95
    private function assertLastInsertIdAfterUpdate(callable $insertExecutor)
96
    {
97
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
98
            $this->markTestSkipped('Test only works on platforms with identity columns.');
99
        }
100
101
        $insertExecutor();
102
        $this->testConnection->update('last_insert_id_table', array('foo' => 2), array('id' => 1));
103
104
        $this->assertSame('1', $this->testConnection->lastInsertId());
105
    }
106
107
    public function testLastInsertIdAfterDeleteExec()
108
    {
109
        $this->assertLastInsertIdAfterDelete($this->createExecInsertExecutor());
110
    }
111
112
    public function testLastInsertIdAfterDeletePrepare()
113
    {
114
        $this->assertLastInsertIdAfterDelete($this->createPrepareInsertExecutor());
115
    }
116
117
    public function testLastInsertIdAfterDeleteQuery()
118
    {
119
        $this->assertLastInsertIdAfterDelete($this->createQueryInsertExecutor());
120
    }
121
122
    private function assertLastInsertIdAfterDelete(callable $insertExecutor)
123
    {
124
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
125
            $this->markTestSkipped('Test only works on platforms with identity columns.');
126
        }
127
128
        $insertExecutor();
129
        $this->testConnection->exec('DELETE FROM last_insert_id_table');
130
131
        $this->assertSame('1', $this->testConnection->lastInsertId());
132
    }
133
134
    public function testLastInsertIdAfterTruncateExec()
135
    {
136
        $this->assertLastInsertIdAfterTruncate($this->createExecInsertExecutor());
137
    }
138
139
    public function testLastInsertIdAfterTruncatePrepare()
140
    {
141
        $this->assertLastInsertIdAfterTruncate($this->createPrepareInsertExecutor());
142
    }
143
144
    public function testLastInsertIdAfterTruncateQuery()
145
    {
146
        $this->assertLastInsertIdAfterTruncate($this->createQueryInsertExecutor());
147
    }
148
149
    private function assertLastInsertIdAfterTruncate(callable $insertExecutor)
150
    {
151
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
152
            $this->markTestSkipped('Test only works on platforms with identity columns.');
153
        }
154
155
        $insertExecutor();
156
        $truncateTableSql = $this->testConnection->getDatabasePlatform()->getTruncateTableSQL('last_insert_id_table');
157
        $this->testConnection->exec($truncateTableSql);
158
159
        $this->assertSame('1', $this->testConnection->lastInsertId());
160
    }
161
162
    public function testLastInsertIdAfterDropTableExec()
163
    {
164
        $this->assertLastInsertIdAfterDropTable($this->createExecInsertExecutor());
165
    }
166
167
    public function testLastInsertIdAfterDropTablePrepare()
168
    {
169
        $this->assertLastInsertIdAfterDropTable($this->createPrepareInsertExecutor());
170
    }
171
172
    public function testLastInsertIdAfterDropTableQuery()
173
    {
174
        $this->assertLastInsertIdAfterDropTable($this->createQueryInsertExecutor());
175
    }
176
177
    private function assertLastInsertIdAfterDropTable(callable $insertExecutor)
178
    {
179
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
180
            $this->markTestSkipped('Test only works on platforms with identity columns.');
181
        }
182
183
        $this->createTable('last_insert_id_table_tmp');
184
185
        $insertExecutor();
186
        $this->testConnection->getSchemaManager()->dropTable('last_insert_id_table_tmp');
187
188
        $this->assertSame('1', $this->testConnection->lastInsertId());
189
    }
190
191
    public function testLastInsertIdAfterSelectExec()
192
    {
193
        $this->assertLastInsertIdAfterSelect($this->createExecInsertExecutor());
194
    }
195
196
    public function testLastInsertIdAfterSelectPrepare()
197
    {
198
        $this->assertLastInsertIdAfterSelect($this->createPrepareInsertExecutor());
199
    }
200
201
    public function testLastInsertIdAfterSelectQuery()
202
    {
203
        $this->assertLastInsertIdAfterSelect($this->createQueryInsertExecutor());
204
    }
205
206
    private function assertLastInsertIdAfterSelect(callable $insertExecutor)
207
    {
208
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
209
            $this->markTestSkipped('Test only works on platforms with identity columns.');
210
        }
211
212
        $insertExecutor();
213
        $this->testConnection->executeQuery('SELECT 1 FROM last_insert_id_table');
214
215
        $this->assertSame('1', $this->testConnection->lastInsertId());
216
    }
217
218
    public function testLastInsertIdInTransactionExec()
219
    {
220
        $this->assertLastInsertIdInTransaction($this->createExecInsertExecutor());
221
    }
222
223
    public function testLastInsertIdInTransactionPrepare()
224
    {
225
        self::markTestIncomplete('Temporarily disabled as causing a dead lock on PDO drivers');
226
        $this->assertLastInsertIdInTransaction($this->createPrepareInsertExecutor());
227
    }
228
229
    public function testLastInsertIdInTransactionQuery()
230
    {
231
        $this->assertLastInsertIdInTransaction($this->createQueryInsertExecutor());
232
    }
233
234
    public function assertLastInsertIdInTransaction(callable $insertExecutor)
235
    {
236
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
237
            $this->markTestSkipped('Test only works on platforms with identity columns.');
238
        }
239
240
        $this->testConnection->beginTransaction();
241
        $insertExecutor();
242
        $this->assertSame('1', $this->testConnection->lastInsertId());
243
        $this->testConnection->rollBack();
244
    }
245
246
    public function testLastInsertIdAfterTransactionCommitExec()
247
    {
248
        $this->assertLastInsertIdAfterTransactionCommit($this->createExecInsertExecutor());
249
    }
250
251
    public function testLastInsertIdAfterTransactionCommitPrepare()
252
    {
253
        $this->assertLastInsertIdAfterTransactionCommit($this->createPrepareInsertExecutor());
254
    }
255
256
    public function testLastInsertIdAfterTransactionCommitQuery()
257
    {
258
        $this->assertLastInsertIdAfterTransactionCommit($this->createQueryInsertExecutor());
259
    }
260
261
    private function assertLastInsertIdAfterTransactionCommit(callable $insertExecutor)
262
    {
263
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
264
            $this->markTestSkipped('Test only works on platforms with identity columns.');
265
        }
266
267
        $this->testConnection->beginTransaction();
268
        $insertExecutor();
269
        $this->testConnection->commit();
270
271
        $this->assertSame('1', $this->testConnection->lastInsertId());
272
    }
273
274
    public function testLastInsertIdAfterTransactionRollbackExec()
275
    {
276
        $this->assertLastInsertIdAfterTransactionRollback($this->createExecInsertExecutor());
277
    }
278
279
    public function testLastInsertIdAfterTransactionRollbackPrepare()
280
    {
281
        $this->assertLastInsertIdAfterTransactionRollback($this->createPrepareInsertExecutor());
282
    }
283
284
    public function testLastInsertIdAfterTransactionRollbackQuery()
285
    {
286
        $this->assertLastInsertIdAfterTransactionRollback($this->createQueryInsertExecutor());
287
    }
288
289
    private function assertLastInsertIdAfterTransactionRollback(callable $insertExecutor)
290
    {
291
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
292
            $this->markTestSkipped('Test only works on platforms with identity columns.');
293
        }
294
295
        $this->testConnection->beginTransaction();
296
        $insertExecutor();
297
        $this->testConnection->rollBack();
298
299
        $this->assertSame('1', $this->testConnection->lastInsertId());
300
    }
301
302
    public function testLastInsertIdInsertAfterTransactionRollbackExec()
303
    {
304
        $this->assertLastInsertIdInsertAfterTransactionRollback($this->createExecInsertExecutor());
305
    }
306
307
    public function testLastInsertIdInsertAfterTransactionRollbackPrepare()
308
    {
309
        $this->assertLastInsertIdInsertAfterTransactionRollback($this->createPrepareInsertExecutor());
310
    }
311
312
    public function testLastInsertIdInsertAfterTransactionRollbackQuery()
313
    {
314
        $this->assertLastInsertIdInsertAfterTransactionRollback($this->createQueryInsertExecutor());
315
    }
316
317
    private function assertLastInsertIdInsertAfterTransactionRollback(callable $insertExecutor)
318
    {
319
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
320
            $this->markTestSkipped('Test only works on platforms with identity columns.');
321
        }
322
323
        $this->testConnection->beginTransaction();
324
        $insertExecutor();
325
        $this->testConnection->rollBack();
326
        $insertExecutor();
327
328
        $expected = $this->testConnection->getDatabasePlatform()->getName() === 'sqlite'
329
            // SQLite has a different transaction concept, that reuses rolled back IDs
330
            // See: http://sqlite.1065341.n5.nabble.com/Autoincrement-with-rollback-td79154.html
331
            ? '1'
332
            : '2';
333
334
        $this->assertSame($expected, $this->testConnection->lastInsertId());
335
    }
336
337
    public function testLastInsertIdReusePreparedStatementPrepare()
338
    {
339
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
340
            $this->markTestSkipped('Test only works on platforms with identity columns.');
341
        }
342
343
        $statement = $this->testConnection->prepare('INSERT INTO last_insert_id_table (foo) VALUES (1)');
344
345
        $statement->execute();
346
        $statement->execute();
347
348
        $this->assertSame('2', $this->testConnection->lastInsertId());
349
    }
350
351
    public function testLastInsertIdReusePreparedStatementQuery()
352
    {
353
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
354
            $this->markTestSkipped('Test only works on platforms with identity columns.');
355
        }
356
357
        $statement = $this->testConnection->query('INSERT INTO last_insert_id_table (foo) VALUES (1)');
358
359
        $statement->execute();
360
361
        $this->assertSame('2', $this->testConnection->lastInsertId());
362
    }
363
364
    public function testLastInsertIdConnectionScope()
365
    {
366
        $platform = $this->_conn->getDatabasePlatform();
367
368
        if ($platform->getName() === 'sqlite') {
369
            $this->markTestSkipped('Test does not work on sqlite as connections do not share memory.');
370
        }
371
372
        if (! $platform->supportsIdentityColumns()) {
373
            $this->markTestSkipped('Test only works on platforms with identity columns.');
374
        }
375
376
        $connection1 = TestUtil::getConnection();
377
        $connection2 = TestUtil::getConnection();
378
379
        $connection1->insert('last_insert_id_table', array('foo' => 1));
380
381
        $this->assertNotSame('1', $connection2->lastInsertId());
382
383
        $connection2->insert('last_insert_id_table', array('foo' => 2));
384
385
        $this->assertSame('1', $connection1->lastInsertId());
386
        $this->assertSame('2', $connection2->lastInsertId());
387
388
        $connection1->close();
389
        $connection2->close();
390
    }
391
392
    public function testLastInsertIdSequence()
393
    {
394
        if (! $this->_conn->getDatabasePlatform()->supportsSequences()) {
395
            $this->markTestSkipped('Test only works on platforms with sequences.');
396
        }
397
398
        $sequence = new Sequence('last_insert_id_seq');
399
400
        $this->_conn->getSchemaManager()->createSequence($sequence);
401
402
        $nextSequenceValueSql = $this->_conn->getDatabasePlatform()->getSequenceNextValSQL('last_insert_id_seq');
403
        $nextSequenceValue = $this->_conn->fetchColumn($nextSequenceValueSql);
404
        $lastInsertId = $this->_conn->lastInsertId('last_insert_id_seq');
405
406
        $this->assertEquals($lastInsertId, $nextSequenceValue);
407
    }
408
409
    public function testLastInsertIdSequenceEmulatedIdentityColumnExec()
410
    {
411
        $this->assertLastInsertIdSequenceEmulatedIdentityColumn($this->createExecInsertExecutor());
412
    }
413
414
    public function testLastInsertIdSequenceEmulatedIdentityColumnPrepare()
415
    {
416
        $this->assertLastInsertIdSequenceEmulatedIdentityColumn($this->createPrepareInsertExecutor());
417
    }
418
419
    public function testLastInsertIdSequenceEmulatedIdentityColumnQuery()
420
    {
421
        $this->assertLastInsertIdSequenceEmulatedIdentityColumn($this->createQueryInsertExecutor());
422
    }
423
424
    private function assertLastInsertIdSequenceEmulatedIdentityColumn(callable $insertExecutor)
425
    {
426
        $platform = $this->_conn->getDatabasePlatform();
427
428
        if ($platform->supportsIdentityColumns() || ! $platform->usesSequenceEmulatedIdentityColumns()) {
429
            $this->markTestSkipped('Test only works on platforms that emulates identity columns through sequences.');
430
        }
431
432
        $sequenceName = $platform->getIdentitySequenceName('last_insert_id_table', 'id');
433
434
        $this->assertSame('0', $this->_conn->lastInsertId($sequenceName));
435
436
        $insertExecutor();
437
438
        $this->assertSame('1', $this->_conn->lastInsertId($sequenceName));
439
    }
440
441
    private function createExecInsertExecutor()
442
    {
443
        return function () {
444
            $this->testConnection->getWrappedConnection()->exec('INSERT INTO last_insert_id_table (foo) VALUES (1)');
445
        };
446
    }
447
448
    private function createPrepareInsertExecutor()
449
    {
450
        return function () {
451
            $stmt = $this->testConnection->getWrappedConnection()->prepare(
452
                'INSERT INTO last_insert_id_table (foo) VALUES (?)'
453
            );
454
455
            $stmt->execute(array(1));
456
        };
457
    }
458
459
    private function createQueryInsertExecutor()
460
    {
461
        return function () {
462
            $this->testConnection->getWrappedConnection()->query('INSERT INTO last_insert_id_table (foo) VALUES (1)');
0 ignored issues
show
Unused Code introduced by
The call to Doctrine\DBAL\Driver\Connection::query() has too many arguments starting with 'INSERT INTO last_insert...table (foo) VALUES (1)'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

462
            $this->testConnection->getWrappedConnection()->/** @scrutinizer ignore-call */ query('INSERT INTO last_insert_id_table (foo) VALUES (1)');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
463
        };
464
    }
465
}
466