Passed
Push — type-registry ( f9a1df...0931f1 )
by Michael
24:09
created

WriteTest::lastInsertId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 10
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional;
4
5
use DateTime;
6
use Doctrine\DBAL\Driver\DriverException;
7
use Doctrine\DBAL\ParameterType;
8
use Doctrine\DBAL\Schema\Sequence;
9
use Doctrine\DBAL\Schema\Table;
10
use Doctrine\DBAL\Types\Type;
11
use Doctrine\Tests\DbalFunctionalTestCase;
12
use Throwable;
13
use function array_filter;
14
use function strtolower;
15
16
class WriteTest extends DbalFunctionalTestCase
17
{
18
    protected function setUp() : void
19
    {
20
        parent::setUp();
21
22
        try {
23
            $table = new Table('write_table');
24
            $table->addColumn('id', 'integer', ['autoincrement' => true]);
25
            $table->addColumn('test_int', 'integer');
26
            $table->addColumn('test_string', 'string', ['notnull' => false]);
27
            $table->setPrimaryKey(['id']);
28
29
            $this->connection->getSchemaManager()->createTable($table);
30
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
31
        }
32
        $this->connection->executeUpdate('DELETE FROM write_table');
33
    }
34
35
    /**
36
     * @group DBAL-80
37
     */
38
    public function testExecuteUpdateFirstTypeIsNull()
39
    {
40
        $sql = 'INSERT INTO write_table (test_string, test_int) VALUES (?, ?)';
41
        $this->connection->executeUpdate($sql, ['text', 1111], [null, ParameterType::INTEGER]);
42
43
        $sql = 'SELECT * FROM write_table WHERE test_string = ? AND test_int = ?';
44
        self::assertTrue((bool) $this->connection->fetchColumn($sql, ['text', 1111]));
45
    }
46
47
    public function testExecuteUpdate()
48
    {
49
        $sql      = 'INSERT INTO write_table (test_int) VALUES ( ' . $this->connection->quote(1) . ')';
50
        $affected = $this->connection->executeUpdate($sql);
51
52
        self::assertEquals(1, $affected, 'executeUpdate() should return the number of affected rows!');
53
    }
54
55
    public function testExecuteUpdateWithTypes()
56
    {
57
        $sql      = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
58
        $affected = $this->connection->executeUpdate(
59
            $sql,
60
            [1, 'foo'],
61
            [ParameterType::INTEGER, ParameterType::STRING]
62
        );
63
64
        self::assertEquals(1, $affected, 'executeUpdate() should return the number of affected rows!');
65
    }
66
67
    public function testPrepareRowCountReturnsAffectedRows()
68
    {
69
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
70
        $stmt = $this->connection->prepare($sql);
71
72
        $stmt->bindValue(1, 1);
73
        $stmt->bindValue(2, 'foo');
74
        $stmt->execute();
75
76
        self::assertEquals(1, $stmt->rowCount());
77
    }
78
79
    public function testPrepareWithPdoTypes()
80
    {
81
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
82
        $stmt = $this->connection->prepare($sql);
83
84
        $stmt->bindValue(1, 1, ParameterType::INTEGER);
85
        $stmt->bindValue(2, 'foo', ParameterType::STRING);
86
        $stmt->execute();
87
88
        self::assertEquals(1, $stmt->rowCount());
89
    }
90
91
    public function testPrepareWithDbalTypes()
92
    {
93
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
94
        $stmt = $this->connection->prepare($sql);
95
96
        $stmt->bindValue(1, 1, Type::getType('integer'));
97
        $stmt->bindValue(2, 'foo', Type::getType('string'));
98
        $stmt->execute();
99
100
        self::assertEquals(1, $stmt->rowCount());
101
    }
102
103
    public function testPrepareWithDbalTypeNames()
104
    {
105
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
106
        $stmt = $this->connection->prepare($sql);
107
108
        $stmt->bindValue(1, 1, 'integer');
109
        $stmt->bindValue(2, 'foo', 'string');
110
        $stmt->execute();
111
112
        self::assertEquals(1, $stmt->rowCount());
113
    }
114
115
    public function insertRows()
116
    {
117
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 1, 'test_string' => 'foo']));
118
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
119
    }
120
121
    public function testInsert()
122
    {
123
        $this->insertRows();
124
    }
125
126
    public function testDelete()
127
    {
128
        $this->insertRows();
129
130
        self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 2]));
131
        self::assertCount(1, $this->connection->fetchAll('SELECT * FROM write_table'));
132
133
        self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 1]));
134
        self::assertCount(0, $this->connection->fetchAll('SELECT * FROM write_table'));
135
    }
136
137
    public function testUpdate()
138
    {
139
        $this->insertRows();
140
141
        self::assertEquals(1, $this->connection->update('write_table', ['test_string' => 'bar'], ['test_string' => 'foo']));
142
        self::assertEquals(2, $this->connection->update('write_table', ['test_string' => 'baz'], ['test_string' => 'bar']));
143
        self::assertEquals(0, $this->connection->update('write_table', ['test_string' => 'baz'], ['test_string' => 'bar']));
144
    }
145
146
    public function testLastInsertId()
147
    {
148
        if (! $this->connection->getDatabasePlatform()->prefersIdentityColumns()) {
149
            $this->markTestSkipped('Test only works on platforms with identity columns.');
150
        }
151
152
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
153
        $num = $this->lastInsertId();
154
155
        self::assertNotNull($num, 'LastInsertId() should not be null.');
156
        self::assertGreaterThan(0, $num, 'LastInsertId() should be non-negative number.');
157
    }
158
159
    public function testLastInsertIdSequence()
160
    {
161
        if (! $this->connection->getDatabasePlatform()->supportsSequences()) {
162
            $this->markTestSkipped('Test only works on platforms with sequences.');
163
        }
164
165
        $sequence = new Sequence('write_table_id_seq');
166
        try {
167
            $this->connection->getSchemaManager()->createSequence($sequence);
168
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
169
        }
170
171
        $sequences = $this->connection->getSchemaManager()->listSequences();
172
        self::assertCount(1, array_filter($sequences, static function ($sequence) {
173
            return strtolower($sequence->getName()) === 'write_table_id_seq';
174
        }));
175
176
        $stmt            = $this->connection->query($this->connection->getDatabasePlatform()->getSequenceNextValSQL('write_table_id_seq'));
177
        $nextSequenceVal = $stmt->fetchColumn();
178
179
        $lastInsertId = $this->lastInsertId('write_table_id_seq');
180
181
        self::assertGreaterThan(0, $lastInsertId);
182
        self::assertEquals($nextSequenceVal, $lastInsertId);
183
    }
184
185
    public function testLastInsertIdNoSequenceGiven()
186
    {
187
        if (! $this->connection->getDatabasePlatform()->supportsSequences() || $this->connection->getDatabasePlatform()->supportsIdentityColumns()) {
188
            $this->markTestSkipped("Test only works consistently on platforms that support sequences and don't support identity columns.");
189
        }
190
191
        self::assertFalse($this->lastInsertId());
192
    }
193
194
    /**
195
     * @group DBAL-445
196
     */
197
    public function testInsertWithKeyValueTypes()
198
    {
199
        $testString = new DateTime('2013-04-14 10:10:10');
200
201
        $this->connection->insert(
202
            'write_table',
203
            ['test_int' => '30', 'test_string' => $testString],
204
            ['test_string' => 'datetime', 'test_int' => 'integer']
205
        );
206
207
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
208
209
        self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
210
    }
211
212
    /**
213
     * @group DBAL-445
214
     */
215
    public function testUpdateWithKeyValueTypes()
216
    {
217
        $testString = new DateTime('2013-04-14 10:10:10');
218
219
        $this->connection->insert(
220
            'write_table',
221
            ['test_int' => '30', 'test_string' => $testString],
222
            ['test_string' => 'datetime', 'test_int' => 'integer']
223
        );
224
225
        $testString = new DateTime('2013-04-15 10:10:10');
226
227
        $this->connection->update(
228
            'write_table',
229
            ['test_string' => $testString],
230
            ['test_int' => '30'],
231
            ['test_string' => 'datetime', 'test_int' => 'integer']
232
        );
233
234
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
235
236
        self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
237
    }
238
239
    /**
240
     * @group DBAL-445
241
     */
242
    public function testDeleteWithKeyValueTypes()
243
    {
244
        $val = new DateTime('2013-04-14 10:10:10');
245
        $this->connection->insert(
246
            'write_table',
247
            ['test_int' => '30', 'test_string' => $val],
248
            ['test_string' => 'datetime', 'test_int' => 'integer']
249
        );
250
251
        $this->connection->delete('write_table', ['test_int' => 30, 'test_string' => $val], ['test_string' => 'datetime', 'test_int' => 'integer']);
252
253
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
254
255
        self::assertFalse($data);
256
    }
257
258
    public function testEmptyIdentityInsert()
259
    {
260
        $platform = $this->connection->getDatabasePlatform();
261
262
        if (! ($platform->supportsIdentityColumns() || $platform->usesSequenceEmulatedIdentityColumns())) {
263
            $this->markTestSkipped(
264
                'Test only works on platforms with identity columns or sequence emulated identity columns.'
265
            );
266
        }
267
268
        $table = new Table('test_empty_identity');
269
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
270
        $table->setPrimaryKey(['id']);
271
272
        try {
273
            $this->connection->getSchemaManager()->dropTable($table->getQuotedName($platform));
274
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
275
        }
276
277
        foreach ($platform->getCreateTableSQL($table) as $sql) {
278
            $this->connection->exec($sql);
279
        }
280
281
        $seqName = $platform->usesSequenceEmulatedIdentityColumns()
282
            ? $platform->getIdentitySequenceName('test_empty_identity', 'id')
283
            : null;
284
285
        $sql = $platform->getEmptyIdentityInsertSQL('test_empty_identity', 'id');
286
287
        $this->connection->exec($sql);
288
289
        $firstId = $this->lastInsertId($seqName);
290
291
        $this->connection->exec($sql);
292
293
        $secondId = $this->lastInsertId($seqName);
294
295
        self::assertGreaterThan($firstId, $secondId);
296
    }
297
298
    /**
299
     * @group DBAL-2688
300
     */
301
    public function testUpdateWhereIsNull()
302
    {
303
        $this->connection->insert(
304
            'write_table',
305
            ['test_int' => '30', 'test_string' => null],
306
            ['test_string' => 'string', 'test_int' => 'integer']
307
        );
308
309
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
310
311
        self::assertCount(1, $data);
312
313
        $this->connection->update('write_table', ['test_int' => 10], ['test_string' => null], ['test_string' => 'string', 'test_int' => 'integer']);
314
315
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
316
317
        self::assertCount(0, $data);
318
    }
319
320
    public function testDeleteWhereIsNull()
321
    {
322
        $this->connection->insert(
323
            'write_table',
324
            ['test_int' => '30', 'test_string' => null],
325
            ['test_string' => 'string', 'test_int' => 'integer']
326
        );
327
328
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
329
330
        self::assertCount(1, $data);
331
332
        $this->connection->delete('write_table', ['test_string' => null], ['test_string' => 'string']);
333
334
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
335
336
        self::assertCount(0, $data);
337
    }
338
339
    /**
340
     * Returns the ID of the last inserted row or skips the test if the currently used driver
341
     * doesn't support this feature
342
     *
343
     * @return string
344
     *
345
     * @throws DriverException
346
     */
347
    private function lastInsertId(?string $name = null)
348
    {
349
        try {
350
            return $this->connection->lastInsertId($name);
351
        } catch (DriverException $e) {
352
            if ($e->getCode() === 'IM001') {
353
                $this->markTestSkipped($e->getMessage());
354
            }
355
356
            throw $e;
357
        }
358
    }
359
}
360