Failed Conditions
Pull Request — master (#3973)
by Grégoire
03:04
created

Statement::getIterator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL;
6
7
use Doctrine\DBAL\Driver\DriverException;
8
use Doctrine\DBAL\Driver\Statement as DriverStatement;
9
use Doctrine\DBAL\Platforms\AbstractPlatform;
10
use Doctrine\DBAL\Types\Type;
11
use IteratorAggregate;
12
use Throwable;
13
use function is_string;
14
15
/**
16
 * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
17
 * for logging, DBAL mapping types, etc.
18
 */
19
class Statement implements IteratorAggregate, DriverStatement
20
{
21
    /**
22
     * The SQL statement.
23
     *
24
     * @var string
25
     */
26
    protected $sql;
27
28
    /**
29
     * The bound parameters.
30
     *
31
     * @var mixed[]
32
     */
33
    protected $params = [];
34
35
    /**
36
     * The parameter types.
37
     *
38
     * @var int[]|string[]|Type[]
39
     */
40
    protected $types = [];
41
42
    /**
43
     * The underlying driver statement.
44
     *
45
     * @var DriverStatement
46
     */
47
    protected $stmt;
48
49
    /**
50
     * The underlying database platform.
51
     *
52
     * @var AbstractPlatform
53
     */
54
    protected $platform;
55
56
    /**
57
     * The connection this statement is bound to and executed on.
58
     *
59
     * @var Connection
60
     */
61
    protected $conn;
62
63
    /**
64
     * Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>.
65
     *
66
     * @param string     $sql  The SQL of the statement.
67
     * @param Connection $conn The connection on which the statement should be executed.
68
     */
69 1883
    public function __construct(string $sql, Connection $conn)
70
    {
71 1883
        $this->sql      = $sql;
72 1883
        $this->stmt     = $conn->getWrappedConnection()->prepare($sql);
73 1862
        $this->conn     = $conn;
74 1862
        $this->platform = $conn->getDatabasePlatform();
75 1862
    }
76
77
    /**
78
     * Binds a parameter value to the statement.
79
     *
80
     * The value can optionally be bound with a PDO binding type or a DBAL mapping type.
81
     * If bound with a DBAL mapping type, the binding type is derived from the mapping
82
     * type and the value undergoes the conversion routines of the mapping type before
83
     * being bound.
84
     *
85
     * @param string|int      $param Parameter identifier. For a prepared statement using named placeholders,
86
     *                               this will be a parameter name of the form :name. For a prepared statement
87
     *                               using question mark placeholders, this will be the 1-indexed position
88
     *                               of the parameter.
89
     * @param mixed           $value The value to bind to the parameter.
90
     * @param string|int|Type $type  Either one of the constants defined in {@link \Doctrine\DBAL\ParameterType}
91
     *                               or a DBAL mapping type name or instance.
92
     *
93
     * @throws DBALException
94
     * @throws DriverException
95
     */
96 203
    public function bindValue($param, $value, $type = ParameterType::STRING) : void
97
    {
98 203
        $this->params[$param] = $value;
99 203
        $this->types[$param]  = $type;
100
101 203
        if (is_string($type)) {
102 21
            $type = Type::getType($type);
103
        }
104
105 203
        if ($type instanceof Type) {
106 21
            $value       = $type->convertToDatabaseValue($value, $this->platform);
107 21
            $bindingType = $type->getBindingType();
108
        } else {
109 182
            $bindingType = $type;
110
        }
111
112 203
        $this->stmt->bindValue($param, $value, $bindingType);
113 203
    }
114
115
    /**
116
     * Binds a parameter to a value by reference.
117
     *
118
     * Binding a parameter by reference does not support DBAL mapping types.
119
     *
120
     * @param string|int $param    Parameter identifier. For a prepared statement using named placeholders,
121
     *                             this will be a parameter name of the form :name. For a prepared statement
122
     *                             using question mark placeholders, this will be the 1-indexed position
123
     *                             of the parameter.
124
     * @param mixed      $variable The variable to bind to the parameter.
125
     * @param int        $type     The PDO binding type.
126
     * @param int|null   $length   Must be specified when using an OUT bind
127
     *                             so that PHP allocates enough memory to hold the returned value.
128
     *
129
     * @throws DriverException
130
     */
131 524
    public function bindParam($param, &$variable, int $type = ParameterType::STRING, ?int $length = null) : void
132
    {
133 524
        $this->params[$param] = $variable;
134 524
        $this->types[$param]  = $type;
135
136 524
        $this->stmt->bindParam($param, $variable, $type, $length);
137 524
    }
138
139
    /**
140
     * {@inheritDoc}
141
     *
142
     * @throws DBALException
143
     */
144 1715
    public function execute(?array $params = null) : void
145
    {
146 1715
        if ($params !== null) {
147 104
            $this->params = $params;
148
        }
149
150 1715
        $logger = $this->conn->getConfiguration()->getSQLLogger();
151 1715
        $logger->startQuery($this->sql, $this->params, $this->types);
152
153
        try {
154 1715
            $this->stmt->execute($params);
155 34
        } catch (Throwable $ex) {
156 34
            throw DBALException::driverExceptionDuringQuery(
157 34
                $this->conn->getDriver(),
158 34
                $ex,
159 34
                $this->sql,
160 34
                $this->conn->resolveParams($this->params, $this->types)
161
            );
162 1681
        } finally {
163 1715
            $logger->stopQuery();
164
        }
165
166 1681
        $this->params = [];
167 1681
        $this->types  = [];
168 1681
    }
169
170 168
    public function closeCursor() : void
171
    {
172 168
        $this->stmt->closeCursor();
173 168
    }
174
175
    /**
176
     * Returns the number of columns in the result set.
177
     */
178
    public function columnCount() : int
179
    {
180
        return $this->stmt->columnCount();
181
    }
182
183 1778
    public function setFetchMode(int $fetchMode) : void
184
    {
185 1778
        $this->stmt->setFetchMode($fetchMode);
186 1778
    }
187
188
    /**
189
     * Required by interface IteratorAggregate.
190
     *
191
     * {@inheritdoc}
192
     */
193 21
    public function getIterator()
194
    {
195 21
        return $this->stmt;
196
    }
197
198
    /**
199
     * {@inheritdoc}
200
     */
201 196
    public function fetch(?int $fetchMode = null)
202
    {
203 196
        return $this->stmt->fetch($fetchMode);
204
    }
205
206
    /**
207
     * {@inheritdoc}
208
     */
209 126
    public function fetchAll(?int $fetchMode = null) : array
210
    {
211 126
        return $this->stmt->fetchAll($fetchMode);
212
    }
213
214
    /**
215
     * {@inheritDoc}
216
     */
217 1281
    public function fetchColumn()
218
    {
219 1281
        return $this->stmt->fetchColumn();
220
    }
221
222
    /**
223
     * Returns the number of rows affected by the last execution of this statement.
224
     *
225
     * @return int The number of affected rows.
226
     */
227 84
    public function rowCount() : int
228
    {
229 84
        return $this->stmt->rowCount();
230
    }
231
232
    /**
233
     * Gets the wrapped driver statement.
234
     */
235
    public function getWrappedStatement() : DriverStatement
236
    {
237
        return $this->stmt;
238
    }
239
}
240