-
Notifications
You must be signed in to change notification settings - Fork 36
Description
oci8.php, function fetchInto(), lines 385 and 397:
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
(385) $arr = @oci_fetch_array($result,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
if (is_array($arr)) {
$moredata = count($arr);
} else {
$moredata = false;
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE &&
$moredata)
{
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
(397) $arr = @oci_fetch_array($result,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS); <= s/b OCI_NUM
oci_fetch_array() is always called with OCI_ASSOC value and you cannot change it. It is written with assumption that you always want it returned in OCI_ASSOC order.
arg fetchmode can be any one of :
- DB_FETCHMODE_DEFAULT
- DB_FETCHMODE_ORDERED
- DB_FETCHMODE_ASSOC
- DB_FETCHMODE_OBJECT
- DB_FETCHMODE_FLIPPED
Valid modes in oci_fetch_array () used in the if-else can only be
- OCI_BOTH
- OCI_ASSOC
- OCI_NUM
When the expression "if ($fetchmode & DB_FETCHMODE_ASSOC) " evaluates to true,
(385) $arr = @oci_fetch_array($result,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
DB_FETCHMODE_ASSOC is hard coded and mapped (or implied) into OCI_ASSOC which works and is correct.
But when "if ($fetchmode & DB_FETCHMODE_ASSOC)" evaluates to false,
independently of what value $fetchmode is, OCI_ASSOC is always used as the value in oci_fetch_array():
(397) $arr = @oci_fetch_array($result,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
The problem lies in the else block when the expression is false.
$fetchMode can be potentially any 1 of the 5 DB_FETCHMODE_* values, while there are only 3 OCI_* values to specify in oci_fetch_array().
Technically there should be a mapping of $fetchMode => OCI_*
- DB_FETCHMODE_DEFAULT => ?
- DB_FETCHMODE_ORDERED => OCI_NUM
- DB_FETCHMODE_ASSOC => OCI_ASSOC
- DB_FETCHMODE_OBJECT => ?
- DB_FETCHMODE_FLIPPED => ?
As it is written, the rows are always returned in OCI_ASSOC order in the else block.
I found this out when an application I took over calls fetchInto() using both DB_FETCHMODE_ASSOC and DB_FETCHMODE_ORDERED and the resultant rows being returns was alway in OCI_ASSOC order throwing exceptions.
In my specific situation I modified the else block line at 397 oci_fetch_array() to always use OCI_NUM and it solved my specific problem.
This is the diff between the original and my problem fixed using OCI_NUM in the else block.
# diff oci8.php-dist oci8.php 397c397 < $arr = @oci_fetch_array($result,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS); --- > $arr = @oci_fetch_array($result,OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
I have tested this in my own application and this fixed the problem.
Sorry but I do no have any suggestions as to what a proper "fix" would be in this case. Hmmm.