MagicStack / MagicStack/asyncpg
Cannot use custom codec for non-scalar type
還沒有人認領這個 Issue。
- 主要語言
- Python
- 星號
- 8.1k
- 分支
- 468
- PR 合併指標
- 30 天內沒有已合併 PR
描述
- asyncpg version: 0.18.3
- PostgreSQL version: AgensGraph 2.1.0, based on PostgreSQL 10.4
- Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
the issue with a local PostgreSQL install?: Does not apply - Python version: 3.7.2
- Platform: Ubuntu 16.04.3 LTS
- Do you use pgbouncer?: No
- Did you install asyncpg with pip?: Yes
- If you built asyncpg locally, which version of Cython did you use?: Not relevant
- Can the issue be reproduced under both asyncio and
uvloop?: Not relevant
I'm trying to use asyncpg for communication with AgensGraph. It is graph database build on top of PostgreSQL 10.4. Bitnine provides client agensgraph-python for it, but is built on top of
psycopg2 and therefore dosn't support async.
I've tried to simply use asyncpg instead with following simple example:
import asyncio
import asyncpg
async def run():
conn = await asyncpg.connect(
database = 'agens',
user = 'agens',
host = '127.0.0.1',
port = 5435
)
await conn.execute('''
DROP GRAPH IF EXISTS t CASCADE;
CREATE GRAPH t;
SET graph_path = t;
CREATE (:v {name: 'AgensGraph'});
''')
values = await conn.fetch("MATCH (n) RETURN n")
print(values)
await conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
got following exception:
Traceback (most recent call last):
File "example_script.py", line 56, in <module>
loop.run_until_complete(run())
File "/home/ondrej_zapletal/.pyenv/versions/3.7.2/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "example_script.py", line 50, in run
values = await conn.fetch("MATCH (n) RETURN n")
File "/home/ondrej_zapletal/.pyenv/versions/squid/lib/python3.7/site-packages/asyncpg/connection.py", line 421, in fetch
return await self._execute(query, args, 0, timeout)
File "/home/ondrej_zapletal/.pyenv/versions/squid/lib/python3.7/site-packages/asyncpg/connection.py", line 1414, in _execute
query, args, limit, timeout, return_status=return_status)
File "/home/ondrej_zapletal/.pyenv/versions/squid/lib/python3.7/site-packages/asyncpg/connection.py", line 1422, in __execute
return await self._do_execute(query, executor, timeout)
File "/home/ondrej_zapletal/.pyenv/versions/squid/lib/python3.7/site-packages/asyncpg/connection.py", line 1434, in _do_execute
stmt = await self._get_statement(query, None)
File "/home/ondrej_zapletal/.pyenv/versions/squid/lib/python3.7/site-packages/asyncpg/connection.py", line 341, in _get_statement
settings.register_data_types(types)
File "asyncpg/protocol/settings.pyx", line 35, in asyncpg.protocol.protocol.ConnectionSettings.register_data_types
File "asyncpg/protocol/settings.pyx", line 36, in asyncpg.protocol.protocol.ConnectionSettings.register_data_types
File "asyncpg/protocol/codecs/base.pyx", line 563, in asyncpg.protocol.protocol.DataCodecConfig.add_types
File "asyncpg/protocol/codecs/base.pyx", line 677, in asyncpg.protocol.protocol.DataCodecConfig.declare_fallback_codec
NotImplementedError: unhandled standard data type 'graphid' (OID 7002)
I've looked at agensgraph-python implementation and it seems fairly straight forward.
It simply adds new types [GRAPHID, VERTEX, EDGE, GRAPHPATH]. Like this:
I've tried to use set_type_codec to define those, but I've come across this error:
My question is why it isn't allowed to add codecs for composite types?
I've overcame this problem temporarily by patching set_type_codec in following way:
import asyncio
import asyncpg
async def set_type_codec(conn, typenames):
schema='pg_catalog'
format='text'
conn._check_open()
for typename in typenames:
typeinfo = await conn.fetchrow(
asyncpg.introspection.TYPE_BY_NAME, typename, schema)
if not typeinfo:
raise ValueError('unknown type: {}.{}'.format(schema, typename))
oid = typeinfo['oid']
conn._protocol.get_settings().add_python_codec(
oid, typename, schema, 'scalar',
lambda a: a, lambda a: a, format)
# Statement cache is no longer valid due to codec changes.
conn._drop_local_statement_cache()
async def run():
conn = await asyncpg.connect(
database = 'agens',
user = 'agens',
host = '127.0.0.1',
port = 5435
)
await set_type_codec(conn, ['graphid', 'vertex', 'edge', 'graphpath'])
await conn.execute('''
DROP GRAPH IF EXISTS t CASCADE;
CREATE GRAPH t;
SET graph_path = t;
CREATE (:v {name: 'AgensGraph'});
CREATE (:v {name: 'OtherData'});
''')
values = await conn.fetch("MATCH (n) RETURN n")
print(values)
await conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
This seems to work for me so far, but I'm not sure if I won't come across some additional issues due to this in the future.
貢獻指南
這個儲存庫沒有索引到貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
閱讀 asyncpg/connection.py 中 set_type_codec 附近的程式碼,然後檢查 asyncpg/protocol/settings.pyx 和 asyncpg/protocol/codecs/base.pyx,複合型別的拒絕發生在這裡。重現 AgensGraph 的 graphid/vertex/edge/graphpath 情況,並驗證無需私有修補程式即可為這些型別註冊自訂 codecs,同時 MATCH 查詢仍能正常運作。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- postgresql, python
- 領域
- databases
- Issue 類型
- 功能
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 停滯
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100