Passed
Pull Request — 3.0.x (#4000)
by Grégoire
08:27
created

Statement   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 258
Duplicated Lines 0 %

Test Coverage

Coverage 85.94%

Importance

Changes 0
Metric Value
eloc 56
dl 0
loc 258
ccs 55
cts 64
cp 0.8594
rs 10
c 0
b 0
f 0
wmc 23

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A fetch() 0 3 1
A bindValue() 0 20 4
A errorInfo() 0 3 1
A fetchAll() 0 3 1
A getIterator() 0 3 1
A columnCount() 0 3 1
A rowCount() 0 3 1
A setFetchMode() 0 3 1
A closeCursor() 0 3 1
A fetchColumn() 0 3 1
B execute() 0 34 6
A bindParam() 0 6 1
A errorCode() 0 3 1
A getWrappedStatement() 0 3 1
1
<?php
2
3
namespace Doctrine\DBAL;
4
5
use Doctrine\DBAL\Driver\Statement as DriverStatement;
6
use Doctrine\DBAL\Platforms\AbstractPlatform;
7
use Doctrine\DBAL\Types\Type;
8
use IteratorAggregate;
9
use Throwable;
10
use function is_string;
11
12
/**
13
 * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
14
 * for logging, DBAL mapping types, etc.
15
 */
16
class Statement implements IteratorAggregate, DriverStatement
17
{
18
    /**
19
     * The SQL statement.
20
     *
21
     * @var string
22
     */
23
    protected $sql;
24
25
    /**
26
     * The bound parameters.
27
     *
28
     * @var mixed[]
29
     */
30
    protected $params = [];
31
32
    /**
33
     * The parameter types.
34
     *
35
     * @var int[]|string[]
36
     */
37
    protected $types = [];
38
39
    /**
40
     * The underlying driver statement.
41
     *
42
     * @var \Doctrine\DBAL\Driver\Statement
43
     */
44
    protected $stmt;
45
46
    /**
47
     * The underlying database platform.
48
     *
49
     * @var AbstractPlatform
50
     */
51
    protected $platform;
52
53
    /**
54
     * The connection this statement is bound to and executed on.
55
     *
56
     * @var Connection
57
     */
58
    protected $conn;
59
60
    /**
61
     * Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>.
62
     *
63
     * @param string     $sql  The SQL of the statement.
64
     * @param Connection $conn The connection on which the statement should be executed.
65
     */
66 1043
    public function __construct($sql, Connection $conn)
67
    {
68 1043
        $this->sql      = $sql;
69 1043
        $this->stmt     = $conn->getWrappedConnection()->prepare($sql);
70 1019
        $this->conn     = $conn;
71 1019
        $this->platform = $conn->getDatabasePlatform();
72 1019
    }
73
74
    /**
75
     * Binds a parameter value to the statement.
76
     *
77
     * The value can optionally be bound with a PDO binding type or a DBAL mapping type.
78
     * If bound with a DBAL mapping type, the binding type is derived from the mapping
79
     * type and the value undergoes the conversion routines of the mapping type before
80
     * being bound.
81
     *
82
     * @param string|int $name  The name or position of the parameter.
83
     * @param mixed      $value The value of the parameter.
84
     * @param mixed      $type  Either a PDO binding type or a DBAL mapping type name or instance.
85
     *
86
     * @return bool TRUE on success, FALSE on failure.
87
     */
88 227
    public function bindValue($name, $value, $type = ParameterType::STRING)
89
    {
90 227
        $this->params[$name] = $value;
91 227
        $this->types[$name]  = $type;
92 227
        if ($type !== null) {
93 227
            if (is_string($type)) {
94 48
                $type = Type::getType($type);
95
            }
96
97 227
            if ($type instanceof Type) {
98 72
                $value       = $type->convertToDatabaseValue($value, $this->platform);
99 72
                $bindingType = $type->getBindingType();
100
            } else {
101 155
                $bindingType = $type;
102
            }
103
104 227
            return $this->stmt->bindValue($name, $value, $bindingType);
0 ignored issues
show
Bug introduced by
It seems like $bindingType can also be of type Doctrine\DBAL\Types\Type; however, parameter $type of Doctrine\DBAL\Driver\Statement::bindValue() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

104
            return $this->stmt->bindValue($name, $value, /** @scrutinizer ignore-type */ $bindingType);
Loading history...
105
        }
106
107
        return $this->stmt->bindValue($name, $value);
108
    }
109
110
    /**
111
     * Binds a parameter to a value by reference.
112
     *
113
     * Binding a parameter by reference does not support DBAL mapping types.
114
     *
115
     * @param string|int $name   The name or position of the parameter.
116
     * @param mixed      $var    The reference to the variable to bind.
117
     * @param int        $type   The PDO binding type.
118
     * @param int|null   $length Must be specified when using an OUT bind
119
     *                           so that PHP allocates enough memory to hold the returned value.
120
     *
121
     * @return bool TRUE on success, FALSE on failure.
122
     */
123 215
    public function bindParam($name, &$var, $type = ParameterType::STRING, $length = null)
124
    {
125 215
        $this->params[$name] = $var;
126 215
        $this->types[$name]  = $type;
127
128 215
        return $this->stmt->bindParam($name, $var, $type, $length);
129
    }
130
131
    /**
132
     * Executes the statement with the currently bound parameters.
133
     *
134
     * @param mixed[]|null $params
135
     *
136
     * @return bool TRUE on success, FALSE on failure.
137
     *
138
     * @throws DBALException
139
     */
140 827
    public function execute($params = null)
141
    {
142 827
        if ($params !== null) {
143 103
            $this->params = $params;
144
        }
145
146 827
        $logger = $this->conn->getConfiguration()->getSQLLogger();
147 827
        if ($logger !== null) {
148 827
            $logger->startQuery($this->sql, $this->params, $this->types);
149
        }
150
151
        try {
152 827
            $stmt = $this->stmt->execute($params);
153 24
        } catch (Throwable $ex) {
154 24
            if ($logger !== null) {
155 24
                $logger->stopQuery();
156
            }
157
158 24
            throw DBALException::driverExceptionDuringQuery(
159 24
                $this->conn->getDriver(),
160 24
                $ex,
161 24
                $this->sql,
162 24
                $this->conn->resolveParams($this->params, $this->types)
163
            );
164
        }
165
166 803
        if ($logger !== null) {
167 803
            $logger->stopQuery();
168
        }
169
170 803
        $this->params = [];
171 803
        $this->types  = [];
172
173 803
        return $stmt;
174
    }
175
176
    /**
177
     * Closes the cursor, freeing the database resources used by this statement.
178
     *
179
     * @return bool TRUE on success, FALSE on failure.
180
     */
181 256
    public function closeCursor()
182
    {
183 256
        return $this->stmt->closeCursor();
184
    }
185
186
    /**
187
     * Returns the number of columns in the result set.
188
     *
189
     * @return int
190
     */
191
    public function columnCount()
192
    {
193
        return $this->stmt->columnCount();
194
    }
195
196
    /**
197
     * Fetches the SQLSTATE associated with the last operation on the statement.
198
     *
199
     * @return string|int|bool
200
     */
201
    public function errorCode()
202
    {
203
        return $this->stmt->errorCode();
204
    }
205
206
    /**
207
     * {@inheritDoc}
208
     */
209
    public function errorInfo()
210
    {
211
        return $this->stmt->errorInfo();
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217 923
    public function setFetchMode($fetchMode)
218
    {
219 923
        return $this->stmt->setFetchMode($fetchMode);
220
    }
221
222
    /**
223
     * Required by interface IteratorAggregate.
224
     *
225
     * {@inheritdoc}
226
     */
227 24
    public function getIterator()
228
    {
229 24
        return $this->stmt;
230
    }
231
232
    /**
233
     * {@inheritdoc}
234
     */
235 247
    public function fetch($fetchMode = null)
236
    {
237 247
        return $this->stmt->fetch($fetchMode);
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243 144
    public function fetchAll($fetchMode = null)
244
    {
245 144
        return $this->stmt->fetchAll($fetchMode);
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     */
251 328
    public function fetchColumn()
252
    {
253 328
        return $this->stmt->fetchColumn();
254
    }
255
256
    /**
257
     * Returns the number of rows affected by the last execution of this statement.
258
     *
259
     * @return int The number of affected rows.
260
     */
261 96
    public function rowCount() : int
262
    {
263 96
        return $this->stmt->rowCount();
264
    }
265
266
    /**
267
     * Gets the wrapped driver statement.
268
     *
269
     * @return \Doctrine\DBAL\Driver\Statement
270
     */
271
    public function getWrappedStatement()
272
    {
273
        return $this->stmt;
274
    }
275
}
276