• Tom Lane's avatar
    Fix TOAST access failure in RETURNING queries. · 9ee1cf04
    Tom Lane authored
    Discussion of commit 3e2f3c2e exposed a problem that is of longer
    standing: since we don't detoast data while sticking it into a portal's
    holdStore for PORTAL_ONE_RETURNING and PORTAL_UTIL_SELECT queries, and we
    release the query's snapshot as soon as we're done loading the holdStore,
    later readout of the holdStore can do TOAST fetches against data that can
    no longer be seen by any of the session's live snapshots.  This means that
    a concurrent VACUUM could remove the TOAST data before we can fetch it.
    Commit 3e2f3c2e exposed the problem by showing that sometimes we had *no*
    live snapshots while fetching TOAST data, but we'd be at risk anyway.
    
    I believe this code was all right when written, because our management of a
    session's exposed xmin was such that the TOAST references were safe until
    end of transaction.  But that's no longer true now that we can advance or
    clear our PGXACT.xmin intra-transaction.
    
    To fix, copy the query's snapshot during FillPortalStore() and save it in
    the Portal; release it only when the portal is dropped.  This essentially
    implements a policy that we must hold a relevant snapshot whenever we
    access potentially-toasted data.  We had already come to that conclusion
    in other places, cf commits 08e261cb and ec543db7.
    
    I'd have liked to add a regression test case for this, but I didn't see
    a way to make one that's not unreasonably bloated; it seems to require
    returning a toasted value to the client, and those will be big.
    
    In passing, improve PortalRunUtility() so that it positively verifies
    that its ending PopActiveSnapshot() call will pop the expected snapshot,
    removing a rather shaky assumption about which utility commands might
    do their own PopActiveSnapshot().  There's no known bug here, but now
    that we're actively referencing the snapshot it's almost free to make
    this code a bit more bulletproof.
    
    We might want to consider back-patching something like this into older
    branches, but it would be prudent to let it prove itself more in HEAD
    beforehand.
    
    Discussion: <87vazemeda.fsf@credativ.de>
    9ee1cf04
portal.h 9.64 KB