DBAL630Test.php 5.59 KB
Newer Older
1 2
<?php

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

5 6
namespace Doctrine\Tests\DBAL\Functional\Ticket;

7
use Doctrine\DBAL\DBALException;
8
use Doctrine\DBAL\Driver\PDOConnection;
9
use Doctrine\DBAL\ParameterType;
Sergei Morozov's avatar
Sergei Morozov committed
10
use Doctrine\Tests\DbalFunctionalTestCase;
11
use PDO;
12
use function assert;
13
use function in_array;
14 15 16 17

/**
 * @group DBAL-630
 */
Sergei Morozov's avatar
Sergei Morozov committed
18
class DBAL630Test extends DbalFunctionalTestCase
19
{
Sergei Morozov's avatar
Sergei Morozov committed
20
    /** @var bool */
21 22
    private $running = false;

23
    protected function setUp() : void
24 25 26
    {
        parent::setUp();

Sergei Morozov's avatar
Sergei Morozov committed
27
        $platform = $this->connection->getDatabasePlatform()->getName();
28

Sergei Morozov's avatar
Sergei Morozov committed
29
        if (! in_array($platform, ['postgresql'])) {
30 31 32
            $this->markTestSkipped('Currently restricted to PostgreSQL');
        }

33
        try {
Sergei Morozov's avatar
Sergei Morozov committed
34 35
            $this->connection->exec('CREATE TABLE dbal630 (id SERIAL, bool_col BOOLEAN NOT NULL);');
            $this->connection->exec('CREATE TABLE dbal630_allow_nulls (id SERIAL, bool_col BOOLEAN);');
36 37
        } catch (DBALException $e) {
        }
38 39 40
        $this->running = true;
    }

41
    protected function tearDown() : void
42 43
    {
        if ($this->running) {
44
            $pdo = $this->getPDO();
45

46
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
47
        }
48 49

        parent::tearDown();
50 51
    }

52
    public function testBooleanConversionSqlLiteral() : void
53
    {
Sergei Morozov's avatar
Sergei Morozov committed
54 55
        $this->connection->executeUpdate('INSERT INTO dbal630 (bool_col) VALUES(false)');
        $id = $this->connection->lastInsertId('dbal630_id_seq');
56
        self::assertNotEmpty($id);
57

Sergei Morozov's avatar
Sergei Morozov committed
58
        $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
59

60
        self::assertFalse($row['bool_col']);
61 62
    }

63
    public function testBooleanConversionBoolParamRealPrepares() : void
64
    {
Sergei Morozov's avatar
Sergei Morozov committed
65
        $this->connection->executeUpdate(
66
            'INSERT INTO dbal630 (bool_col) VALUES(?)',
Sergei Morozov's avatar
Sergei Morozov committed
67 68
            ['false'],
            [ParameterType::BOOLEAN]
69
        );
Sergei Morozov's avatar
Sergei Morozov committed
70
        $id = $this->connection->lastInsertId('dbal630_id_seq');
71
        self::assertNotEmpty($id);
72

Sergei Morozov's avatar
Sergei Morozov committed
73
        $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
74

75
        self::assertFalse($row['bool_col']);
76 77
    }

78
    public function testBooleanConversionBoolParamEmulatedPrepares() : void
79
    {
80 81
        $pdo = $this->getPDO();
        $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
82

Sergei Morozov's avatar
Sergei Morozov committed
83
        $platform = $this->connection->getDatabasePlatform();
84

Sergei Morozov's avatar
Sergei Morozov committed
85
        $stmt = $this->connection->prepare('INSERT INTO dbal630 (bool_col) VALUES(?)');
86
        $stmt->bindValue(1, $platform->convertBooleansToDatabaseValue('false'), ParameterType::BOOLEAN);
87 88
        $stmt->execute();

Sergei Morozov's avatar
Sergei Morozov committed
89
        $id = $this->connection->lastInsertId('dbal630_id_seq');
90

91
        self::assertNotEmpty($id);
92

Sergei Morozov's avatar
Sergei Morozov committed
93
        $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
94

95
        self::assertFalse($row['bool_col']);
96
    }
97

98 99 100 101
    /**
     * @dataProvider booleanTypeConversionWithoutPdoTypeProvider
     */
    public function testBooleanConversionNullParamEmulatedPrepares(
102 103 104
        ?bool $statementValue,
        ?bool $databaseConvertedValue
    ) : void {
105 106
        $pdo = $this->getPDO();
        $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
107

Sergei Morozov's avatar
Sergei Morozov committed
108
        $platform = $this->connection->getDatabasePlatform();
109

Sergei Morozov's avatar
Sergei Morozov committed
110
        $stmt = $this->connection->prepare('INSERT INTO dbal630_allow_nulls (bool_col) VALUES(?)');
111
        $stmt->bindValue(1, $platform->convertBooleansToDatabaseValue($statementValue));
112 113
        $stmt->execute();

Sergei Morozov's avatar
Sergei Morozov committed
114
        $id = $this->connection->lastInsertId('dbal630_allow_nulls_id_seq');
115

116
        self::assertNotEmpty($id);
117

Sergei Morozov's avatar
Sergei Morozov committed
118
        $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]);
119

120
        self::assertSame($databaseConvertedValue, $row['bool_col']);
121 122 123 124 125 126
    }

    /**
     * @dataProvider booleanTypeConversionUsingBooleanTypeProvider
     */
    public function testBooleanConversionNullParamEmulatedPreparesWithBooleanTypeInBindValue(
127 128 129
        ?bool $statementValue,
        bool $databaseConvertedValue
    ) : void {
130 131
        $pdo = $this->getPDO();
        $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
132

Sergei Morozov's avatar
Sergei Morozov committed
133
        $platform = $this->connection->getDatabasePlatform();
134

Sergei Morozov's avatar
Sergei Morozov committed
135
        $stmt = $this->connection->prepare('INSERT INTO dbal630_allow_nulls (bool_col) VALUES(?)');
136 137 138 139 140
        $stmt->bindValue(
            1,
            $platform->convertBooleansToDatabaseValue($statementValue),
            ParameterType::BOOLEAN
        );
141 142
        $stmt->execute();

Sergei Morozov's avatar
Sergei Morozov committed
143
        $id = $this->connection->lastInsertId('dbal630_allow_nulls_id_seq');
144

145
        self::assertNotEmpty($id);
146

Sergei Morozov's avatar
Sergei Morozov committed
147
        $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]);
148

149
        self::assertSame($databaseConvertedValue, $row['bool_col']);
150 151 152 153
    }

    /**
     * Boolean conversion mapping provider
Sergei Morozov's avatar
Sergei Morozov committed
154
     *
Sergei Morozov's avatar
Sergei Morozov committed
155
     * @return mixed[][]
156
     */
157
    public static function booleanTypeConversionUsingBooleanTypeProvider() : iterable
158
    {
Sergei Morozov's avatar
Sergei Morozov committed
159
        return [
160
            // statement value, database converted value result
Sergei Morozov's avatar
Sergei Morozov committed
161 162 163 164
            [true, true],
            [false, false],
            [null, false],
        ];
165 166 167 168
    }

    /**
     * Boolean conversion mapping provider
Sergei Morozov's avatar
Sergei Morozov committed
169
     *
Sergei Morozov's avatar
Sergei Morozov committed
170
     * @return mixed[][]
171
     */
172
    public static function booleanTypeConversionWithoutPdoTypeProvider() : iterable
173
    {
Sergei Morozov's avatar
Sergei Morozov committed
174
        return [
175
            // statement value, database converted value result
Sergei Morozov's avatar
Sergei Morozov committed
176 177 178 179
            [true, true],
            [false, false],
            [null, null],
        ];
180
    }
181 182 183 184 185 186 187 188

    private function getPDO() : PDO
    {
        $wrappedConnection = $this->connection->getWrappedConnection();
        assert($wrappedConnection instanceof PDOConnection);

        return $wrappedConnection->getWrappedConnection();
    }
189
}