.. autoattribute:: rowcount
:annotation: int
+ .. autoattribute:: query
+ :annotation: Optional[bytes]
+
+ The query will be in PostgreSQL format (with ``$1``, ``$2``...
+ parameters), the parameters will *not* be merged to the query: see
+ `params`.
+
+ .. autoattribute:: params
+ :annotation: Optional[List[Optional[bytes]]]
+
+ The parameters are adapted to PostgreSQL format.
+
The `!AsyncCursor` class
------------------------
self._pos = 0
self._iresult = 0
self._rowcount = -1
+ self._query: Optional[bytes] = None
+ self._params: Optional[List[Optional[bytes]]] = None
@property
def connection(self) -> ConnectionType:
res = self.pgresult
return res.status if res else None
+ @property
+ def query(self) -> Optional[bytes]:
+ """The last query sent to the server, if available."""
+ return self._query
+
+ @property
+ def params(self) -> Optional[List[Optional[bytes]]]:
+ """The last set of parameters sent to the server, if available."""
+ return self._params
+
@property
def pgresult(self) -> Optional["PGresult"]:
"""The `~psycopg3.pq.PGresult` exposed by the cursor."""
pgq.convert(query, vars)
if pgq.params or no_pqexec or self.format == pq.Format.BINARY:
+ self._query = pgq.query
+ self._params = pgq.params
self._conn.pgconn.send_query_params(
pgq.query,
pgq.params,
else:
# if we don't have to, let's use exec_ as it can run more than
# one query in one go
+ self._query = pgq.query
+ self._params = None
self._conn.pgconn.send_query(pgq.query)
def _execute_results(self, results: Sequence["PGresult"]) -> None:
pgq = PostgresQuery(self._transformer)
pgq.convert(query, vars)
+ self._query = pgq.query
self._conn.pgconn.send_prepare(name, pgq.query, param_types=pgq.types)
return pgq
def _send_query_prepared(self, name: bytes, pgq: PostgresQuery) -> None:
+ self._params = pgq.params
self._conn.pgconn.send_query_prepared(
name,
pgq.params,
assert cur.rowcount == -1
+def test_copy_query(conn):
+ cur = conn.cursor()
+ with cur.copy("copy (select 1) to stdout") as copy:
+ assert cur.query == b"copy (select 1) to stdout"
+ assert cur.params is None
+ list(copy)
+
+
def ensure_table(cur, tabledef, name="copy_in"):
cur.execute(f"drop table if exists {name}")
cur.execute(f"create table {name} ({tabledef})")
assert cur.rowcount == -1
+async def test_copy_query(aconn):
+ cur = await aconn.cursor()
+ async with cur.copy("copy (select 1) to stdout") as copy:
+ assert cur.query == b"copy (select 1) to stdout"
+ assert cur.params is None
+ async for record in copy:
+ pass
+
+
async def ensure_table(cur, tabledef, name="copy_in"):
await cur.execute(f"drop table if exists {name}")
await cur.execute(f"create table {name} ({tabledef})")
assert list(cur) == []
+def test_query_params_execute(conn):
+ cur = conn.cursor()
+ assert cur.query is None
+ assert cur.params is None
+
+ cur.execute("select %s, %s", [1, None])
+ assert cur.query == b"select $1, $2"
+ assert cur.params == [b"1", None]
+
+ cur.execute("select 1")
+ assert cur.query == b"select 1"
+ assert cur.params is None
+
+ with pytest.raises(psycopg3.DataError):
+ cur.execute("select %s::int", ["wat"])
+
+ assert cur.query == b"select $1::int"
+ assert cur.params == [b"wat"]
+
+
+def test_query_params_executemany(conn):
+ cur = conn.cursor()
+
+ cur.executemany("select %s, %s", [[1, 2], [3, 4]])
+ assert cur.query == b"select $1, $2"
+ assert cur.params == [b"3", b"4"]
+
+ with pytest.raises(psycopg3.DataError):
+ cur.executemany("select %s::int", [[1], ["x"], [2]])
+ assert cur.query == b"select $1::int"
+ assert cur.params == [b"x"]
+
+
class TestColumn:
def test_description_attribs(self, conn):
curs = conn.cursor()
assert res == [(1,), (2,), (3,)]
+async def test_query_params_execute(aconn):
+ cur = await aconn.cursor()
+ assert cur.query is None
+ assert cur.params is None
+
+ await cur.execute("select %s, %s", [1, None])
+ assert cur.query == b"select $1, $2"
+ assert cur.params == [b"1", None]
+
+ await cur.execute("select 1")
+ assert cur.query == b"select 1"
+ assert cur.params is None
+
+ with pytest.raises(psycopg3.DataError):
+ await cur.execute("select %s::int", ["wat"])
+
+ assert cur.query == b"select $1::int"
+ assert cur.params == [b"wat"]
+
+
+async def test_query_params_executemany(aconn):
+ cur = await aconn.cursor()
+
+ await cur.executemany("select %s, %s", [[1, 2], [3, 4]])
+ assert cur.query == b"select $1, $2"
+ assert cur.params == [b"3", b"4"]
+
+ with pytest.raises(psycopg3.DataError):
+ await cur.executemany("select %s::int", [[1], ["x"], [2]])
+ assert cur.query == b"select $1::int"
+ assert cur.params == [b"x"]
+
+
async def test_iter_stop(aconn):
cur = await aconn.cursor()
await cur.execute("select generate_series(1, 3)")