Failed Conditions
Pull Request — develop (#3582)
by Jonathan
69:13 queued 04:11
created

WriteTest::testExecuteUpdateFirstTypeIsNull()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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