TypeConversionTest.php 7.37 KB
Newer Older
1 2
<?php

Michael Moravec's avatar
Michael Moravec committed
3 4
declare(strict_types=1);

5
namespace Doctrine\DBAL\Tests\Functional;
6

Sergei Morozov's avatar
Sergei Morozov committed
7
use DateTime;
8
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
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;
Sergei Morozov's avatar
Sergei Morozov committed
12
use stdClass;
13
use function str_repeat;
14

15
class TypeConversionTest extends FunctionalTestCase
16
{
Sergei Morozov's avatar
Sergei Morozov committed
17
    /** @var int */
18
    private static $typeCounter = 0;
19

20
    protected function setUp() : void
21 22 23
    {
        parent::setUp();

Sergei Morozov's avatar
Sergei Morozov committed
24 25
        $table = new Table('type_conversion');
        $table->addColumn('id', 'integer', ['notnull' => false]);
26 27 28 29
        $table->addColumn('test_string', 'string', [
            'length' => 16,
            'notnull' => false,
        ]);
Sergei Morozov's avatar
Sergei Morozov committed
30 31 32 33 34 35 36 37 38
        $table->addColumn('test_boolean', 'boolean', ['notnull' => false]);
        $table->addColumn('test_bigint', 'bigint', ['notnull' => false]);
        $table->addColumn('test_smallint', 'bigint', ['notnull' => false]);
        $table->addColumn('test_datetime', 'datetime', ['notnull' => false]);
        $table->addColumn('test_datetimetz', 'datetimetz', ['notnull' => false]);
        $table->addColumn('test_date', 'date', ['notnull' => false]);
        $table->addColumn('test_time', 'time', ['notnull' => false]);
        $table->addColumn('test_text', 'text', ['notnull' => false]);
        $table->addColumn('test_array', 'array', ['notnull' => false]);
39
        $table->addColumn('test_json', 'json', ['notnull' => false]);
Sergei Morozov's avatar
Sergei Morozov committed
40 41 42 43
        $table->addColumn('test_object', 'object', ['notnull' => false]);
        $table->addColumn('test_float', 'float', ['notnull' => false]);
        $table->addColumn('test_decimal', 'decimal', ['notnull' => false, 'scale' => 2, 'precision' => 10]);
        $table->setPrimaryKey(['id']);
44

45 46 47
        $this->connection
            ->getSchemaManager()
            ->dropAndCreateTable($table);
48 49
    }

50
    /**
51 52
     * @param mixed $originalValue
     *
53 54 55
     * @dataProvider booleanProvider
     */
    public function testIdempotentConversionToBoolean(string $type, $originalValue) : void
56
    {
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
        $dbValue = $this->processValue($type, $originalValue);

        self::assertIsBool($dbValue);
        self::assertEquals($originalValue, $dbValue);
    }

    /**
     * @return mixed[][]
     */
    public static function booleanProvider() : iterable
    {
        return [
            'true' => ['boolean', true],
            'false' => ['boolean', false],
        ];
    }
Sergei Morozov's avatar
Sergei Morozov committed
73

74
    /**
75 76
     * @param mixed $originalValue
     *
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
     * @dataProvider integerProvider
     */
    public function testIdempotentConversionToInteger(string $type, $originalValue) : void
    {
        $dbValue = $this->processValue($type, $originalValue);

        self::assertIsInt($dbValue);
        self::assertEquals($originalValue, $dbValue);
    }

    /**
     * @return mixed[][]
     */
    public static function integerProvider() : iterable
    {
Sergei Morozov's avatar
Sergei Morozov committed
92
        return [
93
            'smallint' => ['smallint', 123],
Sergei Morozov's avatar
Sergei Morozov committed
94
        ];
95 96 97
    }

    /**
98 99
     * @param mixed $originalValue
     *
100
     * @dataProvider floatProvider
101
     */
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    public function testIdempotentConversionToFloat(string $type, $originalValue) : void
    {
        $dbValue = $this->processValue($type, $originalValue);

        self::assertIsFloat($dbValue);
        self::assertEquals($originalValue, $dbValue);
    }

    /**
     * @return mixed[][]
     */
    public static function floatProvider() : iterable
    {
        return [
            'float' => ['float', 1.5],
        ];
    }

    /**
121 122
     * @param mixed $originalValue
     *
123 124 125
     * @dataProvider toStringProvider
     */
    public function testIdempotentConversionToString(string $type, $originalValue) : void
126
    {
127 128 129 130 131 132
        if ($type === 'text' && $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
            $this->markTestSkipped('DBAL doesn\'t support storing LOBs represented as streams using PDO_OCI');
        }

133
        $dbValue = $this->processValue($type, $originalValue);
134

135 136 137
        self::assertIsString($dbValue);
        self::assertEquals($originalValue, $dbValue);
    }
138

139 140 141 142 143 144 145 146 147 148 149 150
    /**
     * @return mixed[][]
     */
    public static function toStringProvider() : iterable
    {
        return [
            'string' => ['string', 'ABCDEFGabcdefg'],
            'bigint' => ['bigint', 12345678],
            'text' => ['text', str_repeat('foo ', 1000)],
            'decimal' => ['decimal', 1.55],
        ];
    }
151

152
    /**
153 154
     * @param mixed $originalValue
     *
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
     * @dataProvider toArrayProvider
     */
    public function testIdempotentConversionToArray(string $type, $originalValue) : void
    {
        $dbValue = $this->processValue($type, $originalValue);

        self::assertIsArray($dbValue);
        self::assertEquals($originalValue, $dbValue);
    }

    /**
     * @return mixed[][]
     */
    public static function toArrayProvider() : iterable
    {
        return [
            'array' => ['array', ['foo' => 'bar']],
172
            'json' => ['json', ['foo' => 'bar']],
173 174 175 176
        ];
    }

    /**
177 178
     * @param mixed $originalValue
     *
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
     * @dataProvider toObjectProvider
     */
    public function testIdempotentConversionToObject(string $type, $originalValue) : void
    {
        $dbValue = $this->processValue($type, $originalValue);

        self::assertIsObject($dbValue);
        self::assertEquals($originalValue, $dbValue);
    }

    /**
     * @return mixed[][]
     */
    public static function toObjectProvider() : iterable
    {
        $obj      = new stdClass();
        $obj->foo = 'bar';
        $obj->bar = 'baz';

        return [
            'object' => ['object', $obj],
        ];
    }

    /**
     * @dataProvider toDateTimeProvider
     */
    public function testIdempotentConversionToDateTime(string $type, DateTime $originalValue) : void
    {
        $dbValue = $this->processValue($type, $originalValue);

        self::assertInstanceOf(DateTime::class, $dbValue);
Sergei Morozov's avatar
Sergei Morozov committed
211 212 213

        if ($type === 'datetimetz') {
            return;
214
        }
215

216 217 218 219 220 221
        self::assertEquals($originalValue, $dbValue);
        self::assertEquals(
            $originalValue->getTimezone(),
            $dbValue->getTimezone()
        );
    }
222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    /**
     * @return mixed[][]
     */
    public static function toDateTimeProvider() : iterable
    {
        return [
            'datetime' => ['datetime', new DateTime('2010-04-05 10:10:10')],
            'datetimetz' => ['datetimetz', new DateTime('2010-04-05 10:10:10')],
            'date' => ['date', new DateTime('2010-04-05')],
            'time' => ['time', new DateTime('1970-01-01 10:10:10')],
        ];
    }

    /**
     * @param mixed $originalValue
238 239
     *
     * @return mixed
240 241 242 243 244 245 246 247 248 249
     */
    private function processValue(string $type, $originalValue)
    {
        $columnName     = 'test_' . $type;
        $typeInstance   = Type::getType($type);
        $insertionValue = $typeInstance->convertToDatabaseValue($originalValue, $this->connection->getDatabasePlatform());

        $this->connection->insert('type_conversion', ['id' => ++self::$typeCounter, $columnName => $insertionValue]);

        $sql = 'SELECT ' . $columnName . ' FROM type_conversion WHERE id = ' . self::$typeCounter;
Sergei Morozov's avatar
Sergei Morozov committed
250

251 252 253 254
        return $typeInstance->convertToPHPValue(
            $this->connection->fetchColumn($sql),
            $this->connection->getDatabasePlatform()
        );
255
    }
256
}