【发布时间】:2017-07-09 17:42:49
【问题描述】:
在回答 another question 时,我在尝试生成一个 hybrid property 时碰壁了,它会返回一个 function expression 包装一个标量子查询,该子查询将其所有 FROM 对象与封闭查询相关联,但它仍会提供一个 FROM如果封闭查询中没有其他表达式提供要关联的表,则对象。
给定一个玩具模型定义
class Foo(Base):
__tablename__ = 'foo'
foo_id = Column(Integer, primary_key=True, autoincrement=True)
bar = Column(postgresql.ARRAY(Integer))
baz = Column(postgresql.ARRAY(Integer))
@hybrid_property
def bar_sans_baz(self):
return list(set(self.bar).difference(self.baz))
@bar_sans_baz.expression
def bar_sans_baz(cls):
bar = func.unnest(cls.bar).select().correlate(cls)
baz = func.unnest(cls.baz).select().correlate(cls)
stmt = bar.except_(baz)
# Uses `func` generic as ARRAY() constructor
return func.array(stmt.as_scalar(),
type_=postgresql.ARRAY(Integer))
问题是
session.query(Foo.bar_sans_baz)
结果
SELECT array((SELECT unnest(foo.bar) AS unnest_1
FROM foo EXCEPT SELECT unnest(foo.baz) AS unnest_2
FROM foo)) AS bar_sans_baz
因为它在封闭查询中没有任何关联。一个简单的补救方法是使用select_from() 显式添加 FROM 对象:
session.query(Foo.bar_sans_baz).select_from(Foo)
结果查询是期望的
SELECT array((SELECT unnest(foo.bar) AS unnest_1
EXCEPT SELECT unnest(foo.baz) AS unnest_2)) AS bar_sans_baz
FROM foo
虽然这可行,但它会增加精神开销,因为您必须记住添加select_from(Foo),如果只选择混合属性。这不是问题,如果任何其他选择项提供 Foo:
In [105]: print(session.query(Foo.bar_sans_baz, Foo.foo_id))
SELECT array((SELECT unnest(foo.bar) AS unnest_1 EXCEPT SELECT unnest(foo.baz) AS unnest_2)) AS bar_sans_baz, foo.foo_id AS foo_foo_id
FROM foo
有没有办法注释返回的函数表达式func.array(...) - 或内部标量子查询 - 如果没有其他表达式提供它,它将提供 Foo 作为 FROM 对象。或者换句话说,只是一种将 Foo 作为from_obj 添加到函数表达式或标量子查询的方法,以便内部选择可以使用它。
【问题讨论】:
标签: python postgresql sqlalchemy