]> git.ipfire.org Git - thirdparty/psycopg.git/commit
fix: sync pipeline after implicit BEGIN 401/head
authorDenis Laxalde <denis.laxalde@dalibo.com>
Tue, 4 Oct 2022 15:53:26 +0000 (17:53 +0200)
committerDenis Laxalde <denis.laxalde@dalibo.com>
Tue, 4 Oct 2022 17:22:02 +0000 (19:22 +0200)
commit0903334ac4f2844c259d23184ac25ab5e2ea5548
tree6b700ebcb82a66a60e4204f82b8cac1e0562e28c
parentb864e9fea631c964ab464ee7a329f933b008a962
fix: sync pipeline after implicit BEGIN

Prior to this change, the following code:

    with conn.pipeline():
       conn.execute("select 'x'").fetchone()
       conn.execute("select 'y'")

would produce the following libpq trace:

    F 13 Parse  "" "BEGIN" 0
    F 14 Bind  "" "" 0 0 1 0
    F 6 Describe  P ""
    F 9 Execute  "" 0
    F 18 Parse  "" "select 'x'" 0
    F 14 Bind  "" "" 0 0 1 0
    F 6 Describe  P ""
    F 9 Execute  "" 0
    F 4 Flush
    B 4 ParseComplete
    B 4 BindComplete
    B 4 NoData
    B 10 CommandComplete  "BEGIN"
    B 4 ParseComplete
    B 4 BindComplete
    B 33 RowDescription  1 "?column?" NNNN 0 NNNN 65535 -1 0
    B 11 DataRow  1 1 'x'
    B 13 CommandComplete  "SELECT 1"
    F 13 Parse  "" "BEGIN" 0
    F 14 Bind  "" "" 0 0 1 0
    F 6 Describe  P ""
    F 9 Execute  "" 0
    F 18 Parse  "" "select 'y'" 0
    F 14 Bind  "" "" 0 0 1 0
    F 6 Describe  P ""
    F 9 Execute  "" 0
    B 4 ParseComplete
    B 4 BindComplete
    B 4 NoData
    B NN NoticeResponse  S "WARNING" V "WARNING" C "25001" M "there is already a transaction in progress" F "SSSS" L "SSSS" R "SSSS" \x00
    F 4 Sync
    B 10 CommandComplete  "BEGIN"
    B 4 ParseComplete
    B 4 BindComplete
    B 33 RowDescription  1 "?column?" NNNN 0 NNNN 65535 -1 0
    B 11 DataRow  1 1 'y'
    B 13 CommandComplete  "SELECT 1"
    B 5 ReadyForQuery  T

where we can see that the BEGIN statement (due to the connection being
in non-autocommit mode) is emitted twice, as notified by the server.

This is because the transaction state after the implicit BEGIN is not
"correct" (i.e. should be INTRANS, but is IDLE) since the result from
respective statement has not been received yet.

By syncing after the BEGIN, we fetch result from this command thus get
the transaction state INTRANS for following queries. This is similar to
what happens with explicit transaction, by using nested pipelines.
docs/news.rst
psycopg/psycopg/connection.py
tests/test_pipeline.py
tests/test_pipeline_async.py