diff options
Diffstat (limited to 'src/backend/tcop/pquery.c')
-rw-r--r-- | src/backend/tcop/pquery.c | 114 |
1 files changed, 60 insertions, 54 deletions
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 6893b0f4239..fcdc4c347c7 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -39,16 +39,16 @@ static void ProcessQuery(PlannedStmt *plan, DestReceiver *dest, char *completionTag); static void FillPortalStore(Portal portal, bool isTopLevel); -static uint32 RunFromStore(Portal portal, ScanDirection direction, long count, +static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest); -static long PortalRunSelect(Portal portal, bool forward, long count, +static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest); static void PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, DestReceiver *dest, char *completionTag); static void PortalRunMulti(Portal portal, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, char *completionTag); -static long DoPortalRunFetch(Portal portal, +static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest); @@ -195,7 +195,8 @@ ProcessQuery(PlannedStmt *plan, { case CMD_SELECT: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "SELECT %u", queryDesc->estate->es_processed); + "SELECT " UINT64_FORMAT, + queryDesc->estate->es_processed); break; case CMD_INSERT: if (queryDesc->estate->es_processed == 1) @@ -203,15 +204,18 @@ ProcessQuery(PlannedStmt *plan, else lastOid = InvalidOid; snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "INSERT %u %u", lastOid, queryDesc->estate->es_processed); + "INSERT %u " UINT64_FORMAT, + lastOid, queryDesc->estate->es_processed); break; case CMD_UPDATE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "UPDATE %u", queryDesc->estate->es_processed); + "UPDATE " UINT64_FORMAT, + queryDesc->estate->es_processed); break; case CMD_DELETE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "DELETE %u", queryDesc->estate->es_processed); + "DELETE " UINT64_FORMAT, + queryDesc->estate->es_processed); break; default: strcpy(completionTag, "???"); @@ -548,7 +552,6 @@ PortalStart(Portal portal, ParamListInfo params, portal->atStart = true; portal->atEnd = false; /* allow fetches */ portal->portalPos = 0; - portal->posOverflow = false; PopActiveSnapshot(); break; @@ -576,7 +579,6 @@ PortalStart(Portal portal, ParamListInfo params, portal->atStart = true; portal->atEnd = false; /* allow fetches */ portal->portalPos = 0; - portal->posOverflow = false; break; case PORTAL_UTIL_SELECT: @@ -598,7 +600,6 @@ PortalStart(Portal portal, ParamListInfo params, portal->atStart = true; portal->atEnd = false; /* allow fetches */ portal->portalPos = 0; - portal->posOverflow = false; break; case PORTAL_MULTI_QUERY: @@ -708,7 +709,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, char *completionTag) { bool result; - uint32 nprocessed; + uint64 nprocessed; ResourceOwner saveTopTransactionResourceOwner; MemoryContext saveTopTransactionContext; Portal saveActivePortal; @@ -794,7 +795,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, { if (strcmp(portal->commandTag, "SELECT") == 0) snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "SELECT %u", nprocessed); + "SELECT " UINT64_FORMAT, nprocessed); else strcpy(completionTag, portal->commandTag); } @@ -877,14 +878,14 @@ PortalRun(Portal portal, long count, bool isTopLevel, * * count <= 0 is interpreted as a no-op: the destination gets started up * and shut down, but nothing else happens. Also, count == FETCH_ALL is - * interpreted as "all rows". + * interpreted as "all rows". (cf FetchStmt.howMany) * * Caller must already have validated the Portal and done appropriate * setup (cf. PortalRun). * * Returns number of rows processed (suitable for use in result tag) */ -static long +static uint64 PortalRunSelect(Portal portal, bool forward, long count, @@ -892,7 +893,7 @@ PortalRunSelect(Portal portal, { QueryDesc *queryDesc; ScanDirection direction; - uint32 nprocessed; + uint64 nprocessed; /* * NB: queryDesc will be NULL if we are fetching from a held cursor or a @@ -926,7 +927,10 @@ PortalRunSelect(Portal portal, if (forward) { if (portal->atEnd || count <= 0) + { direction = NoMovementScanDirection; + count = 0; /* don't pass negative count to executor */ + } else direction = ForwardScanDirection; @@ -935,29 +939,22 @@ PortalRunSelect(Portal portal, count = 0; if (portal->holdStore) - nprocessed = RunFromStore(portal, direction, count, dest); + nprocessed = RunFromStore(portal, direction, (uint64) count, dest); else { PushActiveSnapshot(queryDesc->snapshot); - ExecutorRun(queryDesc, direction, count); + ExecutorRun(queryDesc, direction, (uint64) count); nprocessed = queryDesc->estate->es_processed; PopActiveSnapshot(); } if (!ScanDirectionIsNoMovement(direction)) { - long oldPos; - if (nprocessed > 0) portal->atStart = false; /* OK to go backward now */ - if (count == 0 || - (unsigned long) nprocessed < (unsigned long) count) + if (count == 0 || nprocessed < (uint64) count) portal->atEnd = true; /* we retrieved 'em all */ - oldPos = portal->portalPos; portal->portalPos += nprocessed; - /* portalPos doesn't advance when we fall off the end */ - if (portal->portalPos < oldPos) - portal->posOverflow = true; } } else @@ -969,7 +966,10 @@ PortalRunSelect(Portal portal, errhint("Declare it with SCROLL option to enable backward scan."))); if (portal->atStart || count <= 0) + { direction = NoMovementScanDirection; + count = 0; /* don't pass negative count to executor */ + } else direction = BackwardScanDirection; @@ -978,11 +978,11 @@ PortalRunSelect(Portal portal, count = 0; if (portal->holdStore) - nprocessed = RunFromStore(portal, direction, count, dest); + nprocessed = RunFromStore(portal, direction, (uint64) count, dest); else { PushActiveSnapshot(queryDesc->snapshot); - ExecutorRun(queryDesc, direction, count); + ExecutorRun(queryDesc, direction, (uint64) count); nprocessed = queryDesc->estate->es_processed; PopActiveSnapshot(); } @@ -994,22 +994,14 @@ PortalRunSelect(Portal portal, portal->atEnd = false; /* OK to go forward now */ portal->portalPos++; /* adjust for endpoint case */ } - if (count == 0 || - (unsigned long) nprocessed < (unsigned long) count) + if (count == 0 || nprocessed < (uint64) count) { portal->atStart = true; /* we retrieved 'em all */ portal->portalPos = 0; - portal->posOverflow = false; } else { - long oldPos; - - oldPos = portal->portalPos; portal->portalPos -= nprocessed; - if (portal->portalPos > oldPos || - portal->portalPos <= 0) - portal->posOverflow = true; } } } @@ -1083,11 +1075,11 @@ FillPortalStore(Portal portal, bool isTopLevel) * are run in the caller's memory context (since we have no estate). Watch * out for memory leaks. */ -static uint32 -RunFromStore(Portal portal, ScanDirection direction, long count, +static uint64 +RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest) { - long current_tuple_count = 0; + uint64 current_tuple_count = 0; TupleTableSlot *slot; slot = MakeSingleTupleTableSlot(portal->tupDesc); @@ -1136,7 +1128,7 @@ RunFromStore(Portal portal, ScanDirection direction, long count, ExecDropSingleTupleTableSlot(slot); - return (uint32) current_tuple_count; + return current_tuple_count; } /* @@ -1375,15 +1367,19 @@ PortalRunMulti(Portal portal, bool isTopLevel, * * Note: we presently assume that no callers of this want isTopLevel = true. * + * count <= 0 is interpreted as a no-op: the destination gets started up + * and shut down, but nothing else happens. Also, count == FETCH_ALL is + * interpreted as "all rows". (cf FetchStmt.howMany) + * * Returns number of rows processed (suitable for use in result tag) */ -long +uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest) { - long result; + uint64 result; Portal saveActivePortal; ResourceOwner saveResourceOwner; MemoryContext savePortalContext; @@ -1470,9 +1466,13 @@ PortalRunFetch(Portal portal, * DoPortalRunFetch * Guts of PortalRunFetch --- the portal context is already set up * + * count <= 0 is interpreted as a no-op: the destination gets started up + * and shut down, but nothing else happens. Also, count == FETCH_ALL is + * interpreted as "all rows". (cf FetchStmt.howMany) + * * Returns number of rows processed (suitable for use in result tag) */ -static long +static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, @@ -1508,13 +1508,21 @@ DoPortalRunFetch(Portal portal, { /* * Definition: Rewind to start, advance count-1 rows, return - * next row (if any). In practice, if the goal is less than - * halfway back to the start, it's better to scan from where - * we are. In any case, we arrange to fetch the target row - * going forwards. + * next row (if any). + * + * In practice, if the goal is less than halfway back to the + * start, it's better to scan from where we are. + * + * Also, if current portalPos is outside the range of "long", + * do it the hard way to avoid possible overflow of the count + * argument to PortalRunSelect. We must exclude exactly + * LONG_MAX, as well, lest the count look like FETCH_ALL. + * + * In any case, we arrange to fetch the target row going + * forwards. */ - if (portal->posOverflow || portal->portalPos == LONG_MAX || - count - 1 <= portal->portalPos / 2) + if ((uint64) (count - 1) <= portal->portalPos / 2 || + portal->portalPos >= (uint64) LONG_MAX) { DoPortalRewind(portal); if (count > 1) @@ -1523,7 +1531,7 @@ DoPortalRunFetch(Portal portal, } else { - long pos = portal->portalPos; + long pos = (long) portal->portalPos; if (portal->atEnd) pos++; /* need one extra fetch if off end */ @@ -1609,7 +1617,7 @@ DoPortalRunFetch(Portal portal, if (dest->mydest == DestNone) { /* MOVE 0 returns 0/1 based on if FETCH 0 would return a row */ - return on_row ? 1L : 0L; + return on_row ? 1 : 0; } else { @@ -1635,12 +1643,11 @@ DoPortalRunFetch(Portal portal, */ if (!forward && count == FETCH_ALL && dest->mydest == DestNone) { - long result = portal->portalPos; + uint64 result = portal->portalPos; if (result > 0 && !portal->atEnd) result--; DoPortalRewind(portal); - /* result is bogus if pos had overflowed, but it's best we can do */ return result; } @@ -1677,5 +1684,4 @@ DoPortalRewind(Portal portal) portal->atStart = true; portal->atEnd = false; portal->portalPos = 0; - portal->posOverflow = false; } |