当前位置: 首页 > 面试题库 >

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

胡俊弼
2023-03-14
问题内容

我的代码基于@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应该返回纯文本,对吗?我如何修改它以获得基于参数的查询?


问题答案:

我知道了。bindparams的实际值保存在一个称为的对象中,该对象SQLCompiler通常是特定于方言的。
这里(链接到GitHub)是在SQLCompiler查询编译过程中将bindparams存储在实例中的位置

因此,我的代码段的最终版本如下所示:

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


 类似资料:
  • 问题内容: 有没有办法在@Preauthorize块中创建更具表现力的语句?这是我重复的例子,因为@Preauthorize并非开箱即用。 我想要的是类似的东西。 问题的一部分是,我需要查询数据库以获取其中一些内容以验证权限,例如查询数据库以获取游戏副本,然后将游戏所有者与制作人进行比较请求。我不太确定所有这些如何在@Preauthorize注释处理器的上下文中运行,还是不确定如何将东西添加到@P

  • 问题内容: 我在非标准位置安装了自己的OpenSSL(出于本示例的目的),并且我希望针对源代码编译Python 3.4时可以以此为基础进行构建。我试过的是这个(目录缩写) 我也尝试了用冒号分隔的路径。 然后,我运行并得到以下信息: 它正在寻找,但是最确定的是: 我不确定自己在做什么错,有什么想法吗? 问题答案: 经过大量的梳理,我设法弄清楚了。这是一堆环境变量…我想我可能做得有些过分,但这基本上可

  • 如何计算方面中的Spring Security表达式?我想我可以很容易地使用完成这项工作的类I spring框架

  • 如果我更改了方法的名称,它会进行编译,但它不会重写toString,因此print方法不会打印预期的内容。 这是试图定义一个日志子系统,该子系统仅在需要时(当它真的要打印时)对lambda求值,但与非lambda参数兼容。我知道其他的方法来实现它,但我想知道为什么我不能这样做,如果有一个变通办法或我做错了什么,

  • 问题内容: 我不想让普通的lambda实现方法并将其toString重新定义为附加值。我希望lambda表达式仅实现toString方法。我知道我的表达不太好,但是我相信您会通过此示例理解我。 如果我更改了方法的名称,它将进行编译,但是它不会覆盖toString,因此print方法将不会输出期望的结果。 这是尝试定义一个日志子系统,该子系统仅在需要时(真正要打印时)评估lambda,但与非lamb

  • 我正在试用新的数据绑定库。我有一个奇怪的问题,属性的绑定没有编译。 这是xml文件的简化版本: 编译时收到以下消息: java.lang.RuntimeException:发现数据绑定错误. ****/ 数据绑定错误****msg:标识符必须具有XML文件中用户定义的类型。视图缺少它 当我删除声明时,一切都会编译(并正常工作!)。 我不知道我错过了什么