1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-12 15:23:02 +03:00

Fix an error in the original coding of holdable cursors: PersistHoldablePortal

thought that it didn't have to reposition the underlying tuplestore if the
portal is atEnd.  But this is not so, because tuplestores have separate read
and write cursors ... and the read cursor hasn't moved from the start.
This mistake explains bug #2970 from William Zhang.

Note: the coding here is pretty inefficient, but given that no one has noticed
this bug until now, I'd say hardly anyone uses the case where the cursor has
been advanced before being persisted.  So maybe it's not worth worrying about.
This commit is contained in:
Tom Lane
2007-02-06 22:49:42 +00:00
parent 122680c514
commit bb65d51c2e

View File

@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.38.4.1 2005/04/11 15:59:47 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.38.4.2 2007/02/06 22:49:42 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@@ -389,15 +389,30 @@ PersistHoldablePortal(Portal portal)
/* we do not need AfterTriggerEndQuery() here */ /* we do not need AfterTriggerEndQuery() here */
/* /*
* Reset the position in the result set: ideally, this could be * Set the position in the result set: ideally, this could be
* implemented by just skipping straight to the tuple # that we * implemented by just skipping straight to the tuple # that we need
* need to be at, but the tuplestore API doesn't support that. So * to be at, but the tuplestore API doesn't support that. So we start
* we start at the beginning of the tuplestore and iterate through * at the beginning of the tuplestore and iterate through it until we
* it until we reach where we need to be. FIXME someday? * reach where we need to be. FIXME someday? (Fortunately, the
* typical case is that we're supposed to be at or near the start
* of the result set, so this isn't as bad as it sounds.)
*/ */
MemoryContextSwitchTo(portal->holdContext); MemoryContextSwitchTo(portal->holdContext);
if (!portal->atEnd) if (portal->atEnd)
{
/* we can handle this case even if posOverflow */
HeapTuple tup;
bool should_free;
while ((tup = tuplestore_gettuple(portal->holdStore, true,
&should_free)) != NULL)
{
if (should_free)
pfree(tup);
}
}
else
{ {
long store_pos; long store_pos;