尝试创建动态过滤器时,我很难在不带引号的情况下打印where语句。
输出: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())
答案 0 :(得分:1)
您正在将每个条件编码为单个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。您的“执行”类似于:
cursor.execute(sql, kwargs.values())
如果该假设不成立,请在sql.Placeholder()
理解中将sql.Literal(v)
替换为conditions
,并使用kwargs.items()
代替kwargs.keys()
。在这种情况下,我认为 Literal
可以正确地转义几乎所有有风险的字符串,但使用占位符和参数更安全。
希望有帮助