gpt4 book ai didi

python - 如何在自定义编译表达式中使用 bindparam()?

转载 作者:行者123 更新时间:2023-11-29 12:19:33 25 4
gpt4 key购买 nike

我的代码基于@zzzeek 对this question 的回答.我稍微扩展了它,以便它考虑到 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 子句中——它们被内联到结果语句中,这似乎会导致绑定(bind)问题

我想如果我们使用 bindparam() 而不是 render_literal_value() 我们可以避免这样的错误。但是 @compiles 下的所有内容都应该返回纯文本,对吗?我如何修改它以获得基于参数的查询?

最佳答案

我明白了。 bindparams 的实际值保存在一个名为 SQLCompiler 的对象中,该对象通常是特定于方言的。 Here(link to GitHub)是查询编译过程中 bindparams 存储在 SQLCompiler 实例中的地方

所以我的代码片段的最终版本如下所示:

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(clause, compiler, asfrom=False, **kw):
def decide(value, column):
add_type_hint = False
if isinstance(value, array) and not value.clauses: # for empty array literals
add_type_hint = True

if isinstance(value, ClauseElement):
intermediate = compiler.process(value)
if add_type_hint:
intermediate += '::' + str(column.type)
return intermediate

elif value is None:
return compiler.render_literal_value(
value,
NULLTYPE
) + '::' + str(column.type)
else:
return compiler.process(
bindparam(
None,
value=compiler.render_literal_value(
value,
column.type
).strip("'")
)
) + '::' + str(column.type)

columns = clause.columns
v = "VALUES %s" % ", ".join(
"(%s)" % ", ".join(
decide(elem, column)
for elem, column in zip(tup, columns))
for tup in clause.list
)
if asfrom:
if clause.alias_name:
v = "(%s) AS %s (%s)" % (v, clause.alias_name, (", ".join(c.name for c in clause.columns)))
else:
v = "(%s)" % v
return v

关于python - 如何在自定义编译表达式中使用 bindparam()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33767740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com