Кажется, что Django ложно заявляет об ошибке синтаксиса SQL - PullRequest
2 голосов
/ 21 января 2012

Кажется, что Django ложно утверждает, что у меня есть ошибка в моем синтаксисе SQL.Запрос работает нормально (возвращая ожидаемые результаты) в django dbshell, но порождает ошибку, когда запрос выполняется через Django.Вот код (следы отслеживания следуют):

#this code is inside the models.Customer.display_sharers() function
sharers_by_action_count = Sharer.objects.raw('''
SELECT wordout_sharer.id, COUNT(actions_of_type.id) AS action_count
FROM
wordout_customer
INNER JOIN wordout_sharer
 ON wordout_sharer.customer_id = wordout_customer.id
LEFT JOIN wordout_click
 ON wordout_sharer.id = wordout_click.sharer_id
LEFT JOIN
(SELECT wordout_action.id, wordout_action.click_id
FROM wordout_action
WHERE
wordout_action.action_type_id = %s) as actions_of_type
 ON actions_of_type.click_id = wordout_click.id
WHERE wordout_customer.id = %s
GROUP BY wordout_sharer.id
ORDER BY action_count %s
''', (action_type_id, self.id, direction))

force_execution = list(sharers_by_action_count) #force the query to run by converting it to a list.. this is to trigger the error.

Вот результат трассировки:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/me/sources/django_wordout/../django_wordout/wordout/models.py", line 106, in display_sharers
    if order_by == 'action_count': #we have to make a special query for when they want to sort by the count of a specific action
  File "/Users/me/sources/django_wordout/../django_wordout/wordout/models.py", line 92, in sharers_by_action_count_with_total_clicks
    force_exec = list(sharers_by_action_count)
  File "/Library/Python/2.7/site-packages/django/db/models/query.py", line 1324, in __iter__
    query = iter(self.query)
  File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py", line 67, in __iter__
    self._execute_query()
  File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py", line 81, in _execute_query
    self.cursor.execute(self.sql, self.params)
  File "/Library/Python/2.7/site-packages/django/db/backends/util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "/Library/Python/2.7/site-packages/django/db/backends/sqlite3/base.py", line 234, in execute
    return Database.Cursor.execute(self, query, params)
DatabaseError: near "?": syntax error

Когда выполняется Database.Cursor.execute(self, query, params), здесь приведены значения всех параметров:

self :

<django.db.backends.sqlite3.base.SQLiteCursorWrapper object at 0x10c477180> 

query :

        SELECT wordout_sharer.id, COUNT(actions_of_type.id) AS action_count
        FROM
        wordout_customer
        INNER JOIN wordout_sharer
         ON wordout_sharer.customer_id = wordout_customer.id
        LEFT JOIN wordout_click
         ON wordout_sharer.id = wordout_click.sharer_id
        LEFT JOIN
        (SELECT wordout_action.id, wordout_action.click_id
        FROM wordout_action
        WHERE
        wordout_action.action_type_id = ?) as actions_of_type
         ON actions_of_type.click_id = wordout_click.id
        WHERE wordout_customer.id = ?
        GROUP BY wordout_sharer.id
        ORDER BY action_count ?

params:

         (1, 1, 'DESC')

Нашел ли я ошибку в Django?Разве он не может правильно обрабатывать определенные типы запросов?

Моя конфигурация : я использую довольно ванильную конфигурацию разработки.Для двигателя БД я использую sqlite.Для миграций (которые актуальны) я использую Юг.

Обновление

Только что обнаружил, что замена %s их значениями делает запрос работающим. Что можетсобираетесь сделать %s проблематичным для Джанго?

Ответы [ 2 ]

4 голосов
/ 21 января 2012

Согласно этой странице , sqlite обрабатывает параметризованные значения как литералы, что означает, что они вставляют константы данного типа вместо обычной «замены текста».

Начиная с ASC или DESCв порядке по - это ключевое слово, а не константа, его нельзя заменить параметром.

На самом деле это может привести к неожиданному поведению, если вы, например, выполните

ORDER BY ? DESC

и вы даете ему имя столбца (скажем, column1), он на самом деле работает, но не сортируется в ожидаемом порядке.Причина в том, что он на самом деле сортируется по строке "column1" - которая одинакова для каждой строки - вместо фактического содержимого столбца.

0 голосов
/ 17 августа 2016

Я оказался в похожей ситуации.В обоих наших случаях мы делаем все правильно, НЕ используя форматирование строк:

Database.Cursor.execute(self, query, params)

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

Database.Cursor.execute(self, query % tuple(params))

Для будущих читателей: просто учтите, что это делает вас уязвимым для SQL-инъекций, если вы используете это как обходной путь.Если вы не понимаете, что это значит, не делайте этого!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...