LINUX.ORG.RU

Синтаксис запросов MySQL. Строки в WHERE.


0

1

Адаптирую сейчас старый проект с SQLite на MySQL. (Фреймверк CodeIgniter 2.1.4)

Особенностей MySQL совершенно не знаю, раньше никогда с ним не работал.

Вот сейчас лезет такая ошибка:

Error Number: 1054

Unknown column 'table_name='articles'' in 'where clause'

SELECT `id`, `allocate_id` FROM (`lt_sys_allocate_id_history`) WHERE `table_name='articles'` ORDER BY `id`

Столбец table_name в таблице lt_sys_allocate_id_history присутсвует:

/*Table: lt_sys_allocate_id_history*/
-------------------------------------

/*Column Information*/
----------------------

Field        Type      Collation        Null    Key     Default  Extra           Privileges                       Comment  
-----------  --------  ---------------  ------  ------  -------  --------------  -------------------------------  ---------
id           int(11)   (NULL)           NO      PRI     (NULL)   auto_increment  select,insert,update,references           
table_name   tinytext  utf8_general_ci  YES             (NULL)                   select,insert,update,references           
allocate_id  int(11)   (NULL)           YES             (NULL)                   select,insert,update,references           
time         tinytext  utf8_general_ci  YES             (NULL)                   select,insert,update,references           

Обратные апострофы добавляет MySQL-драйвер, обслуживающий ActiveRecord. Он считает, что имена полей, имена таблиц, выражение WHERE следует заключать в обратные апострофы.

Правильное ли это поведение драйвера?

В чем еще может быть проблема?

★★★★★

Полагаю, что where в кавычки заключать не нужно. Попробуй руками вбить запрос прямо в базу и спарси ошибки и устрани. mysql -uuser -ppassword, ну, если есть ssh. Тащемта, я никогда в апострофы не заключал ничего. То есть SELECT shit FROM fuckyou WHERE id=666;. Всё.

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

наверное ты в этот свой CodeIgniter как-то неправильно условие запихиваешь, не так, как там это предусмотрено, отсюда и апострофы

или просто баг

Harald ★★★★★ ()
Ответ на: комментарий от Harald

наверное ты в этот свой CodeIgniter как-то неправильно условие запихиваешь, не так, как там это предусмотрено, отсюда и апострофы

кстати да, покажи как ты формируешь query, по идее должно быть как-то так:

$this->db->where('table_name', 'articles');
static_lab ★★★★★ ()
Ответ на: комментарий от static_lab

кстати да, покажи как ты формируешь query, по идее должно быть как-то так:
$this->db->where('table_name', 'articles');

Я засовываю WHERE в виде строки, так как условие берется из специального XML-файла с конфигом проекта.

Вот кусок документации CodeIgniter:

$this->db->where();

Эта функция позволяет установить условие WHERE одним из четырех методов:

4. Специальная строка:

Вы можете писать запросы вручную:

$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);

Я засовываю WHERE, для теста, вот так (один-в-один как в документации!):

$where="table_name='articles'";
$this->db->where($where);

где «table_name='articles'» - в реальном проекте берется из XML конфига. И CodeIgniter тупо обрамляет все это выражение обратными апострофами:

SELECT `id`, `allocate_id` FROM (`lt_sys_allocate_id_history`) WHERE `table_name='articles'` ORDER BY `id`

А нужно:

SELECT `id`, `allocate_id` FROM (`lt_sys_allocate_id_history`) WHERE `table_name`='articles' ORDER BY `id`

Кстати, такое обрамление нормально прожевывает SQLite, но не может прожевать MySQL. У SQLite, правда, драйвер рисует прямые апострофы, а внутри такого обрамления можно пользоваться кавычками. То есть, в случае SQLite будет сгенерирован и нормально выполнен запрос:

SELECT 'id', 'allocate_id' FROM ('lt_sys_allocate_id_history') WHERE 'table_name="articles"' ORDER BY 'id'

Мне подсказывают, что можно воспользоваться решением:

$this->db->where($where, NULL, FALSE)

Однако, такое решение - серьезный удар по безопасности, ибо:

$this->db->where() принимает третий опциональный параметр. Если вы установите его в FALSE, CodeIgniter не будет пытаться защищать имена полей и таблиц обратными кавычками.

Что же делать?

Xintrea ★★★★★ ()
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от static_lab

Шайтан!

Действительно, так сформировалась правильная строка:

SELECT `id`, `allocate_id` FROM (`lt_sys_allocate_id_history`) WHERE `table_name` = 'articles' ORDER BY `id`

Чёрт, теперь выискивать все места с WHERE и в коде и в XML и расставлять пробелы.

В SQLite все работало без пробелов, а в MySQL вона как.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Всё дело в упоротом кодеигниторовском конструкторе запросов: вначале он собирает все условия в одну строку независимо от способа вызова функций, а затем начинает её парсить и экранировать объекты, однако парсер примитивен и не отражает полностью синтаксис SQL, например, не учтены операторы, поэтому токенизация работает неправильно. При вызове же функции where с раздельными названием поля и значением, они склеиваются с " = ", т.е. через пробелы, поэтому всё работает нормально.

static_lab ★★★★★ ()
Ответ на: комментарий от static_lab

Обратные запросы вообще как раз предназначены для экранирования имён полей или таблиц, содержащих спецсимволы или ключевые слова SQL, потому `table_name='articles'` и была понята парсером MySQL собственно как имя поля, которого он, разумеется, не нашёл. Кстати говоря, такое имя поля вполне валидно в MySQL, хотя и выглядит довольно необычно.

static_lab ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.