MagicStack / asyncpg

A fast PostgreSQL Database Client Library for Python/asyncio.
Apache License 2.0
6.99k stars 404 forks source link

Cannot use int as param in SELECT clause #998

Closed SirRhynus closed 1 year ago

SirRhynus commented 1 year ago

I want to for example execute the query SELECT 1 AS id; but with a param. So I used this function to test it out:

async def test():
    conn = await asyncpg.connect(db_uri)
    row = await conn.fetchrow('SELECT $1 AS id;', 1)
    print(row)
    await conn.close()

asyncio.run(test())

This results in the error: asyncpg.exceptions.DataError: invalid input for query argument $1: 1 (expected str, got int), even though it should be a perfectly good SQL query if it was an int.

aydabd commented 1 year ago

The error you encountered is due to the fact that the asyncpg library expects query arguments to be passed as strings. In your code, you're passing an integer (1) as the argument, which is causing the error. This is the correct one: row = await conn.fetchrow('SELECT $1 AS id;', str(1))

elprans commented 1 year ago

asyncpg does not expect arguments to be passed as strings, it expects them to correspond to the type of the argument inferred by Postgres. Type correspondence is documented here.

The issue here is that there is no context for Postgres to infer $1 as an integer, so it defaults to the default assumption that the argument is text. It is generally a good idea to avoid relying on argument type inference and instead always specify the argument type explicitly via a cast, like so:

select $1::int as id;