LINUX.ORG.RU

psycopg2 генерирует неправильные команды для комментариев и схем

 , , , ,


0

1

Продолжаю пытаться использовать библиотеку psycopg2. Проблема подкралась откуда не ждали.

Итак, код написан в соответствии с документацией:

https://www.psycopg.org/docs/usage.html

В которой сказано, что psycopg2 в методе execute() сама делает подстановки в SQL-запрос из переданного кортежа, и делает это правильно. Однако, по факту оказалось, что это не так.

Следующие ошибки демонстрируют, что psycopg2 не понимает где пользовательские данные, а где обращение к объектам. Она просто все подстановки анализирует на переданный базовый Python-тип, и вставляет данные соответственно этому типу. Если это строка - то она будет заключена в одинарные кавычки. Если целое число - будет вставлено число без кавычек.

А что делать, если в кортеже передано имя объекта БД, значение которого не нужно заключать в кавычки? Об этом авторы документации ничего не говорят.

Поэтому, например при использовании комментариев к таблице или при работе со схемами возникают ошибки:

Команды:

cursor.execute( "COMMENT ON TABLE %s IS 'version=%s';", (tableName, tableVersion) )

cursor.execute("CREATE SCHEMA IF NOT EXISTS %s;", (dbSchema,) )


Ошибки:

File "./sample.py", line 205, in setTableVersion
    cursor.execute( "COMMENT ON TABLE %s IS 'version=%s';", (tableName, tableVersion) )
psycopg2.ProgrammingError: ОШИБКА: ошибка синтаксиса at or near "'devices'
LINE 1: COMMENT ON TABLE 'devices' IS 'version=12';
                         ^

File "./sample.py", line 89, in connect
    cursor.execute("CREATE SCHEMA IF NOT EXISTS %s;", (dbSchema,) )
psycopg2.ProgrammingError: ОШИБКА: ошибка синтаксиса at or near "'service'
LINE 1: CREATE SCHEMA IF NOT EXISTS 'service';
                                    ^

В этих командах значения devices и service не должны заключаться в кавычки. Но они заключаются, чем и ломают саму команду.

Вопрос: а как же правильно передавать значения в execute() ?

★★★★★

https://www.psycopg.org/docs/usage.html#passing-parameters-to-sql-queries

Only query values should be bound via this method: it shouldn’t be used to merge table or field names to the query (Psycopg will try quoting the table name as a string value, generating invalid SQL). If you need to generate dynamically SQL queries (for instance choosing dynamically a table name) you can use the facilities provided by the psycopg2.sql module:

>>> cur.execute("INSERT INTO %s VALUES (%s)", ('numbers', 10))  # WRONG
>>> cur.execute(                                                # correct
...     SQL("INSERT INTO {} VALUES (%s)").format(Identifier('numbers')),
...     (10,))
masa
()
Ответ на: комментарий от masa

Мда, «безопасность через неудобность», это надо было так постараться.

Для тех, кто эту тему найдет в надежде разобраться.

Если нужно сконструировать и выполнить запрос, состоящий как из имен объектов БД, так и из данных, хранимых в БД, проще всего это делать в два этапа. На первом этапе конструируется сам запрос:

import psycopg as sql

# Безопасная подстановка имен объектов БД при конструировании запроса
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
    field=sql.Identifier('my_name'),
    table=sql.Identifier('some_table'),
    pkey=sql.Identifier('id'))

На втором этапе происходит выполнение запроса, передавая ему данные через кортеж, чтобы метод execute() сам данные правильно проэкранировал:
# Подстановка значений в плейсхолдер %s    
cur.execute(query, (42,))

Этот подход работает потому, что метод execute() может принимать в первом пареметре как строку, так и объект запроса.

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

А вот тут мимо.

Ну тогда определись, учитель ты или айтишник, или у тебя профессиональная деформация включать свои условные рефлексы там где они не нужны.

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

Я тут начал методично составлять список токсиков. Теперь ты - почетный член, peregrine тоже.

Список самых токсичных русскоязычных АйТи ресурсов для разработчиков и специалистов

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

Список токсиков – это полдела. Нужен ещё список дураков или тугодумов, образно говоря, тормозов. И ты этот список возглавляешь.

anonymous
()
Ответ на: комментарий от peregrine

Раньше думал ТС со странностями, но он похоже совсем упорот.

Вот до чего людей астралинукс доводит! /s

Ну и сколько существует в ЯП интерполяция строк, столько идиоты будут её упорно использовать вместо bind variables, тут видимо ничего не поделаешь.

Этот просто ещё и агрессивный)

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

А какая связь между тобой и разработчиками-специалистами?
Ты гораздо ближе к лоровасянам.

Одно употребление слова токсик это уже диагноз тащемта

anonymous
()