SqlAlchemy冲突绑定参数名称

2024-10-01 02:37:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我在编译多个具有相同绑定参数名称的文本子句时遇到问题

我有自己的子句(MyJoinClause),我为它编写了compile函数。问题是,编译器上下文只能为同一个参数名保存一个值,因此无论在哪个查询中compiler.process被称为last,该值都将在结果中绑定到all其他查询

而不是

SELECT * 
FROM ((select * from x where accid = '100') FULL OUTER JOIN (select * from y where accid = '200'))

它将导致:

SELECT * 
FROM ((select * from x where accid = '200') FULL OUTER JOIN (select * from y where accid = '200'))

完整可运行示例:

from sqlalchemy import text, select
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql import FromClause
from sqlalchemy.sql.base import Executable

class MyJoinClause(Executable, FromClause):
    def __init__(self, main_query, join_to_query):
        self.main_query = main_query
        self.join_to_query = join_to_query


@compiles(MyJoinClause)
def compile_join_using_query(element: MyJoinClause, compiler, **kwargs):
    query_template = "({}) FULL OUTER JOIN ({})"
    # Both queries have bind params with acc_id
    # As we are calling compiler.process, the acc_id bind param values are set on the compiler context
    format_args = [
        compiler.process(element.main_query),
        compiler.process(element.join_to_query)
    ]
    return ('(' + query_template + ')\n').format(*format_args)

q1 = text('select * from x where accid = :acc_id').bindparams(acc_id='100')
q2 = text('select * from y where accid = :acc_id').bindparams(acc_id='200')

final = MyJoinClause(q1, q2)
final = select(['*']).select_from(final)

print(str(final))
# SELECT * 
# FROM ((select * from x where accid = :acc_id) FULL OUTER JOIN (select * from y where accid = :acc_id))

我有什么选择?text子句是在其他地方创建的,我无法控制如何创建(因此在开头加上param名称前缀对我来说不是一个选项)

谢谢


Tags: fromidcompilersqlalchemywherequeryprocessselect