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