Replies: 2 comments
|
The reason The typed way out is statement = select(Hero.name).union(select(Villain.name))
names = session.execute(statement).scalars().all()One heads-up: SQLModel puts |
|
Checked with pyright 1.1.411, sqlmodel 0.0.39: statement = select(Hero.name).union(select(Villain.name))
session.exec(statement).scalars().all()
# error: No overloads for "exec" match the provided arguments
# error: Argument of type "CompoundSelect[tuple[str]]" cannot be assigned to
# parameter "statement" of type "UpdateBase" in function "exec"
session.execute(statement).scalars().all()
# 0 errors — cleanBoth return Two things worth adding: The failure isn't caused by the SQLAlchemy 2.1 prerelease. I reproduced both errors on SQLAlchemy 2.0.51, so it's purely the shape of
@deprecated(
"""
...
""",
category=None,
)
def execute(
self,
statement: _Executable,
...
) -> Result[Any]:
"""
🚨 You probably want to use `session.exec()` instead of `session.execute()`.
...
"""
That seems like a reasonable case for the |
Uh oh!
There was an error while loading. Please reload this page.
Description
Combining two selects with
.union()and running them throughsession.exec()works at runtime, but the result's.scalars()doesn't survive type checking:At runtime
.union()returns a SQLAlchemyCompoundSelect, andexec()hands back the plain SQLAlchemyResult(aChunkedIteratorResulthere), which has.scalars(). On the typed surface though:exec()call itself:No overloads for "exec" match the provided arguments—CompoundSelect[tuple[str]]is not SQLModel'sSelect/SelectOfScalar, so only theUpdateBaseoverload is left and it doesn't fit either.exec()toTupleResult[Unknown]and then rejects the attribute:Object of type TupleResult[Unknown] has no attribute scalars.TupleResultis SQLAlchemy's typing-only class that whitelists a subset ofResultmethods, andscalars()isn't among them.So any compound select (union, intersect, except) currently has no way to reach
.scalars()without a cast or an ignore.Versions: sqlmodel 0.0.39, SQLAlchemy 2.1.0b3, Python 3.14.
A fix could be an
exec()overload acceptingCompoundSelect(orExecutable) that returnsResult[Any], similar to what #909 did for update/delete statements, or a tuple-result annotation that declaresscalars().All reactions