]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Added pgconn.send_describe_prepared, send_describe_portal
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 9 Feb 2021 00:52:50 +0000 (01:52 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 9 Feb 2021 00:52:50 +0000 (01:52 +0100)
psycopg3/psycopg3/pq/_pq_ctypes.py
psycopg3/psycopg3/pq/_pq_ctypes.pyi
psycopg3/psycopg3/pq/pq_ctypes.py
psycopg3_c/psycopg3_c/pq/pgconn.pyx
tests/pq/test_async.py

index 1f9846b97ce16c5e4379515425b9384b63ea1389..280038041d192f47c3c174c9c99768d1cf7fd70e 100644 (file)
@@ -472,7 +472,13 @@ PQsendQueryPrepared.argtypes = [
 ]
 PQsendQueryPrepared.restype = c_int
 
-# TODO: PQsendDescribePrepared PQsendDescribePortal
+PQsendDescribePrepared = pq.PQsendDescribePrepared
+PQsendDescribePrepared.argtypes = [PGconn_ptr, c_char_p]
+PQsendDescribePrepared.restype = c_int
+
+PQsendDescribePortal = pq.PQsendDescribePortal
+PQsendDescribePortal.argtypes = [PGconn_ptr, c_char_p]
+PQsendDescribePortal.restype = c_int
 
 PQgetResult = pq.PQgetResult
 PQgetResult.argtypes = [PGconn_ptr]
index 39485f91b2f96028f51c7344c76f6ea9d249e48a..e6728339f149d7600ded03cc1a5fa2efad5d3884 100644 (file)
@@ -174,6 +174,8 @@ def PQescapeBytea(arg1: bytes, arg2: int, arg3: pointer[c_ulong]) -> pointer[c_u
 def PQunescapeBytea(arg1: bytes, arg2: pointer[c_ulong]) -> pointer[c_ubyte]: ...
 def PQsendQuery(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
 def PQsendQueryParams(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int, arg4: pointer[c_uint], arg5: pointer[c_char_p], arg6: pointer[c_int], arg7: pointer[c_int], arg8: int) -> int: ...
+def PQsendDescribePrepared(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
+def PQsendDescribePortal(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
 def PQgetResult(arg1: Optional[PGconn_struct]) -> PGresult_struct: ...
 def PQconsumeInput(arg1: Optional[PGconn_struct]) -> int: ...
 def PQisBusy(arg1: Optional[PGconn_struct]) -> int: ...
index 75d90155232240f9ab0c18b37f1416f0893e73e3..f017beb425425c666dd534a366c8e142a08916ee 100644 (file)
@@ -463,6 +463,15 @@ class PGconn:
             raise MemoryError("couldn't allocate PGresult")
         return PGresult(rv)
 
+    def send_describe_prepared(self, name: bytes) -> None:
+        if not isinstance(name, bytes):
+            raise TypeError(f"bytes expected, got {type(name)} instead")
+        self._ensure_pgconn()
+        if not impl.PQsendDescribePrepared(self.pgconn_ptr, name):
+            raise PQerror(
+                f"sending describe prepared failed: {error_message(self)}"
+            )
+
     def describe_portal(self, name: bytes) -> "PGresult":
         if not isinstance(name, bytes):
             raise TypeError(f"'name' must be bytes, got {type(name)} instead")
@@ -472,6 +481,15 @@ class PGconn:
             raise MemoryError("couldn't allocate PGresult")
         return PGresult(rv)
 
+    def send_describe_portal(self, name: bytes) -> None:
+        if not isinstance(name, bytes):
+            raise TypeError(f"bytes expected, got {type(name)} instead")
+        self._ensure_pgconn()
+        if not impl.PQsendDescribePortal(self.pgconn_ptr, name):
+            raise PQerror(
+                f"sending describe portal failed: {error_message(self)}"
+            )
+
     def get_result(self) -> Optional["PGresult"]:
         rv = impl.PQgetResult(self.pgconn_ptr)
         return PGresult(rv) if rv else None
index a979fcdebe6ccdc0913af016c09f973e8d234e8b..f277d13eff98e25fc7397ebba4a7109d2850f070 100644 (file)
@@ -369,6 +369,14 @@ cdef class PGconn:
             raise MemoryError("couldn't allocate PGresult")
         return PGresult._from_ptr(rv)
 
+    def send_describe_prepared(self, const char *name) -> None:
+        _ensure_pgconn(self)
+        cdef int rv = libpq.PQsendDescribePrepared(self.pgconn_ptr, name)
+        if not rv:
+            raise PQerror(
+                f"sending describe prepared failed: {error_message(self)}"
+            )
+
     def describe_portal(self, const char *name) -> PGresult:
         _ensure_pgconn(self)
         cdef libpq.PGresult *rv = libpq.PQdescribePortal(self.pgconn_ptr, name)
@@ -376,6 +384,14 @@ cdef class PGconn:
             raise MemoryError("couldn't allocate PGresult")
         return PGresult._from_ptr(rv)
 
+    def send_describe_portal(self, const char *name) -> None:
+        _ensure_pgconn(self)
+        cdef int rv = libpq.PQsendDescribePortal(self.pgconn_ptr, name)
+        if not rv:
+            raise PQerror(
+                f"sending describe prepared failed: {error_message(self)}"
+            )
+
     def get_result(self) -> Optional["PGresult"]:
         cdef libpq.PGresult *pgresult = libpq.PQgetResult(self.pgconn_ptr)
         if pgresult is NULL:
index 0e648b373df5504cd93b436c7ffade996482bcbf..68d95383bdfd3615741bdcc163ec46d6f9a3e82b 100644 (file)
@@ -172,3 +172,40 @@ def test_send_prepared_binary_out(pgconn, fmt, out):
     (res,) = execute_wait(pgconn)
     assert res.status == pq.ExecStatus.TUPLES_OK
     assert res.get_value(0, 0) == out
+
+
+def test_send_describe_prepared(pgconn):
+    pgconn.send_prepare(b"prep", b"select $1::int + $2::int as fld")
+    (res,) = execute_wait(pgconn)
+    assert res.status == pq.ExecStatus.COMMAND_OK, res.error_message
+
+    pgconn.send_describe_prepared(b"prep")
+    (res,) = execute_wait(pgconn)
+    assert res.nfields == 1
+    assert res.ntuples == 0
+    assert res.fname(0) == b"fld"
+    assert res.ftype(0) == 23
+
+    pgconn.finish()
+    with pytest.raises(psycopg3.OperationalError):
+        pgconn.send_describe_prepared(b"prep")
+
+
+def test_send_describe_portal(pgconn):
+    res = pgconn.exec_(
+        b"""
+        begin;
+        declare cur cursor for select * from generate_series(1,10) foo;
+        """
+    )
+    assert res.status == pq.ExecStatus.COMMAND_OK, res.error_message
+
+    pgconn.send_describe_portal(b"cur")
+    (res,) = execute_wait(pgconn)
+    assert res.status == pq.ExecStatus.COMMAND_OK, res.error_message
+    assert res.nfields == 1
+    assert res.fname(0) == b"foo"
+
+    pgconn.finish()
+    with pytest.raises(psycopg3.OperationalError):
+        pgconn.send_describe_portal(b"cur")