Completed
Push — master ( 6d673d...7f4ef4 )
by Sergei
40:47 queued 40:43
created

Statement::bindValue()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

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