我的代码基于 @zzzeeek 的回答这个问题。
我对其进行了一些扩展,因此它考虑了 Postgresql 的 NULL 和 ARRAY。
class values(FromClause):
named_with_column = True
def __init__(self, columns, *args, **kw):
self._column_args = columns
self.list = args
self.alias_name = self.name = kw.pop('alias_name', None)
def _populate_column_collection(self):
# self._columns.update((col.name, col) for col in self._column_args)
for c in self._column_args:
c._make_proxy(self, c.name)
@compiles(values)
def compile_values(element, compiler, asfrom=False, **kw):
columns = element.columns
v = "VALUES %s" % ", ".join(
"(%s)" % ", ".join(
((compiler.visit_array(elem)+'::'+str(column.type)) if isinstance(column.type, ARRAY) else
compiler.render_literal_value(elem, column.type))
if elem is not None else compiler.render_literal_value(elem, NULLTYPE)
for elem, column in zip(tup, columns))
for tup in element.list
)
if asfrom:
if element.alias_name:
v = "(%s) AS %s (%s)" % (v, element.alias_name, (", ".join(c.name for c in element.columns)))
else:
v = "(%s)" % v
return v
一切都工作正常,直到事实证明我无法将带有“%”符号的值插入到这个 VALUES 子句中 - 它们被内联到结果语句中,这似乎会导致绑定问题
我想如果不是render_literal_value()
我们用了bindparam()
我们可以避免这样的错误。但一切都在@compiles
应该返回纯文本,对吗?我如何修改它以获得基于参数的查询?