from psycopg3 import adapt
from psycopg3.types import text
register_c_loader(text.StringLoader.load, load_text, get_context_text)
+ register_c_loader(text.NameLoader.load, load_text, get_context_text)
+ register_c_loader(text.load_bytea_text, load_bytea_text)
+ register_c_loader(text.load_bytea_binary, load_bytea_binary)
register_c_loader(adapt.UnknownLoader.load, load_unknown_text)
register_c_loader(adapt.load_unknown_binary, load_unknown_binary)
@Loader.text(builtins["bytea"].oid)
-def load_bytea(data: bytes) -> bytes:
+def load_bytea_text(data: bytes) -> bytes:
return Escaping().unescape_bytea(data)
from cpython.bytes cimport PyBytes_FromStringAndSize
from cpython.unicode cimport PyUnicode_DecodeUTF8
+from psycopg3.pq cimport libpq
cdef object load_text(const char *data, size_t length, void *context):
return NULL
+cdef object load_bytea_text(const char *data, size_t length, void *context):
+ cdef size_t len_out
+ cdef unsigned char *out = libpq.PQunescapeBytea(
+ <const unsigned char *>data, &len_out)
+ if out is NULL:
+ raise MemoryError(
+ f"couldn't allocate for unescape_bytea of {len(data)} bytes"
+ )
+
+ rv = out[:len_out]
+ libpq.PQfreemem(out)
+ return rv
+
+
+cdef object load_bytea_binary(const char *data, size_t length, void *context):
+ return data[:length]
+
+
cdef object load_unknown_text(const char *data, size_t length, void *context):
# TODO: codec
return PyUnicode_DecodeUTF8(data, length, NULL)