]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Added PQsendQueryParams wrapper
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 21 Mar 2020 10:31:23 +0000 (23:31 +1300)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 21 Mar 2020 10:31:23 +0000 (23:31 +1300)
psycopg3/pq/_pq_ctypes.py
psycopg3/pq/pq_ctypes.py
tests/pq/test_async.py

index 858f78cb4f91d8dac406ab60178868831cd48bd7..1f8eaff9daaa0217ec0cbd8fa651d751c34f05c0 100644 (file)
@@ -335,7 +335,20 @@ PQsendQuery = pq.PQsendQuery
 PQsendQuery.argtypes = [PGconn_ptr, c_char_p]
 PQsendQuery.restype = c_int
 
-# TODO: PQsendQueryParams PQsendPrepare PQsendQueryPrepared
+PQsendQueryParams = pq.PQsendQueryParams
+PQsendQueryParams.argtypes = [
+    PGconn_ptr,
+    c_char_p,
+    c_int,
+    POINTER(Oid),
+    POINTER(c_char_p),
+    POINTER(c_int),
+    POINTER(c_int),
+    c_int,
+]
+PQsendQueryParams.restype = c_int
+
+# TODO: PQsendPrepare PQsendQueryPrepared
 #       PQsendDescribePrepared PQsendDescribePortal
 
 PQgetResult = pq.PQgetResult
index b2aaf3e961a83e7fe476253e971280774b0f81b4..38a5a47866326405e42d26826928c14955746285 100644 (file)
@@ -203,6 +203,33 @@ class PGconn:
         param_types=None,
         param_formats=None,
         result_format=0,
+    ):
+        args = self._query_params_args(
+            command, param_values, param_types, param_formats, result_format
+        )
+        rv = impl.PQexecParams(*args)
+        if not rv:
+            raise MemoryError("couldn't allocate PGresult")
+        return PGresult(rv)
+
+    def send_query_params(
+        self,
+        command,
+        param_values,
+        param_types=None,
+        param_formats=None,
+        result_format=0,
+    ):
+        args = self._query_params_args(
+            command, param_values, param_types, param_formats, result_format
+        )
+        if not impl.PQsendQueryParams(*args):
+            raise PQerror(
+                f"sending query and params failed: {error_message(self)}"
+            )
+
+    def _query_params_args(
+        self, command, param_values, param_types, param_formats, result_format,
     ):
         if not isinstance(command, bytes):
             raise TypeError(
@@ -238,7 +265,7 @@ class PGconn:
                 )
             aformats = (c_int * nparams)(*param_formats)
 
-        rv = impl.PQexecParams(
+        return (
             self.pgconn_ptr,
             command,
             nparams,
@@ -248,9 +275,6 @@ class PGconn:
             aformats,
             result_format,
         )
-        if not rv:
-            raise MemoryError("couldn't allocate PGresult")
-        return PGresult(rv)
 
     def prepare(self, name, command, param_types=None):
         if not isinstance(name, bytes):
index f91cfff7f931306fc0f53b0c98c819abb58ee698..eb90f21192e6ce983bdb4286e12ad4cf45c4c83e 100644 (file)
@@ -1,5 +1,7 @@
 from select import select
 
+from psycopg3.waiting import wait_select
+
 
 def test_send_query(pq, pgconn):
     # This test shows how to process an async query in all its glory
@@ -50,3 +52,27 @@ def test_send_query(pq, pgconn):
     assert results[1].nfields == 1
     assert results[1].fname(0) == b"foo"
     assert results[1].get_value(0, 0) == b"1"
+
+
+def test_send_query_compact_test(pq, conn):
+    # Like the above test but use psycopg3 facilities for compactness
+    conn.pgconn.send_query(
+        b"/* %s */ select pg_sleep(0.01); select 1 as foo;"
+        % (b"x" * 1_000_000)
+    )
+    results = wait_select(conn._exec_gen(conn.pgconn))
+
+    assert len(results) == 2
+    assert results[0].nfields == 1
+    assert results[0].fname(0) == b"pg_sleep"
+    assert results[0].get_value(0, 0) == b""
+    assert results[1].nfields == 1
+    assert results[1].fname(0) == b"foo"
+    assert results[1].get_value(0, 0) == b"1"
+
+
+def test_send_query_params(pq, conn):
+    res = conn.pgconn.send_query_params(b"select $1::int + $2", [b"5", b"3"])
+    (res,) = wait_select(conn._exec_gen(conn.pgconn))
+    assert res.status == pq.ExecStatus.TUPLES_OK
+    assert res.get_value(0, 0) == b"8"