pgpool2.git / summary / log / commit / refs

commit    85f333b678d9acbbd0432dbcf68287d7cc8537bc
Author:   Taiki Koshino <koshino@sraoss.co.jp>
Date:     Fri Sep 18 05:13:34 2026 +0000

    Fix inconsistent internal transaction handling in Parse.
    
    Parse() started an internal transaction for a strict query in raw mode:
    
        if (!SL_MODE)
            if (is_strict_query(...))
                start_internal_transaction(...);
    
    Bind() correctly limits the same operation to replication mode:
    
        if (REPLICATION)
            if (is_strict_query(...))
                start_internal_transaction(...);
    
    This difference left an autocommitted extended-protocol UPDATE in a
    transaction in raw mode because the internal transaction was never
    closed.
    
    Add the REPLICATION condition to Parse() to make it consistent with
    Bind().
    
    The issue was verified using pgproto with the following extended-query
    message sequence:
    
        'P'  "s"  "UPDATE scm_pgpool_txn_probe SET value=value+1 WHERE id=1"  0
        'B'  ""   "s"  0  0  0
        'E'  ""   0
        'S'
        'Y'
        'X'
    
    Before the fix, Pgpool-II returned:
    
        <= BE CommandComplete(UPDATE 1)
        <= BE ReadyForQuery(T)
    
    After the fix, it returns:
    
        <= BE CommandComplete(UPDATE 1)
        <= BE ReadyForQuery(I)
    
    Author: Taiki Koshino <koshino@sraoss.co.jp>
    Discussion: https://github.com/pgpool/pgpool2/issues/172
    Backpatch-through: v4.3


src/protocol/pool_proto_modules.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index 9f3552515..5192fe5a3 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -1612,7 +1612,11 @@ Parse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, pool_set_query_in_progress(); } - if (is_strict_query(query_context->parse_tree)) + /* + * As in Bind(), start an internal transaction only in replication + * mode. In raw mode it would not be closed by ReadyForQuery(). + */ + if (REPLICATION && is_strict_query(query_context->parse_tree)) { start_internal_transaction(frontend, backend, query_context->parse_tree); allow_close_transaction = 1; [parent: 9bc49568bc93]