Passed
Push — drop-deprecated ( db0b1f )
by Michael
27:00
created

PDOStatement   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Test Coverage

Coverage 78.21%

Importance

Changes 0
Metric Value
wmc 29
eloc 84
dl 0
loc 221
ccs 61
cts 78
cp 0.7821
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A bindValue() 0 8 2
A setFetchMode() 0 8 2
A bindParam() 0 13 3
A __construct() 0 3 1
A columnCount() 0 3 1
A closeCursor() 0 3 1
A execute() 0 6 2
A convertFetchMode() 0 14 2
A rowCount() 0 3 1
A getIterator() 0 3 1
A convertParamType() 0 13 2
A fetch() 0 12 3
A fetchColumn() 0 16 5
A fetchAll() 0 18 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Driver;
6
7
use Doctrine\DBAL\DBALException;
8
use Doctrine\DBAL\FetchMode;
9
use Doctrine\DBAL\ParameterType;
10
use IteratorAggregate;
11
use PDO;
12
use const E_USER_DEPRECATED;
13
use function array_slice;
14
use function assert;
15
use function count;
16
use function func_get_args;
17
use function is_array;
18
use function sprintf;
19
use function trigger_error;
20
21
/**
22
 * The PDO implementation of the Statement interface.
23
 * Used by all PDO-based drivers.
24
 */
25
class PDOStatement implements IteratorAggregate, Statement
26
{
27
    private const PARAM_TYPE_MAP = [
28
        ParameterType::NULL         => PDO::PARAM_NULL,
29
        ParameterType::INTEGER      => PDO::PARAM_INT,
30
        ParameterType::STRING       => PDO::PARAM_STR,
31
        ParameterType::BINARY       => PDO::PARAM_LOB,
32
        ParameterType::LARGE_OBJECT => PDO::PARAM_LOB,
33
        ParameterType::BOOLEAN      => PDO::PARAM_BOOL,
34
    ];
35
36
    private const FETCH_MODE_MAP = [
37
        FetchMode::ASSOCIATIVE     => PDO::FETCH_ASSOC,
38
        FetchMode::NUMERIC         => PDO::FETCH_NUM,
39
        FetchMode::MIXED           => PDO::FETCH_BOTH,
40
        FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ,
41
        FetchMode::COLUMN          => PDO::FETCH_COLUMN,
42
        FetchMode::CUSTOM_OBJECT   => PDO::FETCH_CLASS,
43
    ];
44
45
    /** @var \PDOStatement */
46
    private $stmt;
47
48 4282
    public function __construct(\PDOStatement $stmt)
49
    {
50 4282
        $this->stmt = $stmt;
51 4282
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 4267
    public function setFetchMode($fetchMode, ...$args) : void
57
    {
58 4267
        $fetchMode = $this->convertFetchMode($fetchMode);
59
60
        try {
61 4267
            $this->stmt->setFetchMode($fetchMode, ...$args);
62
        } catch (\PDOException $exception) {
63
            throw new PDOException($exception);
64
        }
65 4267
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70 3987
    public function bindValue($param, $value, $type = ParameterType::STRING) : void
71
    {
72 3987
        $type = $this->convertParamType($type);
73
74
        try {
75 3987
            $this->stmt->bindValue($param, $value, $type);
76
        } catch (\PDOException $exception) {
77
            throw new PDOException($exception);
78
        }
79 3987
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84 4176
    public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null) : void
85
    {
86 4176
        $type            = $this->convertParamType($type);
87 4176
        $extraParameters = array_slice(func_get_args(), 3);
88
89 4176
        if (count($extraParameters) !== 0) {
90 4176
            $extraParameters[0] = $extraParameters[0] ?? 0;
91
        }
92
93
        try {
94 4176
            $this->stmt->bindParam($column, $variable, $type, ...$extraParameters);
0 ignored issues
show
Bug introduced by
$extraParameters is expanded, but the parameter $length of PDOStatement::bindParam() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
            $this->stmt->bindParam($column, $variable, $type, /** @scrutinizer ignore-type */ ...$extraParameters);
Loading history...
95
        } catch (\PDOException $exception) {
96
            throw new PDOException($exception);
97
        }
98 4176
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 2029
    public function closeCursor() : void
104
    {
105 2029
        $this->stmt->closeCursor();
106 2029
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111 2667
    public function columnCount()
112
    {
113 2667
        return $this->stmt->columnCount();
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 4273
    public function execute($params = null) : void
120
    {
121
        try {
122 4273
            $this->stmt->execute($params);
123 3976
        } catch (\PDOException $exception) {
124 2686
            throw new PDOException($exception);
125
        }
126 4273
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131 4246
    public function rowCount() : int
132
    {
133 4246
        return $this->stmt->rowCount();
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 4111
    public function fetch($fetchMode = null, ...$args)
140
    {
141
        try {
142 4111
            if ($fetchMode === null) {
143 3946
                return $this->stmt->fetch();
144
            }
145
146 4111
            $fetchMode = $this->convertFetchMode($fetchMode);
147
148 4111
            return $this->stmt->fetch($fetchMode, ...$args);
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $cursor_orientation of PDOStatement::fetch() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

148
            return $this->stmt->fetch($fetchMode, /** @scrutinizer ignore-type */ ...$args);
Loading history...
149
        } catch (\PDOException $exception) {
150
            throw new PDOException($exception);
151
        }
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 4267
    public function fetchAll($fetchMode = null, ...$args)
158
    {
159
        try {
160 4267
            if ($fetchMode === null) {
161 4042
                $data = $this->stmt->fetchAll();
162
            } else {
163 4258
                $data = $this->stmt->fetchAll(
164 4258
                    $this->convertFetchMode($fetchMode),
165 4267
                    ...$args
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $fetch_argument of PDOStatement::fetchAll() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
                    /** @scrutinizer ignore-type */ ...$args
Loading history...
166
                );
167
            }
168
        } catch (\PDOException $exception) {
169
            throw new PDOException($exception);
170
        }
171
172 4267
        assert(is_array($data));
173
174 4267
        return $data;
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 4093
    public function fetchColumn($columnIndex = 0)
181
    {
182
        try {
183 4093
            $value = $this->stmt->fetchColumn($columnIndex);
184
185 4093
            if ($value === null) {
186 2667
                $columnCount = $this->columnCount();
187
188 2667
                if ($columnIndex < 0 || $columnIndex >= $columnCount) {
189
                    throw DBALException::invalidColumnIndex($columnIndex, $columnCount);
190
                }
191
            }
192
193 4093
            return $value;
194
        } catch (\PDOException $exception) {
195
            throw new PDOException($exception);
196
        }
197
    }
198
199
    /**
200
     * Converts DBAL parameter type to PDO parameter type
201
     *
202
     * @param int $type Parameter type
203
     */
204 4246
    private function convertParamType(int $type) : int
205
    {
206 4246
        if (! isset(self::PARAM_TYPE_MAP[$type])) {
207
            // TODO: next major: throw an exception
208
            @trigger_error(sprintf(
209
                'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0',
210
                $type
211
            ), E_USER_DEPRECATED);
212
213
            return $type;
214
        }
215
216 4246
        return self::PARAM_TYPE_MAP[$type];
217
    }
218
219
    /**
220
     * Converts DBAL fetch mode to PDO fetch mode
221
     *
222
     * @param int $fetchMode Fetch mode
223
     */
224 4267
    private function convertFetchMode(int $fetchMode) : int
225
    {
226 4267
        if (! isset(self::FETCH_MODE_MAP[$fetchMode])) {
227
            // TODO: next major: throw an exception
228 2167
            @trigger_error(sprintf(
229
                'Using a PDO fetch mode or their combination (%d given)' .
230
                ' is deprecated and will cause an error in Doctrine 3.0',
231 2167
                $fetchMode
232 2167
            ), E_USER_DEPRECATED);
233
234 2167
            return $fetchMode;
235
        }
236
237 4267
        return self::FETCH_MODE_MAP[$fetchMode];
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243 4051
    public function getIterator()
244
    {
245 4051
        yield from $this->stmt;
246 4051
    }
247
}
248