"""
Maps of builtin types and names
-
-You can update this file by executing it, using the PG* env var to connect
-to a Postgres server.
"""
# Copyright (C) 2020 The Psycopg Team
-import re
from typing import Dict, Iterator, Optional, Union
INVALID_OID = 0
builtins = TypesRegistry()
-# In order to update the registry, just execute this file, using the PG*
-# env vars to point to a running PostgreSQL instance of the desired version.
+# Use tools/update_oids.py to update this data.
for r in [
# fmt: off
# autogenerated: start
# fmt: on
]:
builtins.add(BuiltinTypeInfo(*r))
-
-
-def self_update() -> None:
- import subprocess as sp
-
- queries = [
- """
-select format($$
-# Generated from PostgreSQL %s.%s
-$$,
- setting::int / 10000, setting::int % 100) -- assume PG >= 10
- from pg_settings
- where name = 'server_version_num'
-""",
- r"""
-select format(
- '(%L, %s, %s, %L, %L),',
- typname, oid, typarray, oid::regtype, typdelim)
- from pg_type
- where oid < 10000
- and typname !~ all('{^(_|pg_|reg),_handler$}')
- order by typname
-""",
- ]
-
- with open(__file__, "rb") as f:
- lines = f.read().splitlines()
-
- new = []
- for query in queries:
- out = sp.run(
- ["psql", "-AXqt", "-c", query], stdout=sp.PIPE, check=True
- )
- new.extend(out.stdout.splitlines())
-
- new = [b" " * 4 + line if line else b"" for line in new] # indent
- istart, iend = [
- i
- for i, line in enumerate(lines)
- if re.match(br"\s*#\s*autogenerated:\s+(start|end)", line)
- ]
- lines[istart + 1 : iend] = new
-
- with open(__file__, "wb") as f:
- f.write(b"\n".join(lines))
- f.write(b"\n")
-
-
-if __name__ == "__main__":
- self_update()
--- /dev/null
+"""
+Constants to refer to OIDS in C
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+# Use tools/update_oids.py to update this data.
+
+cdef enum:
+ INVALID_OID = 0
+
+ # autogenerated: start
+
+ # Generated from PostgreSQL 13.0
+
+ ACLITEM_OID = 1033
+ ANY_OID = 2276
+ ANYARRAY_OID = 2277
+ ANYCOMPATIBLE_OID = 5077
+ ANYCOMPATIBLEARRAY_OID = 5078
+ ANYCOMPATIBLENONARRAY_OID = 5079
+ ANYCOMPATIBLERANGE_OID = 5080
+ ANYELEMENT_OID = 2283
+ ANYENUM_OID = 3500
+ ANYNONARRAY_OID = 2776
+ ANYRANGE_OID = 3831
+ BIT_OID = 1560
+ BOOL_OID = 16
+ BOX_OID = 603
+ BPCHAR_OID = 1042
+ BYTEA_OID = 17
+ CHAR_OID = 18
+ CID_OID = 29
+ CIDR_OID = 650
+ CIRCLE_OID = 718
+ CSTRING_OID = 2275
+ DATE_OID = 1082
+ DATERANGE_OID = 3912
+ EVENT_TRIGGER_OID = 3838
+ FLOAT4_OID = 700
+ FLOAT8_OID = 701
+ GTSVECTOR_OID = 3642
+ INET_OID = 869
+ INT2_OID = 21
+ INT2VECTOR_OID = 22
+ INT4_OID = 23
+ INT4RANGE_OID = 3904
+ INT8_OID = 20
+ INT8RANGE_OID = 3926
+ INTERNAL_OID = 2281
+ INTERVAL_OID = 1186
+ JSON_OID = 114
+ JSONB_OID = 3802
+ JSONPATH_OID = 4072
+ LINE_OID = 628
+ LSEG_OID = 601
+ MACADDR_OID = 829
+ MACADDR8_OID = 774
+ MONEY_OID = 790
+ NAME_OID = 19
+ NUMERIC_OID = 1700
+ NUMRANGE_OID = 3906
+ OID_OID = 26
+ OIDVECTOR_OID = 30
+ PATH_OID = 602
+ POINT_OID = 600
+ POLYGON_OID = 604
+ RECORD_OID = 2249
+ REFCURSOR_OID = 1790
+ TEXT_OID = 25
+ TID_OID = 27
+ TIME_OID = 1083
+ TIMESTAMP_OID = 1114
+ TIMESTAMPTZ_OID = 1184
+ TIMETZ_OID = 1266
+ TRIGGER_OID = 2279
+ TSQUERY_OID = 3615
+ TSRANGE_OID = 3908
+ TSTZRANGE_OID = 3910
+ TSVECTOR_OID = 3614
+ TXID_SNAPSHOT_OID = 2970
+ UNKNOWN_OID = 705
+ UUID_OID = 2950
+ VARBIT_OID = 1562
+ VARCHAR_OID = 1043
+ VOID_OID = 2278
+ XID_OID = 28
+ XID8_OID = 5069
+ XML_OID = 142
+ # autogenerated: end
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
-from psycopg3_c cimport libpq
+from psycopg3_c cimport libpq, oids
from psycopg3_c.pq_cython cimport PGresult
from psycopg3 import errors as e
from psycopg3.pq.enums import Format
-TEXT_OID = 25
-
cdef class RowLoader:
cdef object pyloader
break
else:
from psycopg3.adapt import Loader
- loader_cls = Loader.globals[0, format] # INVALID_OID
+ loader_cls = Loader.globals[oids.INVALID_OID, format]
self._loaders_cache[key] = loader = loader_cls(key[0], self)
return loader
# Copyright (C) 2020 The Psycopg Team
from libc.stdint cimport *
-from psycopg3_c.endian cimport be16toh, be32toh, be64toh, htobe64
-
from cpython.long cimport PyLong_FromString, PyLong_FromLong, PyLong_AsLongLong
from cpython.long cimport PyLong_FromLongLong, PyLong_FromUnsignedLong
from cpython.float cimport PyFloat_FromDouble
+from psycopg3_c cimport oids
+from psycopg3_c.endian cimport be16toh, be32toh, be64toh, htobe64
+
cdef extern from "Python.h":
# work around https://github.com/cython/cython/issues/3909
double PyOS_string_to_double(
cdef class IntDumper(CDumper):
- oid = 20 # TODO: int8 oid
+ oid = oids.INT8_OID
def dump(self, obj: Any) -> bytes:
cdef char buf[22]
cdef void register_numeric_c_adapters():
logger.debug("registering optimised numeric c adapters")
- from psycopg3.oids import builtins
-
IntDumper.register(int)
IntBinaryDumper.register_binary(int)
- IntLoader.register(builtins["int2"].oid)
- IntLoader.register(builtins["int4"].oid)
- IntLoader.register(builtins["int8"].oid)
- IntLoader.register(builtins["oid"].oid)
- FloatLoader.register(builtins["float4"].oid)
- FloatLoader.register(builtins["float8"].oid)
-
- Int2BinaryLoader.register_binary(builtins["int2"].oid)
- Int4BinaryLoader.register_binary(builtins["int4"].oid)
- Int8BinaryLoader.register_binary(builtins["int8"].oid)
- OidBinaryLoader.register_binary(builtins["oid"].oid)
- Float4BinaryLoader.register_binary(builtins["float4"].oid)
- Float8BinaryLoader.register_binary(builtins["float8"].oid)
+ IntLoader.register(oids.INT2_OID)
+ IntLoader.register(oids.INT4_OID)
+ IntLoader.register(oids.INT8_OID)
+ IntLoader.register(oids.OID_OID)
+ FloatLoader.register(oids.FLOAT4_OID)
+ FloatLoader.register(oids.FLOAT8_OID)
+
+ Int2BinaryLoader.register_binary(oids.INT2_OID)
+ Int4BinaryLoader.register_binary(oids.INT4_OID)
+ Int8BinaryLoader.register_binary(oids.INT8_OID)
+ OidBinaryLoader.register_binary(oids.OID_OID)
+ Float4BinaryLoader.register_binary(oids.FLOAT4_OID)
+ Float8BinaryLoader.register_binary(oids.FLOAT8_OID)
# Copyright (C) 2020 The Psycopg Team
+from psycopg3_c cimport oids
+
+
cdef class BoolDumper(CDumper):
- oid = 16 # TODO: bool oid
+ oid = oids.BOOL_OID
def dump(self, obj: bool) -> bytes:
# Fast paths, just a pointer comparison
cdef void register_singletons_c_adapters():
logger.debug("registering optimised singletons c adapters")
- from psycopg3.oids import builtins
-
BoolDumper.register(bool)
BoolBinaryDumper.register_binary(bool)
- BoolLoader.register(builtins["bool"].oid)
- BoolBinaryLoader.register_binary(builtins["bool"].oid)
+ BoolLoader.register(oids.BOOL_OID)
+ BoolBinaryLoader.register_binary(oids.BOOL_OID)
# Copyright (C) 2020 The Psycopg Team
from cpython.unicode cimport PyUnicode_Decode, PyUnicode_DecodeUTF8
-from psycopg3_c cimport libpq
+from psycopg3_c cimport libpq, oids
cdef class TextLoader(CLoader):
cdef void register_text_c_adapters():
logger.debug("registering optimised text c adapters")
- from psycopg3.oids import builtins
- from psycopg3.adapt import Loader
+ TextLoader.register(oids.INVALID_OID)
+ TextLoader.register(oids.TEXT_OID)
+ TextLoader.register_binary(oids.TEXT_OID)
+ TextLoader.register(oids.VARCHAR_OID)
+ TextLoader.register_binary(oids.VARCHAR_OID)
- TextLoader.register(0) # INVALID_OID
- TextLoader.register(builtins["text"].oid)
- TextLoader.register_binary(builtins["text"].oid)
- TextLoader.register(builtins["varchar"].oid)
- TextLoader.register_binary(builtins["varchar"].oid)
-
- ByteaLoader.register(builtins['bytea'].oid)
- ByteaBinaryLoader.register_binary(builtins['bytea'].oid)
+ ByteaLoader.register(oids.BYTEA_OID)
+ ByteaBinaryLoader.register_binary(oids.BYTEA_OID)
#!/usr/bin/env python
-"""Generate per-sqlstate errors from PostgreSQL source code.
+"""
+Generate per-sqlstate errors from PostgreSQL source code.
The script can be run at a new PostgreSQL release to refresh the module.
"""
from urllib.request import urlopen
from collections import defaultdict
-from psycopg3.errors import get_base_exception
+from psycopg3.errors import get_base_exception # type: ignore
logger = logging.getLogger()
logging.basicConfig(
--- /dev/null
+#!/usr/bin/env python
+"""
+Update the maps of builtin types and names.
+
+You can update this file by executing it, using the PG* env var to connect
+"""
+
+import os
+import re
+import subprocess as sp
+from typing import List
+
+
+version_sql = """
+select format($$
+# Generated from PostgreSQL %s.%s
+$$,
+ setting::int / 10000, setting::int % 100) -- assume PG >= 10
+ from pg_settings
+ where name = 'server_version_num'
+"""
+
+py_oids_sql = """
+select format(
+ '(%L, %s, %s, %L, %L),',
+ typname, oid, typarray, oid::regtype, typdelim)
+ from pg_type
+ where oid < 10000
+ and typname !~ all('{^(_|pg_|reg),_handler$}')
+ order by typname
+"""
+
+
+cython_oids_sql = """
+select format('%s_OID = %s', upper(typname), oid)
+ from pg_type
+ where oid < 10000
+ and typname !~ all('{^(_|pg_|reg),_handler$}')
+ order by typname
+"""
+
+
+def update_python_oids() -> None:
+ queries = [version_sql, py_oids_sql]
+ fn = os.path.dirname(__file__) + "/../psycopg3/psycopg3/oids.py"
+ update_file(fn, queries)
+
+
+def update_cython_oids() -> None:
+ queries = [version_sql, cython_oids_sql]
+ fn = os.path.dirname(__file__) + "/../psycopg3_c/psycopg3_c/oids.pxd"
+ update_file(fn, queries)
+
+
+def update_file(fn: str, queries: List[str]) -> None:
+ with open(fn, "rb") as f:
+ lines = f.read().splitlines()
+
+ new = []
+ for query in queries:
+ out = sp.run(
+ ["psql", "-AXqt", "-c", query], stdout=sp.PIPE, check=True
+ )
+ new.extend(out.stdout.splitlines())
+
+ new = [b" " * 4 + line if line else b"" for line in new] # indent
+ istart, iend = [
+ i
+ for i, line in enumerate(lines)
+ if re.match(br"\s*#\s*autogenerated:\s+(start|end)", line)
+ ]
+ lines[istart + 1 : iend] = new
+
+ with open(fn, "wb") as f:
+ f.write(b"\n".join(lines))
+ f.write(b"\n")
+
+
+if __name__ == "__main__":
+ update_python_oids()
+ update_cython_oids()