【发布时间】:2021-09-24 20:33:31
【问题描述】:
给定一个带有绑定的字符串:
input = "SELECT * FROM table WHERE col1 = %s AND col2 = %(col2_value)s"
我想将%s 转换为? 和%(named)s 转换为@named,这样我得到:
input = "SELECT * FROM table WHERE col1 = ? AND col2 = @col2_value"
我当前的实现使用re 交换两种类型并返回绑定列表:
def _convert_bindings(query: str) -> Tuple[str, List[Union[None, str]]]:
pos_rex = r"%s"
named_rex = r"%\((\w+)\)s"
bindings = [
None if m.string == "%s" else re.search(r"%\((?P<name>\w+)\)s", m.string).group("name")
for m in re.finditer(f"{pos_rex}|{named_rex}", query)
]
sql = re.sub(pos_rex, r"?", query)
sql = re.sub(named_rex, r"@\1", query)
return sql, bindings
但我认为 Python 必须有一个内置的方法来查找和替换参数,因为 str.format 已经这样做了。
那么提取%s 和%(named)s 并随后替换它们的最pythonic 方法是什么?是否有一个函数/属性可以命名为“str.params”或内置模块中的函数 getparams?
假设没有命名参数列表的先验知识。
【问题讨论】:
-
请问您为什么要这样做?您是否正在从一个数据库后端切换到另一个?
-
对于你所描述的,这个解决方案似乎很好。任何使代码“更加pythonic”的修改都可能不会提高这里的性能。您已经有了列表理解,其余代码只是使用正则表达式模块,所以我认为这很好。
-
我同意使用变量绑定,但如果您在代码库中有问题的字符串格式查询,我认为这是一个手动重构工作来完成并修复所有这些查询。或者你的用例是什么?
-
@Tim Roberts + Robert:我在代码中使用 psycopg2 和本机绑定,并在测试中使用 pglast 解析 SQL 以确保查询预期的源表。 pglast 不支持原生绑定,只支持 PG 绑定。