Closed
Description
I'm using asyncpg 0.10.1, Python 3.6.1 and PostgreSQL 9.6.2.
I started to hit a strange problem this morning, with a query involving a DateRange
column. I was really surprised, because the query is almost equivalent to several others, and it took several hours to distill the even more surprising script:
import sys
import asyncio
import asyncpg
SQL1 = """\
SELECT r.size AS "Size",
r.validity
FROM shelf.attachments AS a
JOIN shelf.resources AS r ON r.id = a.resource_id
WHERE a.object_kind = $1::notable_t
AND a.object_id = $2::UUID
"""
SQL2 = """\
SELECT a.id,
a.resource_id
FROM shelf.attachments AS a
WHERE a.object_kind = $1::notable_t
AND a.object_id = $2::UUID
"""
async def run(order):
conn = await asyncpg.connect(user='user', password='password',
database='database', host='127.0.0.1', port=5423)
if order == 'good':
stmts = [SQL2, SQL1]
else:
stmts = [SQL1, SQL2]
for stmt in stmts:
values = await conn.fetch(stmt, 'risk.Company', '3332bc6c-3319-11e7-a713-0242ac120002')
print(values)
await conn.close()
def main():
loop = asyncio.get_event_loop()
loop.run_until_complete(run('good' if len(sys.argv) == 1 else 'bad'))
if __name__ == '__main__':
main()
Executing the script without arguments, I get:
$ python test1.py
[<Record id=UUID('333b8f86-3319-11e7-a713-0242ac120002') resource_id=UUID('33385b9a-3319-11e7-a713-0242ac120002')>]
[<Record Size=59329 validity=<Range [datetime.date(2017, 5, 7), datetime.date(9999, 12, 31))>>]
With an arbitrary argument the script executes the statements in a different order, and I get:
$ python test1.py foo
Traceback (most recent call last):
File "test1.py", line 47, in <module>
main()
File "test1.py", line 43, in main
loop.run_until_complete(run('good' if len(sys.argv) == 1 else 'bad'))
File ".../python3.6/asyncio/base_events.py", line 466, in run_until_complete
return future.result()
File "test1.py", line 35, in run
values = await conn.fetch(stmt, 'risk.Company', '3332bc6c-3319-11e7-a713-0242ac120002')
File "/tmp/apg/lib/python3.6/site-packages/asyncpg/connection.py", line 340, in fetch
return await self._execute(query, args, 0, timeout)
File "/tmp/apg/lib/python3.6/site-packages/asyncpg/connection.py", line 651, in _execute
return await self._do_execute(query, executor, timeout)
File "/tmp/apg/lib/python3.6/site-packages/asyncpg/connection.py", line 672, in _do_execute
result = await executor(stmt, None)
File "asyncpg/protocol/protocol.pyx", line 162, in bind_execute (asyncpg/protocol/protocol.c:57595)
File "asyncpg/protocol/prepared_stmt.pyx", line 95, in asyncpg.protocol.protocol.PreparedStatementState._encode_bind_msg (asyncpg/protocol/protocol.c:53417)
File "asyncpg/protocol/prepared_stmt.pyx", line 162, in asyncpg.protocol.protocol.PreparedStatementState._ensure_rows_decoder (asyncpg/protocol/protocol.c:54254)
RuntimeError: no decoder for OID 3912
In other words, it seems that the source of the problem is not the statement itself, but rather when it gets executed.
If needed, I'm willing to try to reproduce the issue with plain data types: above, the notable_t
is an enum
defined as
CREATE TYPE notable_t AS ENUM (
'risk.Company',
'risk.CompanySite',
....
)