asyncpg dialect improperly coerces the BigInteger type when passing it to the function polymorphic in its arguments #7814
-
Describe the bugSo, this is a really minor bug, which can be also related to asyncpg but I am not sure. The problem emerges when using asyncpg, it is not present when using psycopg2. It is easily reproducible, so I will let the code to speak for itself. Take following statement:
When executed, it should fire the postgres
In our case, this is the first version which should be executed. And it does, but only if using
The reason I think that this is a problem with SQLAlchemy, is that You can easily overcome this issue with explicit type coertion, which is a part of SQLAlchemy API. Use following statement:
And everything runs flawlessly. To Reproducefrom sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy import select, func, BigInteger
from sqlalchemy.sql.expression import type_coerce
import asyncio
engine = create_async_engine(
"postgresql+asyncpg://postgres:1234567890@localhost:6543/postgres",
echo=True,
)
SessionLocal = sessionmaker(
class_=AsyncSession,
autocommit=False,
autoflush=False,
expire_on_commit=False,
future=True,
bind=engine,
)
async def main():
lock_id_64bit = 4944215145091319531
async with SessionLocal() as session:
# stmt = f"SELECT pg_try_advisory_lock({lock_id_64bit})"
stmt = select(
# This will work:
# func.pg_try_advisory_lock(type_coerce(lock_id_64bit, BigInteger()))
# But this not (only when using AsyncIO api, synchronous runs this without issues)
func.pg_try_advisory_lock(lock_id_64bit)
)
result = (await session.execute(stmt)).scalar_one()
print(result)
if __name__ == "__main__":
asyncio.run(main()) ErrorFull traceback:
VersionsSystem info
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 9 replies
-
Hi, sqlalchemy tries to guess what type to use based on the in argument. since python has only one kind of integer, that's what guessed. You can specify a type on the function, doing I think this is an expected behaviour, since |
Beta Was this translation helpful? Give feedback.
-
@CaselIT Yes, this would not bother me in any way, but... |
Beta Was this translation helpful? Give feedback.
-
this should be working in 2.0 / github main. have we confirmed that? |
Beta Was this translation helpful? Give feedback.
Hi,
sqlalchemy tries to guess what type to use based on the in argument. since python has only one kind of integer, that's what guessed. You can specify a type on the function, doing
select(func.pg_try_advisory_lock(lock_id_64bit, type_=BigInteger)
I think this is an expected behaviour, since
pg_try_advisory_lock
uses a generic function, so it has to guess the type from the arguments.