Вы кодируете каждое условие как отдельный идентификатор 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
будет правильно экранировать практически любую рискованную строку, но безопаснее использовать заполнители и параметры.
Надеюсь, что это поможет