BlobTest.php 5.27 KB
Newer Older
1 2
<?php

3
namespace Doctrine\DBAL\Tests\Functional;
4

5
use Doctrine\DBAL\Driver\OCI8\Driver as OCI8Driver;
6
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
7
use Doctrine\DBAL\FetchMode;
8
use Doctrine\DBAL\ParameterType;
Sergei Morozov's avatar
Sergei Morozov committed
9
use Doctrine\DBAL\Schema\Table;
10
use Doctrine\DBAL\Tests\FunctionalTestCase;
11
use Doctrine\DBAL\Types\Type;
12 13
use function fopen;
use function str_repeat;
14
use function stream_get_contents;
15 16 17 18

/**
 * @group DBAL-6
 */
19
class BlobTest extends FunctionalTestCase
20
{
21
    protected function setUp() : void
22 23 24
    {
        parent::setUp();

25 26 27
        if ($this->connection->getDriver() instanceof PDOOracleDriver) {
            // inserting BLOBs as streams on Oracle requires Oracle-specific SQL syntax which is currently not supported
            // see http://php.net/manual/en/pdo.lobs.php#example-1035
28
            self::markTestSkipped('DBAL doesn\'t support storing LOBs represented as streams using PDO_OCI');
29 30
        }

Sergei Morozov's avatar
Sergei Morozov committed
31 32 33 34 35
        $table = new Table('blob_table');
        $table->addColumn('id', 'integer');
        $table->addColumn('clobfield', 'text');
        $table->addColumn('blobfield', 'blob');
        $table->setPrimaryKey(['id']);
36

Sergei Morozov's avatar
Sergei Morozov committed
37
        $sm = $this->connection->getSchemaManager();
Sergei Morozov's avatar
Sergei Morozov committed
38
        $sm->dropAndCreateTable($table);
39 40
    }

41
    public function testInsert() : void
42
    {
Sergei Morozov's avatar
Sergei Morozov committed
43
        $ret = $this->connection->insert('blob_table', [
44 45 46 47 48 49 50 51 52
            'id'          => 1,
            'clobfield'   => 'test',
            'blobfield'   => 'test',
        ], [
            ParameterType::INTEGER,
            ParameterType::STRING,
            ParameterType::LARGE_OBJECT,
        ]);

53
        self::assertEquals(1, $ret);
54 55
    }

56
    public function testInsertProcessesStream() : void
57
    {
58 59
        // https://github.com/doctrine/dbal/issues/3290
        if ($this->connection->getDriver() instanceof OCI8Driver) {
60
            self::markTestIncomplete('The oci8 driver does not support stream resources as parameters');
61 62 63
        }

        $longBlob = str_repeat('x', 4 * 8192); // send 4 chunks
Sergei Morozov's avatar
Sergei Morozov committed
64
        $this->connection->insert('blob_table', [
65 66 67 68 69 70 71 72 73 74 75 76
            'id'        => 1,
            'clobfield' => 'ignored',
            'blobfield' => fopen('data://text/plain,' . $longBlob, 'r'),
        ], [
            ParameterType::INTEGER,
            ParameterType::STRING,
            ParameterType::LARGE_OBJECT,
        ]);

        $this->assertBlobContains($longBlob);
    }

77
    public function testSelect() : void
78
    {
Sergei Morozov's avatar
Sergei Morozov committed
79
        $this->connection->insert('blob_table', [
Sergei Morozov's avatar
Sergei Morozov committed
80 81 82 83 84 85 86 87
            'id'          => 1,
            'clobfield'   => 'test',
            'blobfield'   => 'test',
        ], [
            ParameterType::INTEGER,
            ParameterType::STRING,
            ParameterType::LARGE_OBJECT,
        ]);
88 89 90 91

        $this->assertBlobContains('test');
    }

92
    public function testUpdate() : void
93
    {
Sergei Morozov's avatar
Sergei Morozov committed
94
        $this->connection->insert('blob_table', [
Sergei Morozov's avatar
Sergei Morozov committed
95 96 97 98 99 100 101 102
            'id' => 1,
            'clobfield' => 'test',
            'blobfield' => 'test',
        ], [
            ParameterType::INTEGER,
            ParameterType::STRING,
            ParameterType::LARGE_OBJECT,
        ]);
103

Sergei Morozov's avatar
Sergei Morozov committed
104
        $this->connection->update('blob_table', ['blobfield' => 'test2'], ['id' => 1], [
Sergei Morozov's avatar
Sergei Morozov committed
105 106 107
            ParameterType::LARGE_OBJECT,
            ParameterType::INTEGER,
        ]);
108 109 110 111

        $this->assertBlobContains('test2');
    }

112
    public function testUpdateProcessesStream() : void
113
    {
114 115
        // https://github.com/doctrine/dbal/issues/3290
        if ($this->connection->getDriver() instanceof OCI8Driver) {
116
            self::markTestIncomplete('The oci8 driver does not support stream resources as parameters');
117 118
        }

Sergei Morozov's avatar
Sergei Morozov committed
119
        $this->connection->insert('blob_table', [
120 121 122 123 124 125 126 127 128
            'id'          => 1,
            'clobfield'   => 'ignored',
            'blobfield'   => 'test',
        ], [
            ParameterType::INTEGER,
            ParameterType::STRING,
            ParameterType::LARGE_OBJECT,
        ]);

Sergei Morozov's avatar
Sergei Morozov committed
129
        $this->connection->update('blob_table', [
130 131 132 133 134 135 136 137 138 139
            'id'          => 1,
            'blobfield'   => fopen('data://text/plain,test2', 'r'),
        ], ['id' => 1], [
            ParameterType::INTEGER,
            ParameterType::LARGE_OBJECT,
        ]);

        $this->assertBlobContains('test2');
    }

140
    public function testBindParamProcessesStream() : void
141
    {
142
        if ($this->connection->getDriver() instanceof OCI8Driver) {
143
            self::markTestIncomplete('The oci8 driver does not support stream resources as parameters');
144 145
        }

Sergei Morozov's avatar
Sergei Morozov committed
146
        $stmt = $this->connection->prepare("INSERT INTO blob_table(id, clobfield, blobfield) VALUES (1, 'ignored', ?)");
147 148 149 150 151 152 153 154 155 156 157 158

        $stream = null;
        $stmt->bindParam(1, $stream, ParameterType::LARGE_OBJECT);

        // Bind param does late binding (bind by reference), so create the stream only now:
        $stream = fopen('data://text/plain,test', 'r');

        $stmt->execute();

        $this->assertBlobContains('test');
    }

159
    private function assertBlobContains(string $text) : void
160
    {
Sergei Morozov's avatar
Sergei Morozov committed
161
        $rows = $this->connection->query('SELECT blobfield FROM blob_table')->fetchAll(FetchMode::COLUMN);
162

Gabriel Caruso's avatar
Gabriel Caruso committed
163
        self::assertCount(1, $rows);
164

Sergei Morozov's avatar
Sergei Morozov committed
165
        $blobValue = Type::getType('blob')->convertToPHPValue($rows[0], $this->connection->getDatabasePlatform());
166

167
        self::assertIsResource($blobValue);
168
        self::assertEquals($text, stream_get_contents($blobValue));
169
    }
170
}