From 6f0b6db6f95bcad4be47ecea99732c3f17073e7d Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Wed, 23 Dec 2020 22:02:19 +0100 Subject: [PATCH] Register automatically the array loader on all the builtins Also added reg* types to the known builtins. This way regtype[] is loaded as a list of strings. --- psycopg3/psycopg3/oids.py | 11 +++++++++++ psycopg3/psycopg3/types/array.py | 6 ++---- psycopg3_c/psycopg3_c/oids.pxd | 11 +++++++++++ tests/types/test_array.py | 30 ++++++++++++++++++++++-------- tools/update_oids.py | 4 ++-- 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/psycopg3/psycopg3/oids.py b/psycopg3/psycopg3/oids.py index c8791a007..ccaef1f88 100644 --- a/psycopg3/psycopg3/oids.py +++ b/psycopg3/psycopg3/oids.py @@ -142,6 +142,17 @@ for r in [ ('polygon', 604, 1027, 'polygon', ','), ('record', 2249, 2287, 'record', ','), ('refcursor', 1790, 2201, 'refcursor', ','), + ('regclass', 2205, 2210, 'regclass', ','), + ('regcollation', 4191, 4192, 'regcollation', ','), + ('regconfig', 3734, 3735, 'regconfig', ','), + ('regdictionary', 3769, 3770, 'regdictionary', ','), + ('regnamespace', 4089, 4090, 'regnamespace', ','), + ('regoper', 2203, 2208, 'regoper', ','), + ('regoperator', 2204, 2209, 'regoperator', ','), + ('regproc', 24, 1008, 'regproc', ','), + ('regprocedure', 2202, 2207, 'regprocedure', ','), + ('regrole', 4096, 4097, 'regrole', ','), + ('regtype', 2206, 2211, 'regtype', ','), ('text', 25, 1009, 'text', ','), ('tid', 27, 1010, 'tid', ','), ('time', 1083, 1183, 'time without time zone', ','), diff --git a/psycopg3/psycopg3/types/array.py b/psycopg3/psycopg3/types/array.py index 6599e3339..7cfe8cc18 100644 --- a/psycopg3/psycopg3/types/array.py +++ b/psycopg3/psycopg3/types/array.py @@ -291,8 +291,6 @@ def register_all_arrays() -> None: registered all the base loaders. """ for t in builtins: - if t.array_oid and ( - (t.oid, Format.TEXT) in Loader.globals - or (t.oid, Format.BINARY) in Loader.globals - ): + # TODO: handle different delimiters (box) + if t.array_oid and getattr(t, "delimiter", None) == ",": register(t.array_oid, t.oid, name=t.name) diff --git a/psycopg3_c/psycopg3_c/oids.pxd b/psycopg3_c/psycopg3_c/oids.pxd index d5b0b12a8..711ffdc3d 100644 --- a/psycopg3_c/psycopg3_c/oids.pxd +++ b/psycopg3_c/psycopg3_c/oids.pxd @@ -67,6 +67,17 @@ cdef enum: POLYGON_OID = 604 RECORD_OID = 2249 REFCURSOR_OID = 1790 + REGCLASS_OID = 2205 + REGCOLLATION_OID = 4191 + REGCONFIG_OID = 3734 + REGDICTIONARY_OID = 3769 + REGNAMESPACE_OID = 4089 + REGOPER_OID = 2203 + REGOPERATOR_OID = 2204 + REGPROC_OID = 24 + REGPROCEDURE_OID = 2202 + REGROLE_OID = 4096 + REGTYPE_OID = 2206 TEXT_OID = 25 TID_OID = 27 TIME_OID = 1083 diff --git a/tests/types/test_array.py b/tests/types/test_array.py index b2a983327..591901cfa 100644 --- a/tests/types/test_array.py +++ b/tests/types/test_array.py @@ -101,18 +101,32 @@ def test_load_list_int(conn, obj, want, fmt_out): def test_array_register(conn): - # unknown for real cur = conn.cursor() - cur.execute("select '{postgres=arwdDxt/postgres}'::aclitem[]") - res = cur.fetchone()[0] - assert res == "{postgres=arwdDxt/postgres}" + cur.execute("create table mytype (data text)") + cur.execute("""select '(foo)'::mytype, '{"(foo)"}'::mytype[]""") + res = cur.fetchone() + assert res[0] == "(foo)" + assert res[1] == "{(foo)}" array.register( - builtins["aclitem"].array_oid, builtins["aclitem"].oid, context=conn + cur.description[1].type_code, cur.description[0].type_code, context=cur ) - cur.execute("select '{postgres=arwdDxt/postgres}'::aclitem[]") - res = cur.fetchone()[0] - assert res == ["postgres=arwdDxt/postgres"] + cur.execute("""select '(foo)'::mytype, '{"(foo)"}'::mytype[]""") + res = cur.fetchone() + assert res[0] == "(foo)" + assert res[1] == ["(foo)"] + + +def test_array_of_unknown_builtin(conn): + # we cannot load this type, but we understand it is an array + val = "postgres=arwdDxt/postgres" + cur = conn.cursor() + cur.execute(f"select '{val}'::aclitem, array['{val}']::aclitem[]") + res = cur.fetchone() + assert cur.description[0].type_code == builtins["aclitem"].oid + assert res[0] == val + assert cur.description[1].type_code == builtins["aclitem"].array_oid + assert res[1] == [val] @pytest.mark.xfail diff --git a/tools/update_oids.py b/tools/update_oids.py index edfd05c72..0cbbea4af 100755 --- a/tools/update_oids.py +++ b/tools/update_oids.py @@ -26,7 +26,7 @@ select format( typname, oid, typarray, oid::regtype, typdelim) from pg_type where oid < 10000 - and typname !~ all('{^(_|pg_|reg),_handler$}') + and typname !~ all('{^(_|pg_),_handler$}') order by typname """ @@ -35,7 +35,7 @@ cython_oids_sql = """ select format('%s_OID = %s', upper(typname), oid) from pg_type where oid < 10000 - and typname !~ all('{^(_|pg_|reg),_handler$}') + and typname !~ all('{^(_|pg_),_handler$}') order by typname """ -- 2.47.2