From 83ead8e9e2a2c2bb5d14ec834a5e81f74bccfeef Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 5 May 2020 06:26:26 +1200 Subject: [PATCH] Baby steps registering c optimised adapters Just registered some so far, not using the map yet --- .travis.yml | 6 +++++ psycopg3/__init__.py | 15 ++++++++++--- psycopg3/_psycopg3.pyx | 1 + psycopg3/adapt.pxd | 5 +++++ psycopg3/adapt.pyx | 46 ++++++++++++++++++++++++++++++++++++++ psycopg3/transform.pyx | 2 +- psycopg3/types/numeric.pxd | 6 +++++ 7 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 psycopg3/adapt.pxd create mode 100644 psycopg3/adapt.pyx create mode 100644 psycopg3/types/numeric.pxd diff --git a/.travis.yml b/.travis.yml index 89e1e5642..91bdee98e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,3 +81,9 @@ install: script: - tox + + +# This branch is still far from passing tests +branches: + except: + - cython diff --git a/psycopg3/__init__.py b/psycopg3/__init__.py index 23488315c..09c7fa173 100644 --- a/psycopg3/__init__.py +++ b/psycopg3/__init__.py @@ -4,6 +4,7 @@ psycopg3 -- PostgreSQL database adapter for Python # Copyright (C) 2020 The Psycopg Team +from . import pq from .consts import VERSION as __version__ # noqa from .connection import AsyncConnection, Connection @@ -20,9 +21,6 @@ from .errors import ( NotSupportedError, ) -# register default adapters -from . import types # noqa - from .dbapi20 import BINARY, DATETIME, NUMBER, ROWID, STRING from .dbapi20 import Binary, Date, DateFromTicks, Time, TimeFromTicks from .dbapi20 import Timestamp, TimestampFromTicks @@ -33,6 +31,17 @@ apilevel = "2.0" threadsafety = 2 paramstyle = "pyformat" + +# register default adapters +from . import types # noqa + +# Override adapters with fast version if available +if pq.__impl__ == "c": + from ._psycopg3 import register_builtin_c_loaders + + register_builtin_c_loaders() + + __all__ = ( ["Warning", "Error", "InterfaceError", "DatabaseError", "DataError"] + ["OperationalError", "IntegrityError", "InternalError"] diff --git a/psycopg3/_psycopg3.pyx b/psycopg3/_psycopg3.pyx index 007af0a48..0ab2fa969 100644 --- a/psycopg3/_psycopg3.pyx +++ b/psycopg3/_psycopg3.pyx @@ -1,3 +1,4 @@ include "types/numeric.pyx" include "types/text.pyx" +include "adapt.pyx" include "transform.pyx" diff --git a/psycopg3/adapt.pxd b/psycopg3/adapt.pxd new file mode 100644 index 000000000..feb109746 --- /dev/null +++ b/psycopg3/adapt.pxd @@ -0,0 +1,5 @@ + +ctypedef object (*cloader_func)(const char *data, size_t length, void *context) +# ctypedef void * (*get_context_func)(PGconn_ptr conn) + +cdef void register_c_loader(object pyloader, cloader_func cloader) diff --git a/psycopg3/adapt.pyx b/psycopg3/adapt.pyx new file mode 100644 index 000000000..aa35c8d91 --- /dev/null +++ b/psycopg3/adapt.pyx @@ -0,0 +1,46 @@ +from psycopg3.adapt cimport cloader_func + +from psycopg3.types cimport numeric + + +import logging +logger = logging.getLogger("psycopg3.adapt") + + +cdef class CLoader: + cdef object pyloader + cdef cloader_func cloader + + +cloaders = {} + +cdef void register_c_loader(object pyloader, cloader_func cloader): + """ + Map a python loader to an optimised C version. + + Whenever the python loader would be used the C version may be chosen in + preference. + """ + cdef CLoader cl = CLoader() + cl.pyloader = pyloader + cl.cloader = cloader + cloaders[pyloader] = cl + + +def register_builtin_c_loaders(): + if cloaders: + logger.warning("c loaders already registered") + return + + logger.debug("registering optimised c loaders") + register_numeric_c_loaders() + + +cdef void register_numeric_c_loaders(): + logger.debug("registering optimised numeric c loaders") + from psycopg3.types import numeric + register_c_loader(numeric.load_int, load_int_text) + register_c_loader(numeric.load_int2_binary, load_int2_binary) + register_c_loader(numeric.load_int4_binary, load_int4_binary) + register_c_loader(numeric.load_int8_binary, load_int8_binary) + register_c_loader(numeric.load_oid_binary, load_oid_binary) diff --git a/psycopg3/transform.pyx b/psycopg3/transform.pyx index 52eb9d4e8..3967d815b 100644 --- a/psycopg3/transform.pyx +++ b/psycopg3/transform.pyx @@ -9,6 +9,7 @@ from typing import Any, Dict, Iterable, List, Optional, Tuple from psycopg3.pq cimport libpq from psycopg3.pq.pq_cython cimport PGresult +from psycopg3.adapt cimport cloader_func from psycopg3 import errors as e from psycopg3.pq.enums import Format @@ -17,7 +18,6 @@ from psycopg3.pq.enums import Format TEXT_OID = 25 -ctypedef object (*cloader_func)(const char *data, size_t length, void *context) cdef struct RowLoader: PyObject *pyloader # borrowed diff --git a/psycopg3/types/numeric.pxd b/psycopg3/types/numeric.pxd new file mode 100644 index 000000000..dce56be9f --- /dev/null +++ b/psycopg3/types/numeric.pxd @@ -0,0 +1,6 @@ +cdef object load_int_text(const char *data, size_t length, void *context) +cdef object load_int2_binary(const char *data, size_t length, void *context) +cdef object load_int4_binary(const char *data, size_t length, void *context) +cdef object load_int8_binary(const char *data, size_t length, void *context) +cdef object load_oid_binary(const char *data, size_t length, void *context) +cdef object load_bool_binary(const char *data, size_t length, void *context) -- 2.47.2