If the connection is idle, it might be that we are missing results.
Receive them to align the connection state to what the transaction
object expects, otherwise the assert in _push_savepoint() will fail.
raise TypeError("transaction blocks can be used only once")
self._entered = True
+ # If we are in pipeline mode and connection idle, we might be in a
+ # nested statement but we haven't received yet the result to go
+ # INTRANS. This would make _push_savepoint() fail. If so, synchronize
+ # with the server.
+ if (
+ self._conn._pipeline
+ and self.pgconn.transaction_status == TransactionStatus.IDLE
+ ):
+ yield from self._conn._pipeline._sync_gen()
+
self._push_savepoint()
for command in self._get_enter_commands():
yield from self._conn._exec_command(command)
assert r == "inner"
+def test_transaction_nested_no_statement(conn):
+ with conn.pipeline():
+ with conn.transaction():
+ with conn.transaction():
+ cur = conn.execute("select 1")
+
+ (r,) = cur.fetchone()
+ assert r == 1
+
+
def test_outer_transaction(conn):
with conn.transaction():
with conn.pipeline():
assert r == "inner"
+async def test_transaction_nested_no_statement(aconn):
+ async with aconn.pipeline():
+ async with aconn.transaction():
+ async with aconn.transaction():
+ cur = await aconn.execute("select 1")
+
+ (r,) = await cur.fetchone()
+ assert r == 1
+
+
async def test_outer_transaction(aconn):
async with aconn.transaction():
async with aconn.pipeline():