Failed Conditions
Pull Request — master (#3074)
by Sergei
15:08
created

PDOStatement::convertFetchMode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 3
nop 1
crap 3.0416
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Driver;
21
22
use Doctrine\DBAL\FetchMode;
23
use Doctrine\DBAL\ParameterType;
24
use PDO;
25
26
/**
27
 * The PDO implementation of the Statement interface.
28
 * Used by all PDO-based drivers.
29
 *
30
 * @since 2.0
31
 */
32
class PDOStatement extends \PDOStatement implements Statement
33
{
34
    /**
35
     * @var int[]
36
     */
37
    private const PARAM_TYPE_MAP = [
38
        ParameterType::NULL         => PDO::PARAM_NULL,
39
        ParameterType::INTEGER      => PDO::PARAM_INT,
40
        ParameterType::STRING       => PDO::PARAM_STR,
41
        ParameterType::LARGE_OBJECT => PDO::PARAM_LOB,
42
        ParameterType::BOOLEAN      => PDO::PARAM_BOOL,
43
    ];
44
45
    /**
46
     * @var int[]
47
     */
48
    private const FETCH_MODE_MAP = [
49
        FetchMode::ASSOCIATIVE     => PDO::FETCH_ASSOC,
50
        FetchMode::NUMERIC         => PDO::FETCH_NUM,
51
        FetchMode::MIXED           => PDO::FETCH_BOTH,
52
        FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ,
53
        FetchMode::COLUMN          => PDO::FETCH_COLUMN,
54
        FetchMode::CUSTOM_OBJECT   => PDO::FETCH_CLASS,
55
    ];
56
57
    /**
58
     * @var PDOConnection|null
59
     */
60
    private $connection;
61
62
    /**
63
     * Protected constructor.
64
     *
65
     * @param PDOConnection|null $connection
66
     *
67
     * @todo do we need to keep BC here? Or can we make $connection mandatory?
68
     */
69 257
    protected function __construct(PDOConnection $connection = null)
70
    {
71 257
        $this->connection = $connection;
72 257
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 227
    public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
78
    {
79 227
        $fetchMode = $this->convertFetchMode($fetchMode);
80
81
        // This thin wrapper is necessary to shield against the weird signature
82
        // of PDOStatement::setFetchMode(): even if the second and third
83
        // parameters are optional, PHP will not let us remove it from this
84
        // declaration.
85
        try {
86 227
            if ($arg2 === null && $arg3 === null) {
87 227
                return parent::setFetchMode($fetchMode);
88
            }
89
90 2
            if ($arg3 === null) {
91 2
                return parent::setFetchMode($fetchMode, $arg2);
92
            }
93
94
            return parent::setFetchMode($fetchMode, $arg2, $arg3);
95
        } catch (\PDOException $exception) {
96
            throw new PDOException($exception);
97
        }
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 33
    public function bindValue($param, $value, $type = ParameterType::STRING)
104
    {
105 33
        $type = $this->convertParamType($type);
106
107
        try {
108 33
            return parent::bindValue($param, $value, $type);
109
        } catch (\PDOException $exception) {
110
            throw new PDOException($exception);
111
        }
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 7
    public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null)
118
    {
119 7
        $type = $this->convertParamType($type);
120
121
        try {
122 7
            return parent::bindParam($column, $variable, $type, $length, $driverOptions);
123
        } catch (\PDOException $exception) {
124
            throw new PDOException($exception);
125
        }
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131 20
    public function closeCursor()
132
    {
133
        try {
134 20
            return parent::closeCursor();
135
        } catch (\PDOException $exception) {
136
            // Exceptions not allowed by the interface.
137
            // In case driver implementations do not adhere to the interface, silence exceptions here.
138
            return true;
139
        }
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145 133
    public function execute($params = null)
146
    {
147
        try {
148 133
            $result = parent::execute($params);
149
150 128
            if ($this->connection) {
151 128
                $this->connection->trackLastInsertId();
152
            }
153
154 128
            return $result;
155 7
        } catch (\PDOException $exception) {
156 3
            throw new PDOException($exception);
157
        }
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 68
    public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
164
    {
165 68
        $fetchMode = $this->convertFetchMode($fetchMode);
166
167
        try {
168 68
            if ($fetchMode === null && \PDO::FETCH_ORI_NEXT === $cursorOrientation && 0 === $cursorOffset) {
169 9
                return parent::fetch();
170
            }
171
172 59
            if (\PDO::FETCH_ORI_NEXT === $cursorOrientation && 0 === $cursorOffset) {
173 59
                return parent::fetch($fetchMode);
174
            }
175
176
            if (0 === $cursorOffset) {
177
                return parent::fetch($fetchMode, $cursorOrientation);
178
            }
179
180
            return parent::fetch($fetchMode, $cursorOrientation, $cursorOffset);
181
        } catch (\PDOException $exception) {
182
            throw new PDOException($exception);
183
        }
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 101
    public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
190
    {
191 101
        $fetchMode = $this->convertFetchMode($fetchMode);
192
193
        try {
194 101
            if ($fetchMode === null && null === $fetchArgument && null === $ctorArgs) {
195 88
                return parent::fetchAll();
196
            }
197
198 54
            if (null === $fetchArgument && null === $ctorArgs) {
199 53
                return parent::fetchAll($fetchMode);
200
            }
201
202 1
            if (null === $ctorArgs) {
203 1
                return parent::fetchAll($fetchMode, $fetchArgument);
204
            }
205
206
            return parent::fetchAll($fetchMode, $fetchArgument, $ctorArgs);
207
        } catch (\PDOException $exception) {
208
            throw new PDOException($exception);
209
        }
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215 43
    public function fetchColumn($columnIndex = 0)
216
    {
217
        try {
218 43
            return parent::fetchColumn($columnIndex);
219
        } catch (\PDOException $exception) {
220
            throw new PDOException($exception);
221
        }
222
    }
223
224
    /**
225
     * Converts DBAL parameter type to PDO parameter type
226
     *
227
     * @param int $type Parameter type
228
     */
229 40
    private function convertParamType(int $type) : int
230
    {
231 40
        if (! isset(self::PARAM_TYPE_MAP[$type])) {
232
            throw new \InvalidArgumentException('Invalid parameter type: ' . $type);
233
        }
234
235 40
        return self::PARAM_TYPE_MAP[$type];
236
    }
237
238
    /**
239
     * Converts DBAL fetch mode to PDO fetch mode
240
     *
241
     * @param int|null $fetchMode Fetch mode
242
     */
243 227
    private function convertFetchMode(?int $fetchMode) : ?int
244
    {
245 227
        if ($fetchMode === null) {
246 97
            return null;
247
        }
248
249 227
        if (! isset(self::FETCH_MODE_MAP[$fetchMode])) {
250
            throw new \InvalidArgumentException('Invalid fetch mode: ' . $fetchMode);
251
        }
252
253 227
        return self::FETCH_MODE_MAP[$fetchMode];
254
    }
255
}
256