summaryrefslogtreecommitdiff
path: root/src/backend/tcop/pquery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop/pquery.c')
-rw-r--r--src/backend/tcop/pquery.c114
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;
}