Completed
Pull Request — master (#3759)
by Benjamin
63:20
created

WriteTest::testGetSequenceNumber()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 17
c 2
b 0
f 0
dl 0
loc 30
rs 9.3888
cc 5
nc 8
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 Oracle 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 identity columns or sequence emulated identity columns.'
280
            );
281
        }
282
283
        if ($platform instanceof OraclePlatform && $this->connection->getWrappedConnection() instanceof PDOConnection) {
284
            $this->markTestSkipped(
285
                'Oracle supports emulated identity columns through sequences, ' .
286
                'but PDO Oracle driver does not support lastInsertId()'
287
            );
288
        }
289
290
        $table = new Table('test_empty_identity');
291
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
292
        $table->setPrimaryKey(['id']);
293
294
        try {
295
            $this->connection->getSchemaManager()->dropTable($table->getQuotedName($platform));
296
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
297
        }
298
299
        foreach ($platform->getCreateTableSQL($table) as $sql) {
300
            $this->connection->exec($sql);
301
        }
302
303
        $seqName = $platform->usesSequenceEmulatedIdentityColumns()
304
            ? $platform->getIdentitySequenceName('test_empty_identity', 'id')
305
            : null;
306
307
        $sql = $platform->getEmptyIdentityInsertSQL('test_empty_identity', 'id');
308
309
        $this->connection->exec($sql);
310
311
        $firstId = $seqName !== null
312
            ? $this->connection->getSequenceNumber($seqName)
313
            : $this->connection->lastInsertId();
314
315
        $this->connection->exec($sql);
316
317
        $secondId = $seqName !== null
318
            ? $this->connection->getSequenceNumber($seqName)
319
            : $this->connection->lastInsertId();
320
321
        self::assertGreaterThan($firstId, $secondId);
322
    }
323
324
    /**
325
     * @group DBAL-2688
326
     */
327
    public function testUpdateWhereIsNull() : void
328
    {
329
        $this->connection->insert(
330
            'write_table',
331
            ['test_int' => '30', 'test_string' => null],
332
            ['test_string' => 'string', 'test_int' => 'integer']
333
        );
334
335
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
336
337
        self::assertCount(1, $data);
338
339
        $this->connection->update('write_table', ['test_int' => 10], ['test_string' => null], ['test_string' => 'string', 'test_int' => 'integer']);
340
341
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
342
343
        self::assertCount(0, $data);
344
    }
345
346
    public function testDeleteWhereIsNull() : void
347
    {
348
        $this->connection->insert(
349
            'write_table',
350
            ['test_int' => '30', 'test_string' => null],
351
            ['test_string' => 'string', 'test_int' => 'integer']
352
        );
353
354
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
355
356
        self::assertCount(1, $data);
357
358
        $this->connection->delete('write_table', ['test_string' => null], ['test_string' => 'string']);
359
360
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
361
362
        self::assertCount(0, $data);
363
    }
364
}
365