WriteTest.php 11.5 KB
Newer Older
1 2 3
<?php

namespace Doctrine\Tests\DBAL\Functional;
4

Sergei Morozov's avatar
Sergei Morozov committed
5
use DateTime;
6
use Doctrine\DBAL\ParameterType;
Sergei Morozov's avatar
Sergei Morozov committed
7 8 9
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
10
use Doctrine\DBAL\Types\Type;
Sergei Morozov's avatar
Sergei Morozov committed
11 12
use Doctrine\Tests\DbalFunctionalTestCase;
use Throwable;
13 14
use function array_filter;
use function strtolower;
15

Sergei Morozov's avatar
Sergei Morozov committed
16
class WriteTest extends DbalFunctionalTestCase
17
{
18
    protected function setUp()
19 20 21 22
    {
        parent::setUp();

        try {
Sergei Morozov's avatar
Sergei Morozov committed
23 24
            $table = new Table('write_table');
            $table->addColumn('id', 'integer', ['autoincrement' => true]);
25
            $table->addColumn('test_int', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
26 27
            $table->addColumn('test_string', 'string', ['notnull' => false]);
            $table->setPrimaryKey(['id']);
28

Sergei Morozov's avatar
Sergei Morozov committed
29
            $this->connection->getSchemaManager()->createTable($table);
Sergei Morozov's avatar
Sergei Morozov committed
30
        } catch (Throwable $e) {
31
        }
Sergei Morozov's avatar
Sergei Morozov committed
32
        $this->connection->executeUpdate('DELETE FROM write_table');
33 34
    }

35 36 37 38 39
    /**
     * @group DBAL-80
     */
    public function testExecuteUpdateFirstTypeIsNull()
    {
Sergei Morozov's avatar
Sergei Morozov committed
40
        $sql = 'INSERT INTO write_table (test_string, test_int) VALUES (?, ?)';
Sergei Morozov's avatar
Sergei Morozov committed
41
        $this->connection->executeUpdate($sql, ['text', 1111], [null, ParameterType::INTEGER]);
42

Sergei Morozov's avatar
Sergei Morozov committed
43
        $sql = 'SELECT * FROM write_table WHERE test_string = ? AND test_int = ?';
Sergei Morozov's avatar
Sergei Morozov committed
44
        self::assertTrue((bool) $this->connection->fetchColumn($sql, ['text', 1111]));
45 46
    }

47 48
    public function testExecuteUpdate()
    {
Sergei Morozov's avatar
Sergei Morozov committed
49 50
        $sql      = 'INSERT INTO write_table (test_int) VALUES ( ' . $this->connection->quote(1) . ')';
        $affected = $this->connection->executeUpdate($sql);
51

Sergei Morozov's avatar
Sergei Morozov committed
52
        self::assertEquals(1, $affected, 'executeUpdate() should return the number of affected rows!');
53 54 55 56
    }

    public function testExecuteUpdateWithTypes()
    {
Sergei Morozov's avatar
Sergei Morozov committed
57
        $sql      = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
Sergei Morozov's avatar
Sergei Morozov committed
58
        $affected = $this->connection->executeUpdate(
59
            $sql,
Sergei Morozov's avatar
Sergei Morozov committed
60 61
            [1, 'foo'],
            [ParameterType::INTEGER, ParameterType::STRING]
62
        );
63

Sergei Morozov's avatar
Sergei Morozov committed
64
        self::assertEquals(1, $affected, 'executeUpdate() should return the number of affected rows!');
65 66 67 68
    }

    public function testPrepareRowCountReturnsAffectedRows()
    {
Sergei Morozov's avatar
Sergei Morozov committed
69
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
Sergei Morozov's avatar
Sergei Morozov committed
70
        $stmt = $this->connection->prepare($sql);
71 72

        $stmt->bindValue(1, 1);
Sergei Morozov's avatar
Sergei Morozov committed
73
        $stmt->bindValue(2, 'foo');
74 75
        $stmt->execute();

76
        self::assertEquals(1, $stmt->rowCount());
77 78 79 80
    }

    public function testPrepareWithPdoTypes()
    {
Sergei Morozov's avatar
Sergei Morozov committed
81
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
Sergei Morozov's avatar
Sergei Morozov committed
82
        $stmt = $this->connection->prepare($sql);
83

84
        $stmt->bindValue(1, 1, ParameterType::INTEGER);
Sergei Morozov's avatar
Sergei Morozov committed
85
        $stmt->bindValue(2, 'foo', ParameterType::STRING);
86 87
        $stmt->execute();

88
        self::assertEquals(1, $stmt->rowCount());
89 90 91 92
    }

    public function testPrepareWithDbalTypes()
    {
Sergei Morozov's avatar
Sergei Morozov committed
93
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
Sergei Morozov's avatar
Sergei Morozov committed
94
        $stmt = $this->connection->prepare($sql);
95 96

        $stmt->bindValue(1, 1, Type::getType('integer'));
Sergei Morozov's avatar
Sergei Morozov committed
97
        $stmt->bindValue(2, 'foo', Type::getType('string'));
98 99
        $stmt->execute();

100
        self::assertEquals(1, $stmt->rowCount());
101 102 103 104
    }

    public function testPrepareWithDbalTypeNames()
    {
Sergei Morozov's avatar
Sergei Morozov committed
105
        $sql  = 'INSERT INTO write_table (test_int, test_string) VALUES (?, ?)';
Sergei Morozov's avatar
Sergei Morozov committed
106
        $stmt = $this->connection->prepare($sql);
107 108

        $stmt->bindValue(1, 1, 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
109
        $stmt->bindValue(2, 'foo', 'string');
110 111
        $stmt->execute();

112
        self::assertEquals(1, $stmt->rowCount());
113 114 115 116
    }

    public function insertRows()
    {
Sergei Morozov's avatar
Sergei Morozov committed
117 118
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 1, 'test_string' => 'foo']));
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
119 120 121 122 123 124 125 126 127 128 129
    }

    public function testInsert()
    {
        $this->insertRows();
    }

    public function testDelete()
    {
        $this->insertRows();

Sergei Morozov's avatar
Sergei Morozov committed
130 131
        self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 2]));
        self::assertCount(1, $this->connection->fetchAll('SELECT * FROM write_table'));
132

Sergei Morozov's avatar
Sergei Morozov committed
133 134
        self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 1]));
        self::assertCount(0, $this->connection->fetchAll('SELECT * FROM write_table'));
135 136 137 138 139 140
    }

    public function testUpdate()
    {
        $this->insertRows();

Sergei Morozov's avatar
Sergei Morozov committed
141 142 143
        self::assertEquals(1, $this->connection->update('write_table', ['test_string' => 'bar'], ['test_string' => 'foo']));
        self::assertEquals(2, $this->connection->update('write_table', ['test_string' => 'baz'], ['test_string' => 'bar']));
        self::assertEquals(0, $this->connection->update('write_table', ['test_string' => 'baz'], ['test_string' => 'bar']));
144
    }
145 146 147

    public function testLastInsertId()
    {
Sergei Morozov's avatar
Sergei Morozov committed
148
        if (! $this->connection->getDatabasePlatform()->prefersIdentityColumns()) {
149 150 151
            $this->markTestSkipped('Test only works on platforms with identity columns.');
        }

Sergei Morozov's avatar
Sergei Morozov committed
152 153
        self::assertEquals(1, $this->connection->insert('write_table', ['test_int' => 2, 'test_string' => 'bar']));
        $num = $this->connection->lastInsertId();
154

Sergei Morozov's avatar
Sergei Morozov committed
155 156
        self::assertNotNull($num, 'LastInsertId() should not be null.');
        self::assertGreaterThan(0, $num, 'LastInsertId() should be non-negative number.');
157
    }
158 159 160

    public function testLastInsertIdSequence()
    {
Sergei Morozov's avatar
Sergei Morozov committed
161
        if (! $this->connection->getDatabasePlatform()->supportsSequences()) {
162 163 164
            $this->markTestSkipped('Test only works on platforms with sequences.');
        }

Sergei Morozov's avatar
Sergei Morozov committed
165
        $sequence = new Sequence('write_table_id_seq');
166
        try {
Sergei Morozov's avatar
Sergei Morozov committed
167
            $this->connection->getSchemaManager()->createSequence($sequence);
Sergei Morozov's avatar
Sergei Morozov committed
168
        } catch (Throwable $e) {
169 170
        }

Sergei Morozov's avatar
Sergei Morozov committed
171
        $sequences = $this->connection->getSchemaManager()->listSequences();
Sergei Morozov's avatar
Sergei Morozov committed
172
        self::assertCount(1, array_filter($sequences, static function ($sequence) {
173
            return strtolower($sequence->getName()) === 'write_table_id_seq';
Gabriel Caruso's avatar
Gabriel Caruso committed
174
        }));
175

Sergei Morozov's avatar
Sergei Morozov committed
176
        $stmt            = $this->connection->query($this->connection->getDatabasePlatform()->getSequenceNextValSQL('write_table_id_seq'));
177 178
        $nextSequenceVal = $stmt->fetchColumn();

Sergei Morozov's avatar
Sergei Morozov committed
179
        $lastInsertId = $this->connection->lastInsertId('write_table_id_seq');
180

Gabriel Caruso's avatar
Gabriel Caruso committed
181
        self::assertGreaterThan(0, $lastInsertId);
182
        self::assertEquals($nextSequenceVal, $lastInsertId);
183 184 185 186
    }

    public function testLastInsertIdNoSequenceGiven()
    {
Sergei Morozov's avatar
Sergei Morozov committed
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
        }

Sergei Morozov's avatar
Sergei Morozov committed
191
        self::assertFalse($this->connection->lastInsertId(null));
192
    }
193 194 195 196 197 198

    /**
     * @group DBAL-445
     */
    public function testInsertWithKeyValueTypes()
    {
Sergei Morozov's avatar
Sergei Morozov committed
199
        $testString = new DateTime('2013-04-14 10:10:10');
200

Sergei Morozov's avatar
Sergei Morozov committed
201
        $this->connection->insert(
202
            'write_table',
Sergei Morozov's avatar
Sergei Morozov committed
203 204
            ['test_int' => '30', 'test_string' => $testString],
            ['test_string' => 'datetime', 'test_int' => 'integer']
205 206
        );

Sergei Morozov's avatar
Sergei Morozov committed
207
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
208

Sergei Morozov's avatar
Sergei Morozov committed
209
        self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
210 211 212 213 214 215 216
    }

    /**
     * @group DBAL-445
     */
    public function testUpdateWithKeyValueTypes()
    {
Sergei Morozov's avatar
Sergei Morozov committed
217
        $testString = new DateTime('2013-04-14 10:10:10');
218

Sergei Morozov's avatar
Sergei Morozov committed
219
        $this->connection->insert(
220
            'write_table',
Sergei Morozov's avatar
Sergei Morozov committed
221 222
            ['test_int' => '30', 'test_string' => $testString],
            ['test_string' => 'datetime', 'test_int' => 'integer']
223 224
        );

Sergei Morozov's avatar
Sergei Morozov committed
225
        $testString = new DateTime('2013-04-15 10:10:10');
226

Sergei Morozov's avatar
Sergei Morozov committed
227
        $this->connection->update(
228
            'write_table',
Sergei Morozov's avatar
Sergei Morozov committed
229 230 231
            ['test_string' => $testString],
            ['test_int' => '30'],
            ['test_string' => 'datetime', 'test_int' => 'integer']
232 233
        );

Sergei Morozov's avatar
Sergei Morozov committed
234
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
235

Sergei Morozov's avatar
Sergei Morozov committed
236
        self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
237 238 239 240 241 242 243
    }

    /**
     * @group DBAL-445
     */
    public function testDeleteWithKeyValueTypes()
    {
Sergei Morozov's avatar
Sergei Morozov committed
244
        $val = new DateTime('2013-04-14 10:10:10');
Sergei Morozov's avatar
Sergei Morozov committed
245
        $this->connection->insert(
246
            'write_table',
Sergei Morozov's avatar
Sergei Morozov committed
247 248
            ['test_int' => '30', 'test_string' => $val],
            ['test_string' => 'datetime', 'test_int' => 'integer']
249 250
        );

Sergei Morozov's avatar
Sergei Morozov committed
251
        $this->connection->delete('write_table', ['test_int' => 30, 'test_string' => $val], ['test_string' => 'datetime', 'test_int' => 'integer']);
252

Sergei Morozov's avatar
Sergei Morozov committed
253
        $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
254

255
        self::assertFalse($data);
256
    }
257 258 259

    public function testEmptyIdentityInsert()
    {
Sergei Morozov's avatar
Sergei Morozov committed
260
        $platform = $this->connection->getDatabasePlatform();
261

Sergei Morozov's avatar
Sergei Morozov committed
262
        if (! ($platform->supportsIdentityColumns() || $platform->usesSequenceEmulatedIdentityColumns())) {
263 264 265 266 267
            $this->markTestSkipped(
                'Test only works on platforms with identity columns or sequence emulated identity columns.'
            );
        }

Sergei Morozov's avatar
Sergei Morozov committed
268 269 270
        $table = new Table('test_empty_identity');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
        $table->setPrimaryKey(['id']);
271 272

        try {
Sergei Morozov's avatar
Sergei Morozov committed
273
            $this->connection->getSchemaManager()->dropTable($table->getQuotedName($platform));
Sergei Morozov's avatar
Sergei Morozov committed
274 275
        } catch (Throwable $e) {
        }
276 277

        foreach ($platform->getCreateTableSQL($table) as $sql) {
Sergei Morozov's avatar
Sergei Morozov committed
278
            $this->connection->exec($sql);
279 280 281 282 283 284 285 286
        }

        $seqName = $platform->usesSequenceEmulatedIdentityColumns()
            ? $platform->getIdentitySequenceName('test_empty_identity', 'id')
            : null;

        $sql = $platform->getEmptyIdentityInsertSQL('test_empty_identity', 'id');

Sergei Morozov's avatar
Sergei Morozov committed
287
        $this->connection->exec($sql);
288

Sergei Morozov's avatar
Sergei Morozov committed
289
        $firstId = $this->connection->lastInsertId($seqName);
290

Sergei Morozov's avatar
Sergei Morozov committed
291
        $this->connection->exec($sql);
292

Sergei Morozov's avatar
Sergei Morozov committed
293
        $secondId = $this->connection->lastInsertId($seqName);
294

Gabriel Caruso's avatar
Gabriel Caruso committed
295
        self::assertGreaterThan($firstId, $secondId);
296 297
    }

298 299 300 301 302
    /**
     * @group DBAL-2688
     */
    public function testUpdateWhereIsNull()
    {
Sergei Morozov's avatar
Sergei Morozov committed
303
        $this->connection->insert(
304 305 306 307 308
            'write_table',
            ['test_int' => '30', 'test_string' => null],
            ['test_string' => 'string', 'test_int' => 'integer']
        );

Sergei Morozov's avatar
Sergei Morozov committed
309
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
310

311
        self::assertCount(1, $data);
312

Sergei Morozov's avatar
Sergei Morozov committed
313
        $this->connection->update('write_table', ['test_int' => 10], ['test_string' => null], ['test_string' => 'string', 'test_int' => 'integer']);
314

Sergei Morozov's avatar
Sergei Morozov committed
315
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
316

317
        self::assertCount(0, $data);
318 319 320 321
    }

    public function testDeleteWhereIsNull()
    {
Sergei Morozov's avatar
Sergei Morozov committed
322
        $this->connection->insert(
323 324 325 326 327
            'write_table',
            ['test_int' => '30', 'test_string' => null],
            ['test_string' => 'string', 'test_int' => 'integer']
        );

Sergei Morozov's avatar
Sergei Morozov committed
328
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
329

330
        self::assertCount(1, $data);
331

Sergei Morozov's avatar
Sergei Morozov committed
332
        $this->connection->delete('write_table', ['test_string' => null], ['test_string' => 'string']);
333

Sergei Morozov's avatar
Sergei Morozov committed
334
        $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
335

336
        self::assertCount(0, $data);
337
    }
338
}