Добавить фильтры для динамического запроса с помощью pyscopg2 - PullRequest
0 голосов
/ 29 мая 2019

Пытаясь создать динамический фильтр, у меня возникают трудности с печатью, где выписка без "кавычек".

Выход: select "col1", "col2" from "table1" where "col2=1234" and "col3=column1"

Желаемый: select "col1", "col2" from "table1" where col2="1234" and col3="column1"

def filter(table,*args,**kwarg):
 query = sql.SQL("select {0} from {1} where {2}").format(
    sql.SQL(', ').join(map(sql.Identifier,[arg for arg in args])),
    sql.Identifier(table),
    sql.SQL(' and ').join(map(sql.Identifier,{(str(k)+'='+str(v)) for k,v in kwarg.iteritems()}))
    )
 print query.as_string(Connection())

1 Ответ

1 голос
/ 03 июня 2019

Вы кодируете каждое условие как отдельный идентификатор SQL, т. Е. Фактически кодируете sql.Identifier('foo=bar')

Другая ловушка заключается в том, что вы помещаете значения запроса непосредственно в SQL;хотя вы можете доверять источнику, вообще говоря, это будет плохой идеей.Лучше использовать заполнитель и предоставлять фактические значения во время выполнения.

Наконец, списочные понимания обычно предпочтительнее, чем map;однако это выбор стиля.

Сложив их вместе, предикат будет корректно отображаться примерно так:

def filter(table, *args, **kwargs):
  conditions = [sql.SQL(' = ').join([sql.Identifier(k), sql.Placeholder()]) for k in kwarg.keys()]
  query = sql.SQL("select {0} from {1} where {2}").format(
     sql.SQL(', ').join([sql.Identifier(arg) for arg in args]),
     sql.Identifier(table),
     sql.SQL(' and ').join(conditions)
  )

Это предполагает, что базовый dict не изменяется между построением запросаи исполнение.Ваше "execute" будет выглядеть примерно так:

cursor.execute(sql, kwargs.values())

Если это предположение не выполняется, замените sql.Placeholder() на sql.Literal(v) в понимании conditions и используйте kwargs.items() вместо kwargs.keys(),В этом случае я думаю , что Literal будет правильно экранировать практически любую рискованную строку, но безопаснее использовать заполнители и параметры.

Надеюсь, что это поможет

...