From 711bc65221c831a04ea6b737a64ca7aee72c094e Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Thu, 26 Nov 2020 19:18:11 -0800 Subject: [PATCH] Add codecs for a bunch of new builtin types The last round of support for esoteric builtin types was quite a while ago, so catch up. Out of non-internal types this adds support for the new `jsonpath` type. Fixes: #635. --- asyncpg/pgproto | 2 +- asyncpg/protocol/codecs/pgproto.pyx | 39 +++++++++++++++++++++++++---- asyncpg/protocol/pgtypes.pxi | 22 +++++++++++++++- tests/test_codecs.py | 16 ++++++++++++ tools/generate_type_map.py | 6 +++++ 5 files changed, 78 insertions(+), 7 deletions(-) diff --git a/asyncpg/pgproto b/asyncpg/pgproto index 2dc7cc46..126bcd24 160000 --- a/asyncpg/pgproto +++ b/asyncpg/pgproto @@ -1 +1 @@ -Subproject commit 2dc7cc4635b08418dfbc6105b45947244102e86d +Subproject commit 126bcd24bd3c59d581613dae026e2721efbedf16 diff --git a/asyncpg/protocol/codecs/pgproto.pyx b/asyncpg/protocol/codecs/pgproto.pyx index accebcd2..11417d45 100644 --- a/asyncpg/protocol/codecs/pgproto.pyx +++ b/asyncpg/protocol/codecs/pgproto.pyx @@ -180,6 +180,10 @@ cdef init_json_codecs(): pgproto.jsonb_encode, pgproto.jsonb_decode, PG_FORMAT_BINARY) + register_core_codec(JSONPATHOID, + pgproto.jsonpath_encode, + pgproto.jsonpath_decode, + PG_FORMAT_BINARY) cdef init_int_codecs(): @@ -229,6 +233,17 @@ cdef init_pseudo_codecs(): pgproto.uint4_decode, PG_FORMAT_BINARY) + # 64-bit OID types + oid8_types = [ + XID8OID, + ] + + for oid_type in oid8_types: + register_core_codec(oid_type, + pgproto.uint8_encode, + pgproto.uint8_decode, + PG_FORMAT_BINARY) + # reg* types -- these are really system catalog OIDs, but # allow the catalog object name as an input. We could just # decode these as OIDs, but handling them as text seems more @@ -237,7 +252,7 @@ cdef init_pseudo_codecs(): reg_types = [ REGPROCOID, REGPROCEDUREOID, REGOPEROID, REGOPERATOROID, REGCLASSOID, REGTYPEOID, REGCONFIGOID, REGDICTIONARYOID, - REGNAMESPACEOID, REGROLEOID, REFCURSOROID + REGNAMESPACEOID, REGROLEOID, REFCURSOROID, REGCOLLATIONOID, ] for reg_type in reg_types: @@ -256,8 +271,10 @@ cdef init_pseudo_codecs(): no_io_types = [ ANYOID, TRIGGEROID, EVENT_TRIGGEROID, LANGUAGE_HANDLEROID, FDW_HANDLEROID, TSM_HANDLEROID, INTERNALOID, OPAQUEOID, - ANYELEMENTOID, ANYNONARRAYOID, PG_DDL_COMMANDOID, - INDEX_AM_HANDLEROID, + ANYELEMENTOID, ANYNONARRAYOID, ANYCOMPATIBLEOID, + ANYCOMPATIBLEARRAYOID, ANYCOMPATIBLENONARRAYOID, + ANYCOMPATIBLERANGEOID, PG_DDL_COMMANDOID, INDEX_AM_HANDLEROID, + TABLE_AM_HANDLEROID, ] register_core_codec(ANYENUMOID, @@ -306,6 +323,13 @@ cdef init_pseudo_codecs(): pgproto.text_decode, PG_FORMAT_TEXT) + # pg_mcv_list is a special type used in pg_statistic_ext_data + # system catalog + register_core_codec(PG_MCV_LISTOID, + pgproto.bytea_encode, + pgproto.bytea_decode, + PG_FORMAT_BINARY) + cdef init_text_codecs(): textoids = [ @@ -337,8 +361,13 @@ cdef init_tid_codecs(): cdef init_txid_codecs(): register_core_codec(TXID_SNAPSHOTOID, - pgproto.txid_snapshot_encode, - pgproto.txid_snapshot_decode, + pgproto.pg_snapshot_encode, + pgproto.pg_snapshot_decode, + PG_FORMAT_BINARY) + + register_core_codec(PG_SNAPSHOTOID, + pgproto.pg_snapshot_encode, + pgproto.pg_snapshot_decode, PG_FORMAT_BINARY) diff --git a/asyncpg/protocol/pgtypes.pxi b/asyncpg/protocol/pgtypes.pxi index 1be40fb2..d0cc22a6 100644 --- a/asyncpg/protocol/pgtypes.pxi +++ b/asyncpg/protocol/pgtypes.pxi @@ -10,7 +10,7 @@ DEF INVALIDOID = 0 DEF MAXBUILTINOID = 9999 -DEF MAXSUPPORTEDOID = 4096 +DEF MAXSUPPORTEDOID = 5080 DEF BOOLOID = 16 DEF BYTEAOID = 17 @@ -30,6 +30,7 @@ DEF JSONOID = 114 DEF XMLOID = 142 DEF PG_NODE_TREEOID = 194 DEF SMGROID = 210 +DEF TABLE_AM_HANDLEROID = 269 DEF INDEX_AM_HANDLEROID = 325 DEF POINTOID = 600 DEF LSEGOID = 601 @@ -96,8 +97,17 @@ DEF REGDICTIONARYOID = 3769 DEF JSONBOID = 3802 DEF ANYRANGEOID = 3831 DEF EVENT_TRIGGEROID = 3838 +DEF JSONPATHOID = 4072 DEF REGNAMESPACEOID = 4089 DEF REGROLEOID = 4096 +DEF REGCOLLATIONOID = 4191 +DEF PG_MCV_LISTOID = 5017 +DEF PG_SNAPSHOTOID = 5038 +DEF XID8OID = 5069 +DEF ANYCOMPATIBLEOID = 5077 +DEF ANYCOMPATIBLEARRAYOID = 5078 +DEF ANYCOMPATIBLENONARRAYOID = 5079 +DEF ANYCOMPATIBLERANGEOID = 5080 cdef ARRAY_TYPES = (_TEXTOID, _OIDOID,) @@ -105,6 +115,10 @@ BUILTIN_TYPE_OID_MAP = { ABSTIMEOID: 'abstime', ACLITEMOID: 'aclitem', ANYARRAYOID: 'anyarray', + ANYCOMPATIBLEARRAYOID: 'anycompatiblearray', + ANYCOMPATIBLENONARRAYOID: 'anycompatiblenonarray', + ANYCOMPATIBLEOID: 'anycompatible', + ANYCOMPATIBLERANGEOID: 'anycompatiblerange', ANYELEMENTOID: 'anyelement', ANYENUMOID: 'anyenum', ANYNONARRAYOID: 'anynonarray', @@ -135,6 +149,7 @@ BUILTIN_TYPE_OID_MAP = { INTERVALOID: 'interval', JSONBOID: 'jsonb', JSONOID: 'json', + JSONPATHOID: 'jsonpath', LANGUAGE_HANDLEROID: 'language_handler', LINEOID: 'line', LSEGOID: 'lseg', @@ -149,13 +164,16 @@ BUILTIN_TYPE_OID_MAP = { PG_DDL_COMMANDOID: 'pg_ddl_command', PG_DEPENDENCIESOID: 'pg_dependencies', PG_LSNOID: 'pg_lsn', + PG_MCV_LISTOID: 'pg_mcv_list', PG_NDISTINCTOID: 'pg_ndistinct', PG_NODE_TREEOID: 'pg_node_tree', + PG_SNAPSHOTOID: 'pg_snapshot', POINTOID: 'point', POLYGONOID: 'polygon', RECORDOID: 'record', REFCURSOROID: 'refcursor', REGCLASSOID: 'regclass', + REGCOLLATIONOID: 'regcollation', REGCONFIGOID: 'regconfig', REGDICTIONARYOID: 'regdictionary', REGNAMESPACEOID: 'regnamespace', @@ -167,6 +185,7 @@ BUILTIN_TYPE_OID_MAP = { REGTYPEOID: 'regtype', RELTIMEOID: 'reltime', SMGROID: 'smgr', + TABLE_AM_HANDLEROID: 'table_am_handler', TEXTOID: 'text', TIDOID: 'tid', TIMEOID: 'time', @@ -184,6 +203,7 @@ BUILTIN_TYPE_OID_MAP = { VARBITOID: 'varbit', VARCHAROID: 'varchar', VOIDOID: 'void', + XID8OID: 'xid8', XIDOID: 'xid', XMLOID: 'xml', _OIDOID: 'oid[]', diff --git a/tests/test_codecs.py b/tests/test_codecs.py index 8ecbd092..33409911 100644 --- a/tests/test_codecs.py +++ b/tests/test_codecs.py @@ -271,6 +271,9 @@ def _system_timezone(): '[1, 2, 3, 4]', '{"a": [1, 2], "b": 0}' ], (9, 4)), + ('jsonpath', 'jsonpath', [ + '$."track"."segments"[*]."HR"?(@ > 130)', + ], (12, 0)), ('oid[]', 'oid[]', [ [1, 2, 3, 4], [] @@ -389,6 +392,19 @@ def _system_timezone(): ('txid_snapshot', 'txid_snapshot', [ (100, 1000, (100, 200, 300, 400)) ]), + ('pg_snapshot', 'pg_snapshot', [ + (100, 1000, (100, 200, 300, 400)) + ], (13, 0)), + ('xid', 'xid', ( + 2 ** 32 - 1, + 0, + 1, + )), + ('xid8', 'xid8', ( + 2 ** 64 - 1, + 0, + 1, + ), (13, 0)), ('varbit', 'varbit', [ asyncpg.BitString('0000 0001'), asyncpg.BitString('00010001'), diff --git a/tools/generate_type_map.py b/tools/generate_type_map.py index e8f14504..8fa816a4 100755 --- a/tools/generate_type_map.py +++ b/tools/generate_type_map.py @@ -33,7 +33,13 @@ 'real': 'float4', 'double precision': 'float8', 'timestamp with timezone': 'timestamptz', + 'timestamp without timezone': 'timestamp', 'time with timezone': 'timetz', + 'time without timezone': 'time', + 'char': 'bpchar', + 'character': 'bpchar', + 'character varying': 'varchar', + 'bit varying': 'varbit' }