From: Daniele Varrazzo Date: Sun, 20 Dec 2020 23:36:19 +0000 (+0100) Subject: Escaping code moved to psycopg3_c/pq dir X-Git-Tag: 3.0.dev0~252^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=721b0d4af8962cb573736b8e706204f42f9fa11c;p=thirdparty%2Fpsycopg.git Escaping code moved to psycopg3_c/pq dir --- diff --git a/psycopg3_c/psycopg3_c/pq/escaping.pyx b/psycopg3_c/psycopg3_c/pq/escaping.pyx new file mode 100644 index 000000000..210b86728 --- /dev/null +++ b/psycopg3_c/psycopg3_c/pq/escaping.pyx @@ -0,0 +1,127 @@ +""" +psycopg3_c.pq_cython.Escaping object implementation. +""" + +# Copyright (C) 2020 The Psycopg Team + +from psycopg3_c.pq_cython cimport PGconn + + +cdef class Escaping: + def __init__(self, conn: Optional[PGconn] = None): + self.conn = conn + + def escape_literal(self, data: "Buffer") -> memoryview: + cdef char *out + cdef bytes rv + cdef char *ptr + cdef Py_ssize_t length + + if self.conn is None: + raise PQerror("escape_literal failed: no connection provided") + if self.conn.pgconn_ptr is NULL: + raise PQerror("the connection is closed") + + _buffer_as_string_and_size(data, &ptr, &length) + + out = impl.PQescapeLiteral(self.conn.pgconn_ptr, ptr, length) + if out is NULL: + raise PQerror( + f"escape_literal failed: {error_message(self.conn)}" + ) + + return memoryview(PQBuffer._from_buffer(out, strlen(out))) + + def escape_identifier(self, data: "Buffer") -> memoryview: + cdef char *out + cdef char *ptr + cdef Py_ssize_t length + + _buffer_as_string_and_size(data, &ptr, &length) + + if self.conn is None: + raise PQerror("escape_identifier failed: no connection provided") + if self.conn.pgconn_ptr is NULL: + raise PQerror("the connection is closed") + + out = impl.PQescapeIdentifier(self.conn.pgconn_ptr, ptr, length) + if out is NULL: + raise PQerror( + f"escape_identifier failed: {error_message(self.conn)}" + ) + + return memoryview(PQBuffer._from_buffer(out, strlen(out))) + + def escape_string(self, data: "Buffer") -> memoryview: + cdef int error + cdef size_t len_out + cdef char *ptr + cdef Py_ssize_t length + cdef bytearray rv + + _buffer_as_string_and_size(data, &ptr, &length) + + rv = PyByteArray_FromStringAndSize("", 0) + PyByteArray_Resize(rv, length * 2 + 1) + + if self.conn is not None: + if self.conn.pgconn_ptr is NULL: + raise PQerror("the connection is closed") + + len_out = impl.PQescapeStringConn( + self.conn.pgconn_ptr, PyByteArray_AS_STRING(rv), + ptr, length, &error + ) + if error: + raise PQerror( + f"escape_string failed: {error_message(self.conn)}" + ) + + else: + len_out = impl.PQescapeString(PyByteArray_AS_STRING(rv), ptr, length) + + # shrink back or the length will be reported different + PyByteArray_Resize(rv, len_out) + return memoryview(rv) + + def escape_bytea(self, data: "Buffer") -> memoryview: + cdef size_t len_out + cdef unsigned char *out + cdef char *ptr + cdef Py_ssize_t length + + if self.conn is not None and self.conn.pgconn_ptr is NULL: + raise PQerror("the connection is closed") + + _buffer_as_string_and_size(data, &ptr, &length) + + if self.conn is not None: + out = impl.PQescapeByteaConn( + self.conn.pgconn_ptr, ptr, length, &len_out) + else: + out = impl.PQescapeBytea(ptr, length, &len_out) + + if out is NULL: + raise MemoryError( + f"couldn't allocate for escape_bytea of {len(data)} bytes" + ) + + return memoryview( + PQBuffer._from_buffer(out, len_out - 1) # out includes final 0 + ) + + def unescape_bytea(self, data: bytes) -> memoryview: + # not needed, but let's keep it symmetric with the escaping: + # if a connection is passed in, it must be valid. + if self.conn is not None: + if self.conn.pgconn_ptr is NULL: + raise PQerror("the connection is closed") + + cdef size_t len_out + cdef unsigned char *out = impl.PQunescapeBytea(data, &len_out) + if out is NULL: + raise MemoryError( + f"couldn't allocate for unescape_bytea of {len(data)} bytes" + ) + + return memoryview(PQBuffer._from_buffer(out, len_out)) diff --git a/psycopg3_c/psycopg3_c/pq_cython.pyx b/psycopg3_c/psycopg3_c/pq_cython.pyx index f8e5ca0fa..444be18a4 100644 --- a/psycopg3_c/psycopg3_c/pq_cython.pyx +++ b/psycopg3_c/psycopg3_c/pq_cython.pyx @@ -814,124 +814,8 @@ class Conninfo: def __repr__(self): return f"<{type(self).__name__} ({self.keyword.decode('ascii')})>" -cdef class Escaping: - def __init__(self, conn: Optional[PGconn] = None): - self.conn = conn - def escape_literal(self, data: "Buffer") -> memoryview: - cdef char *out - cdef bytes rv - cdef char *ptr - cdef Py_ssize_t length - - if self.conn is None: - raise PQerror("escape_literal failed: no connection provided") - if self.conn.pgconn_ptr is NULL: - raise PQerror("the connection is closed") - - _buffer_as_string_and_size(data, &ptr, &length) - - out = impl.PQescapeLiteral(self.conn.pgconn_ptr, ptr, length) - if out is NULL: - raise PQerror( - f"escape_literal failed: {error_message(self.conn)}" - ) - - return memoryview(PQBuffer._from_buffer(out, strlen(out))) - - def escape_identifier(self, data: "Buffer") -> memoryview: - cdef char *out - cdef char *ptr - cdef Py_ssize_t length - - _buffer_as_string_and_size(data, &ptr, &length) - - if self.conn is None: - raise PQerror("escape_identifier failed: no connection provided") - if self.conn.pgconn_ptr is NULL: - raise PQerror("the connection is closed") - - out = impl.PQescapeIdentifier(self.conn.pgconn_ptr, ptr, length) - if out is NULL: - raise PQerror( - f"escape_identifier failed: {error_message(self.conn)}" - ) - - return memoryview(PQBuffer._from_buffer(out, strlen(out))) - - def escape_string(self, data: "Buffer") -> memoryview: - cdef int error - cdef size_t len_out - cdef char *ptr - cdef Py_ssize_t length - cdef bytearray rv - - _buffer_as_string_and_size(data, &ptr, &length) - - rv = PyByteArray_FromStringAndSize("", 0) - PyByteArray_Resize(rv, length * 2 + 1) - - if self.conn is not None: - if self.conn.pgconn_ptr is NULL: - raise PQerror("the connection is closed") - - len_out = impl.PQescapeStringConn( - self.conn.pgconn_ptr, PyByteArray_AS_STRING(rv), - ptr, length, &error - ) - if error: - raise PQerror( - f"escape_string failed: {error_message(self.conn)}" - ) - - else: - len_out = impl.PQescapeString(PyByteArray_AS_STRING(rv), ptr, length) - - # shrink back or the length will be reported different - PyByteArray_Resize(rv, len_out) - return memoryview(rv) - - def escape_bytea(self, data: "Buffer") -> memoryview: - cdef size_t len_out - cdef unsigned char *out - cdef char *ptr - cdef Py_ssize_t length - - if self.conn is not None and self.conn.pgconn_ptr is NULL: - raise PQerror("the connection is closed") - - _buffer_as_string_and_size(data, &ptr, &length) - - if self.conn is not None: - out = impl.PQescapeByteaConn( - self.conn.pgconn_ptr, ptr, length, &len_out) - else: - out = impl.PQescapeBytea(ptr, length, &len_out) - - if out is NULL: - raise MemoryError( - f"couldn't allocate for escape_bytea of {len(data)} bytes" - ) - - return memoryview( - PQBuffer._from_buffer(out, len_out - 1) # out includes final 0 - ) - - def unescape_bytea(self, data: bytes) -> memoryview: - # not needed, but let's keep it symmetric with the escaping: - # if a connection is passed in, it must be valid. - if self.conn is not None: - if self.conn.pgconn_ptr is NULL: - raise PQerror("the connection is closed") - - cdef size_t len_out - cdef unsigned char *out = impl.PQunescapeBytea(data, &len_out) - if out is NULL: - raise MemoryError( - f"couldn't allocate for unescape_bytea of {len(data)} bytes" - ) - - return memoryview(PQBuffer._from_buffer(out, len_out)) +include "pq/escaping.pyx" cdef class PQBuffer: