История изменений
Исправление Xintrea, (текущая версия) :
Проблема оказалась в 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, :
Проблема оказалась в 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 ее выпилили, и получилась засада.