Failed Conditions
Pull Request — master (#3074)
by Sergei
15:08
created

testLastInsertIdAfterDeletePrepare()   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
        parent::tearDown();
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
        $this->assertLastInsertIdInTransaction($this->createPrepareInsertExecutor());
226
    }
227
228
    public function testLastInsertIdInTransactionQuery()
229
    {
230
        $this->assertLastInsertIdInTransaction($this->createQueryInsertExecutor());
231
    }
232
233
    public function assertLastInsertIdInTransaction(callable $insertExecutor)
234
    {
235
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
236
            $this->markTestSkipped('Test only works on platforms with identity columns.');
237
        }
238
239
        $this->testConnection->beginTransaction();
240
        $insertExecutor();
241
        $this->assertSame('1', $this->testConnection->lastInsertId());
242
        $this->testConnection->rollBack();
243
    }
244
245
    public function testLastInsertIdAfterTransactionCommitExec()
246
    {
247
        $this->assertLastInsertIdAfterTransactionCommit($this->createExecInsertExecutor());
248
    }
249
250
    public function testLastInsertIdAfterTransactionCommitPrepare()
251
    {
252
        $this->assertLastInsertIdAfterTransactionCommit($this->createPrepareInsertExecutor());
253
    }
254
255
    public function testLastInsertIdAfterTransactionCommitQuery()
256
    {
257
        $this->assertLastInsertIdAfterTransactionCommit($this->createQueryInsertExecutor());
258
    }
259
260
    private function assertLastInsertIdAfterTransactionCommit(callable $insertExecutor)
261
    {
262
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
263
            $this->markTestSkipped('Test only works on platforms with identity columns.');
264
        }
265
266
        $this->testConnection->beginTransaction();
267
        $insertExecutor();
268
        $this->testConnection->commit();
269
270
        $this->assertSame('1', $this->testConnection->lastInsertId());
271
    }
272
273
    public function testLastInsertIdAfterTransactionRollbackExec()
274
    {
275
        $this->assertLastInsertIdAfterTransactionRollback($this->createExecInsertExecutor());
276
    }
277
278
    public function testLastInsertIdAfterTransactionRollbackPrepare()
279
    {
280
        $this->assertLastInsertIdAfterTransactionRollback($this->createPrepareInsertExecutor());
281
    }
282
283
    public function testLastInsertIdAfterTransactionRollbackQuery()
284
    {
285
        $this->assertLastInsertIdAfterTransactionRollback($this->createQueryInsertExecutor());
286
    }
287
288
    private function assertLastInsertIdAfterTransactionRollback(callable $insertExecutor)
289
    {
290
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
291
            $this->markTestSkipped('Test only works on platforms with identity columns.');
292
        }
293
294
        $this->testConnection->beginTransaction();
295
        $insertExecutor();
296
        $this->testConnection->rollBack();
297
298
        $this->assertSame('1', $this->testConnection->lastInsertId());
299
    }
300
301
    public function testLastInsertIdInsertAfterTransactionRollbackExec()
302
    {
303
        $this->assertLastInsertIdInsertAfterTransactionRollback($this->createExecInsertExecutor());
304
    }
305
306
    public function testLastInsertIdInsertAfterTransactionRollbackPrepare()
307
    {
308
        $this->assertLastInsertIdInsertAfterTransactionRollback($this->createPrepareInsertExecutor());
309
    }
310
311
    public function testLastInsertIdInsertAfterTransactionRollbackQuery()
312
    {
313
        $this->assertLastInsertIdInsertAfterTransactionRollback($this->createQueryInsertExecutor());
314
    }
315
316
    private function assertLastInsertIdInsertAfterTransactionRollback(callable $insertExecutor)
317
    {
318
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
319
            $this->markTestSkipped('Test only works on platforms with identity columns.');
320
        }
321
322
        $this->testConnection->beginTransaction();
323
        $insertExecutor();
324
        $this->testConnection->rollBack();
325
        $insertExecutor();
326
327
        $expected = $this->testConnection->getDatabasePlatform()->getName() === 'sqlite'
328
            // SQLite has a different transaction concept, that reuses rolled back IDs
329
            // See: http://sqlite.1065341.n5.nabble.com/Autoincrement-with-rollback-td79154.html
330
            ? '1'
331
            : '2';
332
333
        $this->assertSame($expected, $this->testConnection->lastInsertId());
334
    }
335
336
    public function testLastInsertIdReusePreparedStatementPrepare()
337
    {
338
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
339
            $this->markTestSkipped('Test only works on platforms with identity columns.');
340
        }
341
342
        $statement = $this->testConnection->prepare('INSERT INTO last_insert_id_table (foo) VALUES (1)');
343
344
        $statement->execute();
345
        $statement->execute();
346
347
        $this->assertSame('2', $this->testConnection->lastInsertId());
348
    }
349
350
    public function testLastInsertIdReusePreparedStatementQuery()
351
    {
352
        if (! $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
353
            $this->markTestSkipped('Test only works on platforms with identity columns.');
354
        }
355
356
        $statement = $this->testConnection->query('INSERT INTO last_insert_id_table (foo) VALUES (1)');
357
358
        $statement->execute();
359
360
        $this->assertSame('2', $this->testConnection->lastInsertId());
361
    }
362
363
    public function testLastInsertIdConnectionScope()
364
    {
365
        $platform = $this->_conn->getDatabasePlatform();
366
367
        if ($platform->getName() === 'sqlite') {
368
            $this->markTestSkipped('Test does not work on sqlite as connections do not share memory.');
369
        }
370
371
        if (! $platform->supportsIdentityColumns()) {
372
            $this->markTestSkipped('Test only works on platforms with identity columns.');
373
        }
374
375
        $connection1 = TestUtil::getConnection();
376
        $connection2 = TestUtil::getConnection();
377
378
        $connection1->insert('last_insert_id_table', array('foo' => 1));
379
380
        $this->assertNotSame('1', $connection2->lastInsertId());
381
382
        $connection2->insert('last_insert_id_table', array('foo' => 2));
383
384
        $this->assertSame('1', $connection1->lastInsertId());
385
        $this->assertSame('2', $connection2->lastInsertId());
386
387
        $connection1->close();
388
        $connection2->close();
389
    }
390
391
    public function testLastInsertIdSequence()
392
    {
393
        if (! $this->_conn->getDatabasePlatform()->supportsSequences()) {
394
            $this->markTestSkipped('Test only works on platforms with sequences.');
395
        }
396
397
        $sequence = new Sequence('last_insert_id_seq');
398
399
        $this->_conn->getSchemaManager()->createSequence($sequence);
400
401
        $nextSequenceValueSql = $this->_conn->getDatabasePlatform()->getSequenceNextValSQL('last_insert_id_seq');
402
        $nextSequenceValue = $this->_conn->fetchColumn($nextSequenceValueSql);
403
        $lastInsertId = $this->_conn->lastInsertId('last_insert_id_seq');
404
405
        $this->assertEquals($lastInsertId, $nextSequenceValue);
406
    }
407
408
    public function testLastInsertIdSequenceEmulatedIdentityColumnExec()
409
    {
410
        $this->assertLastInsertIdSequenceEmulatedIdentityColumn($this->createExecInsertExecutor());
411
    }
412
413
    public function testLastInsertIdSequenceEmulatedIdentityColumnPrepare()
414
    {
415
        $this->assertLastInsertIdSequenceEmulatedIdentityColumn($this->createPrepareInsertExecutor());
416
    }
417
418
    public function testLastInsertIdSequenceEmulatedIdentityColumnQuery()
419
    {
420
        $this->assertLastInsertIdSequenceEmulatedIdentityColumn($this->createQueryInsertExecutor());
421
    }
422
423
    private function assertLastInsertIdSequenceEmulatedIdentityColumn(callable $insertExecutor)
424
    {
425
        $platform = $this->_conn->getDatabasePlatform();
426
427
        if ($platform->supportsIdentityColumns() || ! $platform->usesSequenceEmulatedIdentityColumns()) {
428
            $this->markTestSkipped('Test only works on platforms that emulates identity columns through sequences.');
429
        }
430
431
        $sequenceName = $platform->getIdentitySequenceName('last_insert_id_table', 'id');
432
433
        $this->assertSame('0', $this->_conn->lastInsertId($sequenceName));
434
435
        $insertExecutor();
436
437
        $this->assertSame('1', $this->_conn->lastInsertId($sequenceName));
438
    }
439
440
    private function createExecInsertExecutor()
441
    {
442
        return function () {
443
            $this->testConnection->getWrappedConnection()->exec('INSERT INTO last_insert_id_table (foo) VALUES (1)');
444
        };
445
    }
446
447
    private function createPrepareInsertExecutor()
448
    {
449
        return function () {
450
            $stmt = $this->testConnection->getWrappedConnection()->prepare(
451
                'INSERT INTO last_insert_id_table (foo) VALUES (?)'
452
            );
453
454
            $stmt->execute(array(1));
455
        };
456
    }
457
458
    private function createQueryInsertExecutor()
459
    {
460
        return function () {
461
            $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

461
            $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...
462
        };
463
    }
464
}
465