Passed
Pull Request — 2.9 (#3517)
by
unknown
62:08
created

PDOSqlsrvStatement::bindValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
4
5
use Doctrine\DBAL\Driver\PDOConnection;
6
use Doctrine\DBAL\Driver\PDOStatement;
7
use Doctrine\DBAL\Driver\Statement;
8
use Doctrine\DBAL\Driver\StatementIterator;
9
use Doctrine\DBAL\ParameterType;
10
use IteratorAggregate;
11
use PDO;
12
use function array_key_exists;
13
use function is_numeric;
14
use function stripos;
15
16
/**
17
 * PDO SQL Server Statement
18
 */
19
class PDOSqlsrvStatement implements IteratorAggregate, Statement
20
{
21
    /**
22
     * The PDO Connection.
23
     *
24
     * @var PDOConnection
25
     */
26
    private $conn;
27
28
    /**
29
     * The SQL statement to execute.
30
     *
31
     * @var string
32
     */
33
    private $sql;
34
35
    /**
36
     * The PDO statement.
37
     *
38
     * @var PDOStatement|null
39
     */
40
    private $stmt;
41
42
    /**
43
     * The last insert ID.
44
     *
45
     * @var LastInsertId|null
46
     */
47
    private $lastInsertId;
48
49
    /**
50
     * The affected number of rows
51
     *
52
     * @var int|null
53
     */
54
    private $rowCount;
55
56
    /**
57
     * Append to any INSERT query to retrieve the last insert id.
58
     */
59
    public const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;';
60
61
    /**
62
     * @param string $sql
63
     */
64
    public function __construct(PDOConnection $conn, $sql, ?LastInsertId $lastInsertId = null)
65
    {
66
        $this->conn = $conn;
67
        $this->sql  = $sql;
68
69
        if (stripos($sql, 'INSERT INTO ') === 0) {
70
            $this->sql         .= self::LAST_INSERT_ID_SQL;
71
            $this->lastInsertId = $lastInsertId;
72
        }
73
74
        $this->stmt = $this->prepare();
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function bindValue($param, $value, $type = ParameterType::STRING)
81
    {
82
        return $this->bindParam($param, $value, $type);
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null)
89
    {
90
        if (($type === ParameterType::LARGE_OBJECT || $type === ParameterType::BINARY)
91
            && $driverOptions === null
92
        ) {
93
            $driverOptions = PDO::SQLSRV_ENCODING_BINARY;
94
        }
95
96
        return $this->stmt->bindParam($column, $variable, $type, $length, $driverOptions);
0 ignored issues
show
Bug introduced by
The method bindParam() does not exist on null. ( Ignorable by Annotation )

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

96
        return $this->stmt->/** @scrutinizer ignore-call */ bindParam($column, $variable, $type, $length, $driverOptions);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function closeCursor()
103
    {
104
        return $this->stmt->closeCursor();
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function columnCount()
111
    {
112
        return $this->stmt->columnCount();
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function errorCode()
119
    {
120
        return $this->stmt->errorCode();
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function errorInfo()
127
    {
128
        return $this->stmt->errorInfo();
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function execute($params = null)
135
    {
136
        if ($params) {
137
            $hasZeroIndex = array_key_exists(0, $params);
138
            foreach ($params as $key => $val) {
139
                $key = $hasZeroIndex && is_numeric($key) ? $key + 1 : $key;
140
                $this->bindValue($key, $val);
141
            }
142
        }
143
144
        if (! $this->stmt) {
145
            $this->stmt = $this->prepare();
146
        }
147
148
        $this->stmt->execute($params);
149
        $this->rowCount = $this->rowCount();
150
151
        if (! $this->lastInsertId) {
152
            return;
153
        }
154
155
        $id = null;
156
        $this->stmt->nextRowset();
157
158
        if ($this->columnCount() > 0) {
159
            $id = $this->fetchColumn();
160
        }
161
162
        if (! $id) {
163
            while ($this->stmt->nextRowset()) {
164
                if ($this->columnCount() === 0) {
165
                    continue;
166
                }
167
168
                $id = $this->fetchColumn();
169
            }
170
        }
171
172
        $this->lastInsertId->setId($id);
173
    }
174
175
    /**
176
     * Prepares PDO statement resource
177
     *
178
     * @return PDOStatement
179
     */
180
    private function prepare()
181
    {
182
        return $this->conn->prepare($this->sql);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->conn->prepare($this->sql) returns the type boolean which is incompatible with the documented return type Doctrine\DBAL\Driver\PDOStatement.
Loading history...
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188
    public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
189
    {
190
        return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3);
191
    }
192
193
    /**
194
     * {@inheritdoc}
195
     */
196
    public function getIterator()
197
    {
198
        return new StatementIterator($this);
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204
    public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
205
    {
206
        return $this->stmt->fetch($fetchMode, $cursorOrientation, $cursorOffset);
207
    }
208
209
    /**
210
     * {@inheritdoc}
211
     */
212
    public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
213
    {
214
        return $this->stmt->fetchAll($fetchMode, $fetchArgument, $ctorArgs);
215
    }
216
217
    /**
218
     * {@inheritdoc}
219
     */
220
    public function fetchColumn($columnIndex = 0)
221
    {
222
        return $this->stmt->fetchColumn($columnIndex);
223
    }
224
225
    /**
226
     * {@inheritdoc}
227
     */
228
    public function rowCount()
229
    {
230
        return $this->rowCount ?: $this->stmt->rowCount();
231
    }
232
}
233