1 | <?php |
||||||
2 | /* |
||||||
3 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
4 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
5 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
6 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
7 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
8 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
9 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
10 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
11 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
12 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
13 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
14 | * |
||||||
15 | * This software consists of voluntary contributions made by many individuals |
||||||
16 | * and is licensed under the MIT license. For more information, see |
||||||
17 | * <http://www.doctrine-project.org>. |
||||||
18 | */ |
||||||
19 | |||||||
20 | namespace Doctrine\DBAL\Driver\IBMDB2; |
||||||
21 | |||||||
22 | use Doctrine\DBAL\Driver\Statement; |
||||||
23 | use Doctrine\DBAL\Driver\StatementIterator; |
||||||
24 | |||||||
25 | class DB2Statement implements \IteratorAggregate, Statement |
||||||
26 | { |
||||||
27 | /** |
||||||
28 | * @var resource |
||||||
29 | */ |
||||||
30 | private $_stmt; |
||||||
31 | |||||||
32 | /** |
||||||
33 | * @var array |
||||||
34 | */ |
||||||
35 | private $_bindParam = []; |
||||||
36 | |||||||
37 | /** |
||||||
38 | * @var string Name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. |
||||||
39 | */ |
||||||
40 | private $defaultFetchClass = '\stdClass'; |
||||||
41 | |||||||
42 | /** |
||||||
43 | * @var string Constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. |
||||||
44 | */ |
||||||
45 | private $defaultFetchClassCtorArgs = []; |
||||||
46 | |||||||
47 | /** |
||||||
48 | * @var integer |
||||||
49 | */ |
||||||
50 | private $_defaultFetchMode = \PDO::FETCH_BOTH; |
||||||
51 | |||||||
52 | /** |
||||||
53 | * Indicates whether the statement is in the state when fetching results is possible |
||||||
54 | * |
||||||
55 | * @var bool |
||||||
56 | */ |
||||||
57 | private $result = false; |
||||||
58 | |||||||
59 | /** |
||||||
60 | * DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG |
||||||
61 | * |
||||||
62 | * @var array |
||||||
63 | */ |
||||||
64 | static private $_typeMap = [ |
||||||
65 | \PDO::PARAM_INT => DB2_LONG, |
||||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
66 | \PDO::PARAM_STR => DB2_CHAR, |
||||||
0 ignored issues
–
show
|
|||||||
67 | ]; |
||||||
68 | |||||||
69 | /** |
||||||
70 | * @param resource $stmt |
||||||
71 | */ |
||||||
72 | public function __construct($stmt) |
||||||
73 | { |
||||||
74 | $this->_stmt = $stmt; |
||||||
75 | } |
||||||
76 | |||||||
77 | /** |
||||||
78 | * {@inheritdoc} |
||||||
79 | */ |
||||||
80 | public function bindValue($param, $value, $type = null) |
||||||
81 | { |
||||||
82 | return $this->bindParam($param, $value, $type); |
||||||
83 | } |
||||||
84 | |||||||
85 | /** |
||||||
86 | * {@inheritdoc} |
||||||
87 | */ |
||||||
88 | public function bindParam($column, &$variable, $type = null, $length = null) |
||||||
89 | { |
||||||
90 | $this->_bindParam[$column] =& $variable; |
||||||
91 | |||||||
92 | if ($type && isset(self::$_typeMap[$type])) { |
||||||
93 | $type = self::$_typeMap[$type]; |
||||||
94 | } else { |
||||||
95 | $type = DB2_CHAR; |
||||||
0 ignored issues
–
show
|
|||||||
96 | } |
||||||
97 | |||||||
98 | if (!db2_bind_param($this->_stmt, $column, "variable", DB2_PARAM_IN, $type)) { |
||||||
0 ignored issues
–
show
The function
db2_bind_param was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
99 | throw new DB2Exception(db2_stmt_errormsg()); |
||||||
0 ignored issues
–
show
The function
db2_stmt_errormsg was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
100 | } |
||||||
101 | |||||||
102 | return true; |
||||||
103 | } |
||||||
104 | |||||||
105 | /** |
||||||
106 | * {@inheritdoc} |
||||||
107 | */ |
||||||
108 | public function closeCursor() |
||||||
109 | { |
||||||
110 | if ( ! $this->_stmt) { |
||||||
111 | return false; |
||||||
112 | } |
||||||
113 | |||||||
114 | $this->_bindParam = []; |
||||||
115 | |||||||
116 | if (!db2_free_result($this->_stmt)) { |
||||||
0 ignored issues
–
show
The function
db2_free_result was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
117 | return false; |
||||||
118 | } |
||||||
119 | |||||||
120 | $this->result = false; |
||||||
121 | |||||||
122 | return true; |
||||||
123 | } |
||||||
124 | |||||||
125 | /** |
||||||
126 | * {@inheritdoc} |
||||||
127 | */ |
||||||
128 | public function columnCount() |
||||||
129 | { |
||||||
130 | if ( ! $this->_stmt) { |
||||||
131 | return false; |
||||||
0 ignored issues
–
show
The expression
return false returns the type false which is incompatible with the return type mandated by Doctrine\DBAL\Driver\Res...tatement::columnCount() of integer .
In the issue above, the returned value is violating the contract defined by the mentioned interface. Let's take a look at an example: interface HasName {
/** @return string */
public function getName();
}
class Name {
public $name;
}
class User implements HasName {
/** @return string|Name */
public function getName() {
return new Name('foo'); // This is a violation of the ``HasName`` interface
// which only allows a string value to be returned.
}
}
Loading history...
|
|||||||
132 | } |
||||||
133 | |||||||
134 | return db2_num_fields($this->_stmt); |
||||||
0 ignored issues
–
show
The function
db2_num_fields was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
135 | } |
||||||
136 | |||||||
137 | /** |
||||||
138 | * {@inheritdoc} |
||||||
139 | */ |
||||||
140 | public function errorCode() |
||||||
141 | { |
||||||
142 | return db2_stmt_error(); |
||||||
0 ignored issues
–
show
The function
db2_stmt_error was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
143 | } |
||||||
144 | |||||||
145 | /** |
||||||
146 | * {@inheritdoc} |
||||||
147 | */ |
||||||
148 | public function errorInfo() |
||||||
149 | { |
||||||
150 | return [ |
||||||
151 | db2_stmt_errormsg(), |
||||||
0 ignored issues
–
show
The function
db2_stmt_errormsg was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
152 | db2_stmt_error(), |
||||||
0 ignored issues
–
show
The function
db2_stmt_error was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
153 | ]; |
||||||
154 | } |
||||||
155 | |||||||
156 | /** |
||||||
157 | * {@inheritdoc} |
||||||
158 | */ |
||||||
159 | public function execute($params = null) |
||||||
160 | { |
||||||
161 | if ( ! $this->_stmt) { |
||||||
162 | return false; |
||||||
163 | } |
||||||
164 | |||||||
165 | if ($params === null) { |
||||||
166 | ksort($this->_bindParam); |
||||||
167 | |||||||
168 | $params = []; |
||||||
169 | |||||||
170 | foreach ($this->_bindParam as $column => $value) { |
||||||
171 | $params[] = $value; |
||||||
172 | } |
||||||
173 | } |
||||||
174 | |||||||
175 | $retval = @db2_execute($this->_stmt, $params); |
||||||
0 ignored issues
–
show
The function
db2_execute was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
176 | |||||||
177 | if ($retval === false) { |
||||||
178 | throw new DB2Exception(db2_stmt_errormsg()); |
||||||
0 ignored issues
–
show
The function
db2_stmt_errormsg was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
179 | } |
||||||
180 | |||||||
181 | $this->result = true; |
||||||
182 | |||||||
183 | return $retval; |
||||||
184 | } |
||||||
185 | |||||||
186 | /** |
||||||
187 | * {@inheritdoc} |
||||||
188 | */ |
||||||
189 | View Code Duplication | public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) |
|||||
190 | { |
||||||
191 | $this->_defaultFetchMode = $fetchMode; |
||||||
192 | $this->defaultFetchClass = $arg2 ? $arg2 : $this->defaultFetchClass; |
||||||
193 | $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; |
||||||
194 | |||||||
195 | return true; |
||||||
196 | } |
||||||
197 | |||||||
198 | /** |
||||||
199 | * {@inheritdoc} |
||||||
200 | */ |
||||||
201 | public function getIterator() |
||||||
202 | { |
||||||
203 | return new StatementIterator($this); |
||||||
204 | } |
||||||
205 | |||||||
206 | /** |
||||||
207 | * {@inheritdoc} |
||||||
208 | */ |
||||||
209 | View Code Duplication | public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0) |
|||||
210 | { |
||||||
211 | // do not try fetching from the statement if it's not expected to contain result |
||||||
212 | // in order to prevent exceptional situation |
||||||
213 | if (!$this->result) { |
||||||
214 | return false; |
||||||
215 | } |
||||||
216 | |||||||
217 | $fetchMode = $fetchMode ?: $this->_defaultFetchMode; |
||||||
218 | switch ($fetchMode) { |
||||||
219 | case \PDO::FETCH_BOTH: |
||||||
220 | return db2_fetch_both($this->_stmt); |
||||||
0 ignored issues
–
show
The function
db2_fetch_both was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
221 | case \PDO::FETCH_ASSOC: |
||||||
222 | return db2_fetch_assoc($this->_stmt); |
||||||
0 ignored issues
–
show
The function
db2_fetch_assoc was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
223 | case \PDO::FETCH_CLASS: |
||||||
224 | $className = $this->defaultFetchClass; |
||||||
225 | $ctorArgs = $this->defaultFetchClassCtorArgs; |
||||||
226 | |||||||
227 | if (func_num_args() >= 2) { |
||||||
228 | $args = func_get_args(); |
||||||
229 | $className = $args[1]; |
||||||
230 | $ctorArgs = isset($args[2]) ? $args[2] : []; |
||||||
231 | } |
||||||
232 | |||||||
233 | $result = db2_fetch_object($this->_stmt); |
||||||
0 ignored issues
–
show
The function
db2_fetch_object was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
234 | |||||||
235 | if ($result instanceof \stdClass) { |
||||||
236 | $result = $this->castObject($result, $className, $ctorArgs); |
||||||
237 | } |
||||||
238 | |||||||
239 | return $result; |
||||||
240 | case \PDO::FETCH_NUM: |
||||||
241 | return db2_fetch_array($this->_stmt); |
||||||
0 ignored issues
–
show
The function
db2_fetch_array was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
242 | case \PDO::FETCH_OBJ: |
||||||
243 | return db2_fetch_object($this->_stmt); |
||||||
244 | default: |
||||||
245 | throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.'); |
||||||
246 | } |
||||||
247 | } |
||||||
248 | |||||||
249 | /** |
||||||
250 | * {@inheritdoc} |
||||||
251 | */ |
||||||
252 | View Code Duplication | public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) |
|||||
253 | { |
||||||
254 | $rows = []; |
||||||
255 | |||||||
256 | switch ($fetchMode) { |
||||||
257 | case \PDO::FETCH_CLASS: |
||||||
258 | while ($row = call_user_func_array([$this, 'fetch'], func_get_args())) { |
||||||
259 | $rows[] = $row; |
||||||
260 | } |
||||||
261 | break; |
||||||
262 | case \PDO::FETCH_COLUMN: |
||||||
263 | while ($row = $this->fetchColumn()) { |
||||||
264 | $rows[] = $row; |
||||||
265 | } |
||||||
266 | break; |
||||||
267 | default: |
||||||
268 | while ($row = $this->fetch($fetchMode)) { |
||||||
269 | $rows[] = $row; |
||||||
270 | } |
||||||
271 | } |
||||||
272 | |||||||
273 | return $rows; |
||||||
274 | } |
||||||
275 | |||||||
276 | /** |
||||||
277 | * {@inheritdoc} |
||||||
278 | */ |
||||||
279 | View Code Duplication | public function fetchColumn($columnIndex = 0) |
|||||
280 | { |
||||||
281 | $row = $this->fetch(\PDO::FETCH_NUM); |
||||||
282 | |||||||
283 | if (false === $row) { |
||||||
284 | return false; |
||||||
285 | } |
||||||
286 | |||||||
287 | return isset($row[$columnIndex]) ? $row[$columnIndex] : null; |
||||||
288 | } |
||||||
289 | |||||||
290 | /** |
||||||
291 | * {@inheritdoc} |
||||||
292 | */ |
||||||
293 | public function rowCount() |
||||||
294 | { |
||||||
295 | return (@db2_num_rows($this->_stmt)) ? : 0; |
||||||
0 ignored issues
–
show
The function
db2_num_rows was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
296 | } |
||||||
297 | |||||||
298 | /** |
||||||
299 | * Casts a stdClass object to the given class name mapping its' properties. |
||||||
300 | * |
||||||
301 | * @param \stdClass $sourceObject Object to cast from. |
||||||
302 | * @param string|object $destinationClass Name of the class or class instance to cast to. |
||||||
303 | * @param array $ctorArgs Arguments to use for constructing the destination class instance. |
||||||
304 | * |
||||||
305 | * @return object |
||||||
306 | * |
||||||
307 | * @throws DB2Exception |
||||||
308 | */ |
||||||
309 | private function castObject(\stdClass $sourceObject, $destinationClass, array $ctorArgs = []) |
||||||
310 | { |
||||||
311 | View Code Duplication | if ( ! is_string($destinationClass)) { |
|||||
312 | if ( ! is_object($destinationClass)) { |
||||||
313 | throw new DB2Exception(sprintf( |
||||||
314 | 'Destination class has to be of type string or object, %s given.', gettype($destinationClass) |
||||||
315 | )); |
||||||
316 | } |
||||||
317 | } else { |
||||||
318 | $destinationClass = new \ReflectionClass($destinationClass); |
||||||
319 | $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); |
||||||
320 | } |
||||||
321 | |||||||
322 | $sourceReflection = new \ReflectionObject($sourceObject); |
||||||
323 | $destinationClassReflection = new \ReflectionObject($destinationClass); |
||||||
324 | /** @var \ReflectionProperty[] $destinationProperties */ |
||||||
325 | $destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), \CASE_LOWER); |
||||||
326 | |||||||
327 | foreach ($sourceReflection->getProperties() as $sourceProperty) { |
||||||
328 | $sourceProperty->setAccessible(true); |
||||||
329 | |||||||
330 | $name = $sourceProperty->getName(); |
||||||
331 | $value = $sourceProperty->getValue($sourceObject); |
||||||
332 | |||||||
333 | // Try to find a case-matching property. |
||||||
334 | if ($destinationClassReflection->hasProperty($name)) { |
||||||
335 | $destinationProperty = $destinationClassReflection->getProperty($name); |
||||||
336 | |||||||
337 | $destinationProperty->setAccessible(true); |
||||||
338 | $destinationProperty->setValue($destinationClass, $value); |
||||||
339 | |||||||
340 | continue; |
||||||
341 | } |
||||||
342 | |||||||
343 | $name = strtolower($name); |
||||||
344 | |||||||
345 | // Try to find a property without matching case. |
||||||
346 | // Fallback for the driver returning either all uppercase or all lowercase column names. |
||||||
347 | if (isset($destinationProperties[$name])) { |
||||||
348 | $destinationProperty = $destinationProperties[$name]; |
||||||
349 | |||||||
350 | $destinationProperty->setAccessible(true); |
||||||
351 | $destinationProperty->setValue($destinationClass, $value); |
||||||
352 | |||||||
353 | continue; |
||||||
354 | } |
||||||
355 | |||||||
356 | $destinationClass->$name = $value; |
||||||
357 | } |
||||||
358 | |||||||
359 | return $destinationClass; |
||||||
0 ignored issues
–
show
|
|||||||
360 | } |
||||||
361 | } |
||||||
362 |