Hello,

I found a trivial bug that terminates the connection.  The attached patch fixes 
this.


PROBLEM
========================================

Savepoint-related statements in a multi-command query terminates the connection 
unexpectedly, as follows.

$ psql -d postgres -c "SELECT 1; SAVEPOINT sp"
FATAL:  DefineSavepoint: unexpected state STARTED
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
connection to server was lost


CAUSE
========================================

1. In exec_simple_query(), isTopLevel is set to false.

        isTopLevel = (list_length(parsetree_list) == 1);

Then it is passed to PortalRun().

                (void) PortalRun(portal,
                                                 FETCH_ALL,
                                                 isTopLevel,
                                                 receiver,
                                                 receiver,
                                                 completionTag);

2. The isTopLevel flag is passed through ProcessUtility() to 
RequireTransactionChain().

                                                        
RequireTransactionChain(isTopLevel, "SAVEPOINT");


3. CheckTransactionChain() returns successfully here:

        /*
         * inside a function call?
         */
        if (!isTopLevel)
                return;


4. Finally, unexpectedly called DefineSavepoint() reports invalid transaction 
block state.

                        /* These cases are invalid. */
                case TBLOCK_DEFAULT:
                case TBLOCK_STARTED:
...
                        elog(FATAL, "DefineSavepoint: unexpected state %s",
                                 BlockStateAsString(s->blockState));



SOLUTION
========================================

The manual page says "Savepoints can only be established when inside a 
transaction block."  So just check for it.

https://www.postgresql.org/docs/devel/static/sql-savepoint.html


RESULT AFTER FIX
========================================

$ psql -d postgres -c "SELECT 1; SAVEPOINT sp"
ERROR:  SAVEPOINT can only be used in transaction blocks


Regards
Takayuki Tsunakawa

Attachment: savept-in-multi-cmd.patch
Description: savept-in-multi-cmd.patch

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to