LINUX.ORG.RU

Где могут быть ограничения на запросы SQLite?

 


0

1

Сайт использует БД SQLite3. Фреймверк CI2. PHP 5.6.24.

После переноса сайта на новый хостинг, перестали выполняться SQL запросы UPDATE с длинным (десятки Кб) содержимым одного поля. Ну, то есть, есть поле data с типом TEXT, хранит текст статей, которые могут быть по ~50Кб. По идее никакого ограничения на длину поля TEXT быть не должно. Но выполнение команды вида:

UPDATE "articles" SET "data" = 'тут очень длинный html' WHERE "id" = '709131de8092025b6d3865ecf90fa123'


Приводит к неопределенной ошибке:

Error Number: Unavaiable
Error Message: Unavaiable


А если укоротить html примерно в два раза, то UPDATE нормально выполняется.

Вопрос: где может стоять какое ограничение на SQLite (или на PDO?) что команда с длинными данными не может выполниться?

★★★★★

Последнее исправление: Xintrea (всего исправлений: 1)

Смотри в настройках у пыха, которые на каждое расширение. И не забудь заглянуть в настройки сухозина (у него какраз фичастые крутилки про все эти размеры и лимиты), если таковой имеется.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от vel

Проблема оказалась в CI2, который толком не умеет работать с неперсистентными соединениями с БД, и самописном драйвере. Для MySQL/Postgree проблемы нет - там включется персистентное соединение и вперед.

А для SQLite все немного сложнее. Персистентного соединения с файловой БД установить по ее природе невозможно. Поэтому там работает режим неперсистентного соединения: иденетификатор соединения устанавливается каждый раз при выполнении скрипта, после того, как пройдут команды использования определенного файла SQLite.

И мне посчастливилось наткнуться на момент, когда соединения еще нет, но зато вызывается функция экранирования строки quote(). Эта функция зависит от типа соединения с базой данных, и в зависимости от типа базы данных использует разные правила экранирования. Но если соединения нет, то определить тип бд нельзя, нельзя определить правила экранирования, ну и quote() работать не будет.

Соответственно, нижеприведенный код не срабатывает:

//Escape the string
if(gettype($this->conn_id)===«object»)
{
$str = $this->conn_id->quote($str);
log_message('debug', «String after quote: ».print_r($str, true));
}

И строка не экранируется. Но зато запоминается для дальнейшего запроса, который может быть вызван т.к. потом соединение устанавливается. Ну просто код БД-подсистемы CI написан без учета, что вообще может возникнуть ситуация, что соединение недоступно в какой-то момент, исходя из предположения, что соединение персистентно.

И если в строке был амперсанд, то он не экранируется, и при конструировании портит SQL-запрос.

А так как это дело находится внутри БД-драйвера, то всякие плейсхолдеры тут не помогут: БД-драйвер и является как раз реализацией плейсхолдеров.

Раньше помогала отдельная функция quote() (или как-то так называлас), которая экранировала согласно переданным флагам и не была завязана на саоединении с БД. Потом в какой-то версии PHP 5.x ее выпилили, и получилась засада.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.