Completed
Pull Request — master (#3759)
by Benjamin
61:16
created

WriteTest::testInsertWithKeyValueTypes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 13
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\Driver\PDOConnection;
10
use Doctrine\DBAL\ParameterType;
11
use Doctrine\DBAL\Platforms\OraclePlatform;
12
use Doctrine\DBAL\Schema\Sequence;
13
use Doctrine\DBAL\Schema\Table;
14
use Doctrine\Tests\DbalFunctionalTestCase;
15
use Doctrine\Tests\TestUtil;
16
use Throwable;
17
use function array_filter;
18
use function strtolower;
19
20
class WriteTest extends DbalFunctionalTestCase
21
{
22
    protected function setUp() : void
23
    {
24
        parent::setUp();
25
26
        $table = new Table('write_table');
27
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
28
        $table->addColumn('test_int', 'integer');
29
        $table->addColumn('test_string', 'string', [
30
            'length' => 32,
31
            'notnull' => false,
32
        ]);
33
        $table->setPrimaryKey(['id']);
34
35
        $this->connection->getSchemaManager()->dropAndCreateTable($table);
36
37
        $this->connection->executeUpdate('DELETE FROM write_table');
38
    }
39
40
    public function testExecuteUpdate() : void
41
    {
42
        $sql      = 'INSERT INTO write_table (test_int) VALUES (1)';
43
        $affected = $this->connection->executeUpdate($sql);
44
45
        self::assertEquals(1, $affected, 'executeUpdate() should return the number of affected rows!');
46
    }
47
48
    public function testExecuteUpdateWithTypes() : void
49
    {
50
        $sql      = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
51
        $affected = $this->connection->executeUpdate(
52
            $sql,
53
            [1, 'foo'],
54
            [ParameterType::INTEGER, ParameterType::STRING]
55
        );
56
57
        self::assertEquals(1, $affected, 'executeUpdate() should return the number of affected rows!');
58
    }
59
60
    public function testPrepareRowCountReturnsAffectedRows() : void
61
    {
62
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
63
        $stmt = $this->connection->prepare($sql);
64
65
        $stmt->bindValue(1, 1);
66
        $stmt->bindValue(2, 'foo');
67
        $stmt->execute();
68
69
        self::assertEquals(1, $stmt->rowCount());
70
    }
71
72
    public function testPrepareWithPdoTypes() : void
73
    {
74
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
75
        $stmt = $this->connection->prepare($sql);
76
77
        $stmt->bindValue(1, 1, ParameterType::INTEGER);
78
        $stmt->bindValue(2, 'foo', ParameterType::STRING);
79
        $stmt->execute();
80
81
        self::assertEquals(1, $stmt->rowCount());
82
    }
83
84
    public function testPrepareWithDbalTypes() : void
85
    {
86
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
87
        $stmt = $this->connection->prepare($sql);
88
89
        $stmt->bindValue(1, 1, ParameterType::INTEGER);
90
        $stmt->bindValue(2, 'foo', ParameterType::STRING);
91
        $stmt->execute();
92
93
        self::assertEquals(1, $stmt->rowCount());
94
    }
95
96
    public function testPrepareWithDbalTypeNames() : void
97
    {
98
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
99
        $stmt = $this->connection->prepare($sql);
100
101
        $stmt->bindValue(1, 1, ParameterType::INTEGER);
102
        $stmt->bindValue(2, 'foo', ParameterType::STRING);
103
        $stmt->execute();
104
105
        self::assertEquals(1, $stmt->rowCount());
106
    }
107
108
    public function insertRows() : void
109
    {
110
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 1, 'test_string' => 'foo']));
111
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
112
    }
113
114
    public function testInsert() : void
115
    {
116
        $this->insertRows();
117
    }
118
119
    public function testDelete() : void
120
    {
121
        $this->insertRows();
122
123
        self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 2]));
124
        self::assertCount(1, $this->connection->fetchAll('SELECT * FROM write_table'));
125
126
        self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 1]));
127
        self::assertCount(0, $this->connection->fetchAll('SELECT * FROM write_table'));
128
    }
129
130
    public function testUpdate() : void
131
    {
132
        $this->insertRows();
133
134
        self::assertEquals(1, $this->connection->update('write_table', ['test_string' => 'bar'], ['test_string' => 'foo']));
135
        self::assertEquals(2, $this->connection->update('write_table', ['test_string' => 'baz'], ['test_string' => 'bar']));
136
        self::assertEquals(0, $this->connection->update('write_table', ['test_string' => 'baz'], ['test_string' => 'bar']));
137
    }
138
139
    public function testLastInsertId() : void
140
    {
141
        if (! $this->connection->getDatabasePlatform()->supportsIdentityColumns()) {
142
            $this->markTestSkipped('This test targets platforms that support identity columns.');
143
        }
144
145
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
146
        $num = $this->connection->lastInsertId();
147
148
        self::assertGreaterThan(0, $num, 'LastInsertId() should be non-negative number.');
149
    }
150
151
    public function testLastInsertIdNotSupported() : void
152
    {
153
        if ($this->connection->getDatabasePlatform()->supportsIdentityColumns()) {
154
            $this->markTestSkipped('This test targets platforms that don\'t support identity columns.');
155
        }
156
157
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
158
159
        self::expectException(DriverException::class);
0 ignored issues
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

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

159
        self::/** @scrutinizer ignore-call */ 
160
              expectException(DriverException::class);
Loading history...
160
        $this->connection->lastInsertId();
161
    }
162
163
    public function testLastInsertIdNewConnection() : void
164
    {
165
        $connection = TestUtil::getConnection();
166
167
        $this->expectException(DriverException::class);
168
        $connection->lastInsertId();
169
    }
170
171
    public function testGetSequenceNumber() : void
172
    {
173
        $platform = $this->connection->getDatabasePlatform();
174
175
        if (! $platform->supportsSequences()) {
176
            $this->markTestSkipped('This test targets platforms that support sequences.');
177
        }
178
179
        if ($platform instanceof OraclePlatform && $this->connection->getWrappedConnection() instanceof PDOConnection) {
180
            $this->markTestSkipped('Oracle supports sequences, but PDO OCI driver does not support lastInsertId()');
181
        }
182
183
        $sequence = new Sequence('write_table_id_seq');
184
        try {
185
            $this->connection->getSchemaManager()->createSequence($sequence);
186
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
187
        }
188
189
        $sequences = $this->connection->getSchemaManager()->listSequences();
190
        self::assertCount(1, array_filter($sequences, static function ($sequence) {
191
            return strtolower($sequence->getName()) === 'write_table_id_seq';
192
        }));
193
194
        $stmt            = $this->connection->query($this->connection->getDatabasePlatform()->getSequenceNextValSQL('write_table_id_seq'));
195
        $nextSequenceVal = $stmt->fetchColumn();
196
197
        $sequenceNumber = $this->connection->getSequenceNumber('write_table_id_seq');
198
199
        self::assertGreaterThan(0, $sequenceNumber);
200
        self::assertEquals($nextSequenceVal, $sequenceNumber);
201
    }
202
203
    public function testGetSequenceNumberNotSupportedOrSequenceDoesNotExist() : void
204
    {
205
        $this->expectException(DriverException::class);
206
        $this->connection->getSequenceNumber('unknown-sequence');
207
    }
208
209
    /**
210
     * @group DBAL-445
211
     */
212
    public function testInsertWithKeyValueTypes() : void
213
    {
214
        $testString = new DateTime('2013-04-14 10:10:10');
215
216
        $this->connection->insert(
217
            'write_table',
218
            ['test_int' => '30', 'test_string' => $testString],
219
            ['test_string' => 'datetime', 'test_int' => 'integer']
220
        );
221
222
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
223
224
        self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
225
    }
226
227
    /**
228
     * @group DBAL-445
229
     */
230
    public function testUpdateWithKeyValueTypes() : void
231
    {
232
        $testString = new DateTime('2013-04-14 10:10:10');
233
234
        $this->connection->insert(
235
            'write_table',
236
            ['test_int' => '30', 'test_string' => $testString],
237
            ['test_string' => 'datetime', 'test_int' => 'integer']
238
        );
239
240
        $testString = new DateTime('2013-04-15 10:10:10');
241
242
        $this->connection->update(
243
            'write_table',
244
            ['test_string' => $testString],
245
            ['test_int' => '30'],
246
            ['test_string' => 'datetime', 'test_int' => 'integer']
247
        );
248
249
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
250
251
        self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
252
    }
253
254
    /**
255
     * @group DBAL-445
256
     */
257
    public function testDeleteWithKeyValueTypes() : void
258
    {
259
        $val = new DateTime('2013-04-14 10:10:10');
260
        $this->connection->insert(
261
            'write_table',
262
            ['test_int' => '30', 'test_string' => $val],
263
            ['test_string' => 'datetime', 'test_int' => 'integer']
264
        );
265
266
        $this->connection->delete('write_table', ['test_int' => 30, 'test_string' => $val], ['test_string' => 'datetime', 'test_int' => 'integer']);
267
268
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
269
270
        self::assertFalse($data);
271
    }
272
273
    public function testEmptyIdentityInsert() : void
274
    {
275
        $platform = $this->connection->getDatabasePlatform();
276
277
        if (! $platform->supportsIdentityColumns() || $platform->usesSequenceEmulatedIdentityColumns()) {
278
            $this->markTestSkipped(
279
                'Test only works on platforms with native support for identity columns.'
280
            );
281
        }
282
283
        $table = new Table('test_empty_identity');
284
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
285
        $table->setPrimaryKey(['id']);
286
287
        try {
288
            $this->connection->getSchemaManager()->dropTable($table->getQuotedName($platform));
289
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
290
        }
291
292
        foreach ($platform->getCreateTableSQL($table) as $sql) {
293
            $this->connection->exec($sql);
294
        }
295
296
        $sql = $platform->getEmptyIdentityInsertSQL('test_empty_identity', 'id');
297
298
        $this->connection->exec($sql);
299
        $firstId = $this->connection->lastInsertId();
300
301
        $this->connection->exec($sql);
302
        $secondId = $this->connection->lastInsertId();
303
304
        self::assertGreaterThan($firstId, $secondId);
305
    }
306
307
    public function testEmptyIdentityInsertEmulated() : void
308
    {
309
        $platform = $this->connection->getDatabasePlatform();
310
311
        if (! $platform->usesSequenceEmulatedIdentityColumns()) {
312
            $this->markTestSkipped(
313
                'Test only works on platforms with emulated identity columns.'
314
            );
315
        }
316
317
        if ($platform instanceof OraclePlatform && $this->connection->getWrappedConnection() instanceof PDOConnection) {
318
            $this->markTestSkipped(
319
                'Oracle supports emulated identity columns through sequences, ' .
320
                'but PDO OCI driver does not support lastInsertId()'
321
            );
322
        }
323
324
        $table = new Table('test_empty_identity');
325
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
326
        $table->setPrimaryKey(['id']);
327
328
        try {
329
            $this->connection->getSchemaManager()->dropTable($table->getQuotedName($platform));
330
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
331
        }
332
333
        foreach ($platform->getCreateTableSQL($table) as $sql) {
334
            $this->connection->exec($sql);
335
        }
336
337
        $seqName = $platform->getIdentitySequenceName('test_empty_identity', 'id');
338
339
        $sql = $platform->getEmptyIdentityInsertSQL('test_empty_identity', 'id');
340
341
        $this->connection->exec($sql);
342
        $firstId = $this->connection->getSequenceNumber($seqName);
343
344
        $this->connection->exec($sql);
345
        $secondId = $this->connection->getSequenceNumber($seqName);
346
347
        self::assertGreaterThan($firstId, $secondId);
348
    }
349
350
    /**
351
     * @group DBAL-2688
352
     */
353
    public function testUpdateWhereIsNull() : void
354
    {
355
        $this->connection->insert(
356
            'write_table',
357
            ['test_int' => '30', 'test_string' => null],
358
            ['test_string' => 'string', 'test_int' => 'integer']
359
        );
360
361
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
362
363
        self::assertCount(1, $data);
364
365
        $this->connection->update('write_table', ['test_int' => 10], ['test_string' => null], ['test_string' => 'string', 'test_int' => 'integer']);
366
367
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
368
369
        self::assertCount(0, $data);
370
    }
371
372
    public function testDeleteWhereIsNull() : void
373
    {
374
        $this->connection->insert(
375
            'write_table',
376
            ['test_int' => '30', 'test_string' => null],
377
            ['test_string' => 'string', 'test_int' => 'integer']
378
        );
379
380
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
381
382
        self::assertCount(1, $data);
383
384
        $this->connection->delete('write_table', ['test_string' => null], ['test_string' => 'string']);
385
386
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
387
388
        self::assertCount(0, $data);
389
    }
390
}
391