Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

💢 OCI8: проблемы с переходом на PHP7

Ещё в копилку проблем с ПХП7: если при привязке переменных в Оракле (bind) поля типа LONG/LOB не находятся в конце списка, то вы получите ошибку ORA-24816. Все столбцы таких типов должны быть привязаны последними, в общей куче. Мы пока столкнулись с проблемой только при сохранении (тестирование пока идёт), в итоге в сохраняющем методе модели пересортировали привязки, основываясь на описании модели.

13 комментариев
Gintonic 2016

Доброго дня,

Мы пока столкнулись с проблемой только при сохранении (тестирование пока идёт), в итоге в сохраняющем методе модели пересортировали привязки, основываясь на описании модели.

Можете привести пример запроса? Это выражение UPDATE или процедура/функция с входными параметрами (или и то и другое)?

Gintonic 2016

Или это вообще не зависит от запроса?

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Gintonic:

В нашем случае это UPDATE или INSERT (не знаю точно), в SELECT пока не встретили.

Евгений Степанищев (bolknote.ru) 2016

Ссылка в тему: http://psoug.org/oraerror/ORA-24816.htm

Сергей 2016

Это не бага, это фича
http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/oci05bnd.htm#LNOCI16372

A special consideration applies on the maximum size of bind variables that are neither LONG or LOB, but that appear after any LOB or LONG bind variable in the SQL statement. You receive an ORA-24816 error from Oracle Database if the maximum size for such bind variables exceeds 4000 bytes. To avoid this error, you must set OCI_ATTR_MAXDATA_SIZE to 4000 bytes for any such binds whose maximum size may exceed 4000 bytes on the server side after character set conversion. Alternatively, reorder the binds so that such binds are placed before any LONG or LOBs in the bind list.

Если у тебя varchar2(4000) и UTF, то

  • When a client connects to a multibyte database (AL32UTF8 for example) and the string , once converted to the multibyte database encoding becomes longer than 4000 BYTES Oracle transforms this internally into a LONG as the data is longer than the 4000 bytes max value for Varchar2.
  • OCI has a requirement that any LOB and LONG needs to be the last of the bind list, this includes that «real» LONG/LOB need to be the last and after any VARCHAR2 that is expanded to over 4000 BYTE due to the characterset conversion
Евгений Степанищев (bolknote.ru) 2016

Комментарий для Сергей:

Почему-то эта «фича» проявляется только на ПХП7, на предыдущих версиях годами проблем не было. Видимо драйвер это как-то сам разруливал.

Сергей 2016

Тут я только гадать могу:

  1. Свежая тестовая база создана в уникоде, а предыдущая нет?
  2. Предыдущий драйвер ставил OCI_ATTR_MAXDATA_SIZE?
Евгений Степанищев (bolknote.ru) 2016

Комментарий для Сергей:

База та же. Не я один заметил ошибку:

https://bugs.php.net/bug.php?id=72524
https://github.com/owncloud/core/issues/18363

Сергей 2016

Комментарий для Евгения Степанищева:

Всё страньше и страньше...
Причем вопрос, с мое кочки зрения, не почему не работает в php7 (не должно работать), а как работало в php5? Единственное, что приходит в голову — ошибка в реализации ошибки :). Или наглая установка OCI_ATTR_MAXDATA_SIZE за что надо бить сапогами.
Но по php я совсем не специалист.
Кстати, в Oracle 12 ограничение осталось.

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Сергей:

Для меня эта ситуация — баг. Годами нормально всё работало, всегда, во всех ситуациях, а тут что-то поломали. По мне так надо вернуть как было.

Gintonic 2016

Не прошло и 3-х месяцев, как запилили фикс, см. комментарии на  https://bugs.php.net/bug.php?id=72524
Как раз сегодня запулили pull-request в master,
http://git.php.net/?p=php-src.git%26a=search%26h=HEAD%26st=commit%26s=72524

39 min ago Christoph M. Becker Merge branch ’pull-request/1997’ master

так что можно ожидать, что в версии 7.0.11 или какой-то ближайшей это выкатят

Gintonic 2016

похоже, обрадовался рано, речь в исправлении идёт только про биндинг NULL-значений после LONG/LOB, а не про любые.

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Gintonic:

Да, фикс видел, выйдет, протестирую.