SQLAlchemy更新后出现奇怪错误:'list'对象没有'_all_columns'属性
这是我问题的简化版本:
subquery = (select(['latitude'])
.select_from(func.unnest(func.array_agg(Room.latitude))
.alias('latitude')).limit(1).as_scalar())
Room.query.with_entities(Room.building, subquery).group_by(Room.building).all()
执行时我在SQLAlchemy内部遇到了一个错误:
File ".../sqlalchemy/sql/selectable.py", line 429, in columns
self._populate_column_collection()
File ".../sqlalchemy/sql/selectable.py", line 992, in _populate_column_collection
for col in self.element.columns._all_columns:
AttributeError: 'list' object has no attribute '_all_columns'
在调试器中查看时,我看到了这个:
>>> self.element
<sqlalchemy.sql.functions.Function at 0x7f72d4fcae50; unnest>
>>> str(self.element)
'unnest(array_agg(rooms.id))'
>>> self.element.columns
[<sqlalchemy.sql.functions.Function at 0x7f72d4fcae50; unnest>]
问题始于SQLAlchemy 0.9.4;在0.9.3版本中一切正常。
在SQLAlchemy 0.9.3中运行时,执行了以下查询(这是预期的结果):
SELECT rooms.building AS rooms_building,
(SELECT latitude
FROM unnest(array_agg(rooms.latitude)) AS latitude
LIMIT 1) AS anon_1
FROM rooms
GROUP BY rooms.building
我是在做错什么,还是这是SQLAlchemy的一个bug?
1 个回答
0
这其实是SQLAlchemy里的一个bug:https://bitbucket.org/zzzeek/sqlalchemy/issue/3137/decide-what-funcxyz-alias-should-do
func.foo().alias()
本来应该和func.foo().select().alias()
是一样的,但在这个情况下,这样做会导致多一层嵌套,这是我们不想要的。所以要修正这个API,可能需要等到1.0版本,除非我能确定func.foo().alias()
现在完全不能用。
根据SQLAlchemy开发者的说法,正确的做法是这样的:
subquery = (select(['*']).select_from(
func.unnest(func.array_agg(Room.latitude)))
.limit(1)
.as_scalar())
很可能下一个版本(我猜是0.9.8)会恢复旧的行为:
我会恢复旧的行为,但现在请使用
select(['*'])
。这个列是没有名字的。PG根据FROM中的别名来给列命名的行为有点神奇(例如,如果函数返回多个列,它就会忽略那个名字,使用函数报告的名字?)