Ошибка оракула
В одном из проектов при исправлении ошибки всплыло неожиданное. Кусок кода, который работал ошибочно, родился где-то в двухтысячных и по всей видимости в те времена работал правильно. В нём проверялось — если тип переменной «целое», то переменная передавалась в «Оракл» с флагом SQLT_INT, иначе — с SQLT_CHR.
Всё работало хорошо, пока ПХП был 32-битным. Проверка is_int в этом языке возвращала «истину» только для чисел в диапазоне -2147483648…2147483647, всё что шире, трактовалось как float. В 64-битном интерпретаторе целыми считаются числа из гораздо более широкого диапазона, соответственно, в каком-то коде такое значение попало в драйвер «Оракла», промаркированное как SQLT_INT.
Беда в том, что драйвер (в этом месте), похоже, остался в пределах 32 бит, код:
$var = null;
$st = oci_parse($con, "SELECT :int FROM DUAL");
oci_bind_by_name($st, 'int', $var, -1, SQLT_INT);
foreach ([100500, PHP_INT_MAX, 2147483648] as $var) {
oci_execute($st);
echo oci_fetch_array($st, OCI_NUM)[0], "\n";
}
Выведет: 100500, -1, -2147483648. Решение я пока знаю только одно: не использовать для целых, которые не помещаются в 32 бита указание типа SQLT_INT.
Проблема в файле oci8_statement.c (это текущий код драйвера из PHP 5.7):
switch (bind->array.type) {
case SQLT_NUM:
case SQLT_INT:
case SQLT_LNG:
...
ZVAL_LONG(entry, ((ub4 *)(bind->array.elements))[i]);
...
Значение в этом месте приводится к четырёхбайтному целому.
ПЫХ — поделие школьников для школьников.
То, что ПЫХ столь популярен, напоминает ситуацию, когда в одной такой стране
был дважды несудимый президент.
Комментарий для PHP:
Спасибо за ваше интересное мнение!