PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pquery.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/xact.h"
#include "commands/prepare.h"
#include "executor/execdesc.h"
#include "executor/executor.h"
#include "executor/tstoreReceiver.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "tcop/pquery.h"
#include "tcop/utility.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
Include dependency graph for pquery.c:

Go to the source code of this file.

Functions

static void ProcessQuery (PlannedStmt *plan, CachedPlan *cplan, CachedPlanSource *plansource, int query_index, const char *sourceText, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
 
static void FillPortalStore (Portal portal, bool isTopLevel)
 
static uint64 RunFromStore (Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest)
 
static uint64 PortalRunSelect (Portal portal, bool forward, long count, DestReceiver *dest)
 
static void PortalRunUtility (Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, QueryCompletion *qc)
 
static void PortalRunMulti (Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
 
static uint64 DoPortalRunFetch (Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
 
static void DoPortalRewind (Portal portal)
 
QueryDescCreateQueryDesc (PlannedStmt *plannedstmt, CachedPlan *cplan, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
 
void FreeQueryDesc (QueryDesc *qdesc)
 
PortalStrategy ChoosePortalStrategy (List *stmts)
 
ListFetchPortalTargetList (Portal portal)
 
ListFetchStatementTargetList (Node *stmt)
 
void PortalStart (Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
 
void PortalSetResultFormat (Portal portal, int nFormats, int16 *formats)
 
bool PortalRun (Portal portal, long count, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
 
uint64 PortalRunFetch (Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
 
bool PlannedStmtRequiresSnapshot (PlannedStmt *pstmt)
 
void EnsurePortalSnapshotExists (void)
 

Variables

Portal ActivePortal = NULL
 

Function Documentation

◆ ChoosePortalStrategy()

PortalStrategy ChoosePortalStrategy ( List stmts)

Definition at line 231 of file pquery.c.

232{
233 int nSetTag;
234 ListCell *lc;
235
236 /*
237 * PORTAL_ONE_SELECT and PORTAL_UTIL_SELECT need only consider the
238 * single-statement case, since there are no rewrite rules that can add
239 * auxiliary queries to a SELECT or a utility command. PORTAL_ONE_MOD_WITH
240 * likewise allows only one top-level statement.
241 */
242 if (list_length(stmts) == 1)
243 {
244 Node *stmt = (Node *) linitial(stmts);
245
246 if (IsA(stmt, Query))
247 {
248 Query *query = (Query *) stmt;
249
250 if (query->canSetTag)
251 {
252 if (query->commandType == CMD_SELECT)
253 {
254 if (query->hasModifyingCTE)
255 return PORTAL_ONE_MOD_WITH;
256 else
257 return PORTAL_ONE_SELECT;
258 }
259 if (query->commandType == CMD_UTILITY)
260 {
262 return PORTAL_UTIL_SELECT;
263 /* it can't be ONE_RETURNING, so give up */
264 return PORTAL_MULTI_QUERY;
265 }
266 }
267 }
268 else if (IsA(stmt, PlannedStmt))
269 {
270 PlannedStmt *pstmt = (PlannedStmt *) stmt;
271
272 if (pstmt->canSetTag)
273 {
274 if (pstmt->commandType == CMD_SELECT)
275 {
276 if (pstmt->hasModifyingCTE)
277 return PORTAL_ONE_MOD_WITH;
278 else
279 return PORTAL_ONE_SELECT;
280 }
281 if (pstmt->commandType == CMD_UTILITY)
282 {
284 return PORTAL_UTIL_SELECT;
285 /* it can't be ONE_RETURNING, so give up */
286 return PORTAL_MULTI_QUERY;
287 }
288 }
289 }
290 else
291 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
292 }
293
294 /*
295 * PORTAL_ONE_RETURNING has to allow auxiliary queries added by rewrite.
296 * Choose PORTAL_ONE_RETURNING if there is exactly one canSetTag query and
297 * it has a RETURNING list.
298 */
299 nSetTag = 0;
300 foreach(lc, stmts)
301 {
302 Node *stmt = (Node *) lfirst(lc);
303
304 if (IsA(stmt, Query))
305 {
306 Query *query = (Query *) stmt;
307
308 if (query->canSetTag)
309 {
310 if (++nSetTag > 1)
311 return PORTAL_MULTI_QUERY; /* no need to look further */
312 if (query->commandType == CMD_UTILITY ||
313 query->returningList == NIL)
314 return PORTAL_MULTI_QUERY; /* no need to look further */
315 }
316 }
317 else if (IsA(stmt, PlannedStmt))
318 {
319 PlannedStmt *pstmt = (PlannedStmt *) stmt;
320
321 if (pstmt->canSetTag)
322 {
323 if (++nSetTag > 1)
324 return PORTAL_MULTI_QUERY; /* no need to look further */
325 if (pstmt->commandType == CMD_UTILITY ||
326 !pstmt->hasReturning)
327 return PORTAL_MULTI_QUERY; /* no need to look further */
328 }
329 }
330 else
331 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
332 }
333 if (nSetTag == 1)
335
336 /* Else, it's the general case... */
337 return PORTAL_MULTI_QUERY;
338}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define stmt
Definition: indent_codes.h:59
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define nodeTag(nodeptr)
Definition: nodes.h:139
@ CMD_UTILITY
Definition: nodes.h:276
@ CMD_SELECT
Definition: nodes.h:271
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define linitial(l)
Definition: pg_list.h:178
@ PORTAL_ONE_RETURNING
Definition: portal.h:92
@ PORTAL_MULTI_QUERY
Definition: portal.h:95
@ PORTAL_ONE_SELECT
Definition: portal.h:91
@ PORTAL_ONE_MOD_WITH
Definition: portal.h:93
@ PORTAL_UTIL_SELECT
Definition: portal.h:94
Definition: nodes.h:135
bool hasModifyingCTE
Definition: plannodes.h:65
bool canSetTag
Definition: plannodes.h:68
bool hasReturning
Definition: plannodes.h:62
CmdType commandType
Definition: plannodes.h:53
Node * utilityStmt
Definition: plannodes.h:139
List * returningList
Definition: parsenodes.h:209
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
bool UtilityReturnsTuples(Node *parsetree)
Definition: utility.c:2028

References PlannedStmt::canSetTag, CMD_SELECT, CMD_UTILITY, Query::commandType, PlannedStmt::commandType, elog, ERROR, PlannedStmt::hasModifyingCTE, PlannedStmt::hasReturning, IsA, lfirst, linitial, list_length(), NIL, nodeTag, PORTAL_MULTI_QUERY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_UTIL_SELECT, Query::returningList, stmt, UtilityReturnsTuples(), Query::utilityStmt, and PlannedStmt::utilityStmt.

Referenced by PlanCacheComputeResultDesc(), and PortalStart().

◆ CreateQueryDesc()

QueryDesc * CreateQueryDesc ( PlannedStmt plannedstmt,
CachedPlan cplan,
const char *  sourceText,
Snapshot  snapshot,
Snapshot  crosscheck_snapshot,
DestReceiver dest,
ParamListInfo  params,
QueryEnvironment queryEnv,
int  instrument_options 
)

Definition at line 72 of file pquery.c.

81{
82 QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
83
84 qd->operation = plannedstmt->commandType; /* operation */
85 qd->plannedstmt = plannedstmt; /* plan */
86 qd->cplan = cplan; /* CachedPlan supplying the plannedstmt */
87 qd->sourceText = sourceText; /* query text */
88 qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */
89 /* RI check snapshot */
90 qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot);
91 qd->dest = dest; /* output dest */
92 qd->params = params; /* parameter values passed into query */
93 qd->queryEnv = queryEnv;
94 qd->instrument_options = instrument_options; /* instrumentation wanted? */
95
96 /* null these fields until set by ExecutorStart */
97 qd->tupDesc = NULL;
98 qd->estate = NULL;
99 qd->planstate = NULL;
100 qd->totaltime = NULL;
101
102 /* not yet executed */
103 qd->already_executed = false;
104
105 return qd;
106}
void * palloc(Size size)
Definition: mcxt.c:1940
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:811
const char * sourceText
Definition: execdesc.h:39
ParamListInfo params
Definition: execdesc.h:43
DestReceiver * dest
Definition: execdesc.h:42
int instrument_options
Definition: execdesc.h:45
EState * estate
Definition: execdesc.h:49
CachedPlan * cplan
Definition: execdesc.h:38
CmdType operation
Definition: execdesc.h:36
Snapshot snapshot
Definition: execdesc.h:40
bool already_executed
Definition: execdesc.h:53
PlannedStmt * plannedstmt
Definition: execdesc.h:37
struct Instrumentation * totaltime
Definition: execdesc.h:56
QueryEnvironment * queryEnv
Definition: execdesc.h:44
TupleDesc tupDesc
Definition: execdesc.h:48
Snapshot crosscheck_snapshot
Definition: execdesc.h:41
PlanState * planstate
Definition: execdesc.h:50

References QueryDesc::already_executed, PlannedStmt::commandType, QueryDesc::cplan, QueryDesc::crosscheck_snapshot, generate_unaccent_rules::dest, QueryDesc::dest, QueryDesc::estate, QueryDesc::instrument_options, QueryDesc::operation, palloc(), QueryDesc::params, QueryDesc::plannedstmt, QueryDesc::planstate, QueryDesc::queryEnv, RegisterSnapshot(), QueryDesc::snapshot, QueryDesc::sourceText, QueryDesc::totaltime, and QueryDesc::tupDesc.

Referenced by _SPI_execute_plan(), BeginCopyTo(), ExecCreateTableAs(), ExecParallelGetQueryDesc(), execute_sql_string(), ExplainOnePlan(), PortalStart(), postquel_start(), ProcessQuery(), and refresh_matview_datafill().

◆ DoPortalRewind()

static void DoPortalRewind ( Portal  portal)
static

Definition at line 1719 of file pquery.c.

1720{
1721 QueryDesc *queryDesc;
1722
1723 /*
1724 * No work is needed if we've not advanced nor attempted to advance the
1725 * cursor (and we don't want to throw a NO SCROLL error in this case).
1726 */
1727 if (portal->atStart && !portal->atEnd)
1728 return;
1729
1730 /* Otherwise, cursor must allow scrolling */
1731 if (portal->cursorOptions & CURSOR_OPT_NO_SCROLL)
1732 ereport(ERROR,
1733 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1734 errmsg("cursor can only scan forward"),
1735 errhint("Declare it with SCROLL option to enable backward scan.")));
1736
1737 /* Rewind holdStore, if we have one */
1738 if (portal->holdStore)
1739 {
1740 MemoryContext oldcontext;
1741
1742 oldcontext = MemoryContextSwitchTo(portal->holdContext);
1744 MemoryContextSwitchTo(oldcontext);
1745 }
1746
1747 /* Rewind executor, if active */
1748 queryDesc = portal->queryDesc;
1749 if (queryDesc)
1750 {
1751 PushActiveSnapshot(queryDesc->snapshot);
1752 ExecutorRewind(queryDesc);
1754 }
1755
1756 portal->atStart = true;
1757 portal->atEnd = false;
1758 portal->portalPos = 0;
1759}
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:149
void ExecutorRewind(QueryDesc *queryDesc)
Definition: execMain.c:615
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:3377
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:669
void PopActiveSnapshot(void)
Definition: snapmgr.c:762
uint64 portalPos
Definition: portal.h:201
QueryDesc * queryDesc
Definition: portal.h:157
bool atEnd
Definition: portal.h:200
bool atStart
Definition: portal.h:199
MemoryContext holdContext
Definition: portal.h:178
Tuplestorestate * holdStore
Definition: portal.h:177
int cursorOptions
Definition: portal.h:148
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1285

References PortalData::atEnd, PortalData::atStart, CURSOR_OPT_NO_SCROLL, PortalData::cursorOptions, ereport, errcode(), errhint(), errmsg(), ERROR, ExecutorRewind(), PortalData::holdContext, PortalData::holdStore, MemoryContextSwitchTo(), PopActiveSnapshot(), PortalData::portalPos, PushActiveSnapshot(), PortalData::queryDesc, QueryDesc::snapshot, and tuplestore_rescan().

Referenced by DoPortalRunFetch().

◆ DoPortalRunFetch()

static uint64 DoPortalRunFetch ( Portal  portal,
FetchDirection  fdirection,
long  count,
DestReceiver dest 
)
static

Definition at line 1525 of file pquery.c.

1529{
1530 bool forward;
1531
1532 Assert(portal->strategy == PORTAL_ONE_SELECT ||
1533 portal->strategy == PORTAL_ONE_RETURNING ||
1534 portal->strategy == PORTAL_ONE_MOD_WITH ||
1535 portal->strategy == PORTAL_UTIL_SELECT);
1536
1537 /*
1538 * Note: we disallow backwards fetch (including re-fetch of current row)
1539 * for NO SCROLL cursors, but we interpret that very loosely: you can use
1540 * any of the FetchDirection options, so long as the end result is to move
1541 * forwards by at least one row. Currently it's sufficient to check for
1542 * NO SCROLL in DoPortalRewind() and in the forward == false path in
1543 * PortalRunSelect(); but someday we might prefer to account for that
1544 * restriction explicitly here.
1545 */
1546 switch (fdirection)
1547 {
1548 case FETCH_FORWARD:
1549 if (count < 0)
1550 {
1551 fdirection = FETCH_BACKWARD;
1552 count = -count;
1553 }
1554 /* fall out of switch to share code with FETCH_BACKWARD */
1555 break;
1556 case FETCH_BACKWARD:
1557 if (count < 0)
1558 {
1559 fdirection = FETCH_FORWARD;
1560 count = -count;
1561 }
1562 /* fall out of switch to share code with FETCH_FORWARD */
1563 break;
1564 case FETCH_ABSOLUTE:
1565 if (count > 0)
1566 {
1567 /*
1568 * Definition: Rewind to start, advance count-1 rows, return
1569 * next row (if any).
1570 *
1571 * In practice, if the goal is less than halfway back to the
1572 * start, it's better to scan from where we are.
1573 *
1574 * Also, if current portalPos is outside the range of "long",
1575 * do it the hard way to avoid possible overflow of the count
1576 * argument to PortalRunSelect. We must exclude exactly
1577 * LONG_MAX, as well, lest the count look like FETCH_ALL.
1578 *
1579 * In any case, we arrange to fetch the target row going
1580 * forwards.
1581 */
1582 if ((uint64) (count - 1) <= portal->portalPos / 2 ||
1583 portal->portalPos >= (uint64) LONG_MAX)
1584 {
1585 DoPortalRewind(portal);
1586 if (count > 1)
1587 PortalRunSelect(portal, true, count - 1,
1589 }
1590 else
1591 {
1592 long pos = (long) portal->portalPos;
1593
1594 if (portal->atEnd)
1595 pos++; /* need one extra fetch if off end */
1596 if (count <= pos)
1597 PortalRunSelect(portal, false, pos - count + 1,
1599 else if (count > pos + 1)
1600 PortalRunSelect(portal, true, count - pos - 1,
1602 }
1603 return PortalRunSelect(portal, true, 1L, dest);
1604 }
1605 else if (count < 0)
1606 {
1607 /*
1608 * Definition: Advance to end, back up abs(count)-1 rows,
1609 * return prior row (if any). We could optimize this if we
1610 * knew in advance where the end was, but typically we won't.
1611 * (Is it worth considering case where count > half of size of
1612 * query? We could rewind once we know the size ...)
1613 */
1614 PortalRunSelect(portal, true, FETCH_ALL, None_Receiver);
1615 if (count < -1)
1616 PortalRunSelect(portal, false, -count - 1, None_Receiver);
1617 return PortalRunSelect(portal, false, 1L, dest);
1618 }
1619 else
1620 {
1621 /* count == 0 */
1622 /* Rewind to start, return zero rows */
1623 DoPortalRewind(portal);
1624 return PortalRunSelect(portal, true, 0L, dest);
1625 }
1626 break;
1627 case FETCH_RELATIVE:
1628 if (count > 0)
1629 {
1630 /*
1631 * Definition: advance count-1 rows, return next row (if any).
1632 */
1633 if (count > 1)
1634 PortalRunSelect(portal, true, count - 1, None_Receiver);
1635 return PortalRunSelect(portal, true, 1L, dest);
1636 }
1637 else if (count < 0)
1638 {
1639 /*
1640 * Definition: back up abs(count)-1 rows, return prior row (if
1641 * any).
1642 */
1643 if (count < -1)
1644 PortalRunSelect(portal, false, -count - 1, None_Receiver);
1645 return PortalRunSelect(portal, false, 1L, dest);
1646 }
1647 else
1648 {
1649 /* count == 0 */
1650 /* Same as FETCH FORWARD 0, so fall out of switch */
1651 fdirection = FETCH_FORWARD;
1652 }
1653 break;
1654 default:
1655 elog(ERROR, "bogus direction");
1656 break;
1657 }
1658
1659 /*
1660 * Get here with fdirection == FETCH_FORWARD or FETCH_BACKWARD, and count
1661 * >= 0.
1662 */
1663 forward = (fdirection == FETCH_FORWARD);
1664
1665 /*
1666 * Zero count means to re-fetch the current row, if any (per SQL)
1667 */
1668 if (count == 0)
1669 {
1670 bool on_row;
1671
1672 /* Are we sitting on a row? */
1673 on_row = (!portal->atStart && !portal->atEnd);
1674
1675 if (dest->mydest == DestNone)
1676 {
1677 /* MOVE 0 returns 0/1 based on if FETCH 0 would return a row */
1678 return on_row ? 1 : 0;
1679 }
1680 else
1681 {
1682 /*
1683 * If we are sitting on a row, back up one so we can re-fetch it.
1684 * If we are not sitting on a row, we still have to start up and
1685 * shut down the executor so that the destination is initialized
1686 * and shut down correctly; so keep going. To PortalRunSelect,
1687 * count == 0 means we will retrieve no row.
1688 */
1689 if (on_row)
1690 {
1691 PortalRunSelect(portal, false, 1L, None_Receiver);
1692 /* Set up to fetch one row forward */
1693 count = 1;
1694 forward = true;
1695 }
1696 }
1697 }
1698
1699 /*
1700 * Optimize MOVE BACKWARD ALL into a Rewind.
1701 */
1702 if (!forward && count == FETCH_ALL && dest->mydest == DestNone)
1703 {
1704 uint64 result = portal->portalPos;
1705
1706 if (result > 0 && !portal->atEnd)
1707 result--;
1708 DoPortalRewind(portal);
1709 return result;
1710 }
1711
1712 return PortalRunSelect(portal, forward, count, dest);
1713}
uint64_t uint64
Definition: c.h:503
DestReceiver * None_Receiver
Definition: dest.c:96
@ DestNone
Definition: dest.h:87
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
#define FETCH_ALL
Definition: parsenodes.h:3420
@ FETCH_RELATIVE
Definition: parsenodes.h:3417
@ FETCH_ABSOLUTE
Definition: parsenodes.h:3416
@ FETCH_FORWARD
Definition: parsenodes.h:3413
@ FETCH_BACKWARD
Definition: parsenodes.h:3414
static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest)
Definition: pquery.c:896
static void DoPortalRewind(Portal portal)
Definition: pquery.c:1719
PortalStrategy strategy
Definition: portal.h:147

References Assert(), PortalData::atEnd, PortalData::atStart, generate_unaccent_rules::dest, DestNone, DoPortalRewind(), elog, ERROR, FETCH_ABSOLUTE, FETCH_ALL, FETCH_BACKWARD, FETCH_FORWARD, FETCH_RELATIVE, if(), None_Receiver, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_UTIL_SELECT, PortalData::portalPos, PortalRunSelect(), and PortalData::strategy.

Referenced by PortalRunFetch().

◆ EnsurePortalSnapshotExists()

void EnsurePortalSnapshotExists ( void  )

Definition at line 1813 of file pquery.c.

1814{
1815 Portal portal;
1816
1817 /*
1818 * Nothing to do if a snapshot is set. (We take it on faith that the
1819 * outermost active snapshot belongs to some Portal; or if there is no
1820 * Portal, it's somebody else's responsibility to manage things.)
1821 */
1822 if (ActiveSnapshotSet())
1823 return;
1824
1825 /* Otherwise, we'd better have an active Portal */
1826 portal = ActivePortal;
1827 if (unlikely(portal == NULL))
1828 elog(ERROR, "cannot execute SQL without an outer snapshot or portal");
1829 Assert(portal->portalSnapshot == NULL);
1830
1831 /*
1832 * Create a new snapshot, make it active, and remember it in portal.
1833 * Because the portal now references the snapshot, we must tell snapmgr.c
1834 * that the snapshot belongs to the portal's transaction level, else we
1835 * risk portalSnapshot becoming a dangling pointer.
1836 */
1838 /* PushActiveSnapshotWithLevel might have copied the snapshot */
1840}
#define unlikely(x)
Definition: c.h:347
Portal ActivePortal
Definition: pquery.c:37
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:271
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:799
void PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level)
Definition: snapmgr.c:683
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:787
Snapshot portalSnapshot
Definition: portal.h:170
int createLevel
Definition: portal.h:133

References ActivePortal, ActiveSnapshotSet(), Assert(), PortalData::createLevel, elog, ERROR, GetActiveSnapshot(), GetTransactionSnapshot(), PortalData::portalSnapshot, PushActiveSnapshotWithLevel(), and unlikely.

Referenced by _SPI_execute_plan(), exec_eval_simple_expr(), and ExecuteCallStmt().

◆ FetchPortalTargetList()

List * FetchPortalTargetList ( Portal  portal)

Definition at line 348 of file pquery.c.

349{
350 /* no point in looking if we determined it doesn't return tuples */
351 if (portal->strategy == PORTAL_MULTI_QUERY)
352 return NIL;
353 /* get the primary statement and find out what it returns */
355}
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
Definition: portalmem.c:151
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:370

References FetchStatementTargetList(), NIL, PORTAL_MULTI_QUERY, PortalGetPrimaryStmt(), and PortalData::strategy.

Referenced by exec_describe_portal_message(), FetchStatementTargetList(), and printtup_startup().

◆ FetchStatementTargetList()

List * FetchStatementTargetList ( Node stmt)

Definition at line 370 of file pquery.c.

371{
372 if (stmt == NULL)
373 return NIL;
374 if (IsA(stmt, Query))
375 {
376 Query *query = (Query *) stmt;
377
378 if (query->commandType == CMD_UTILITY)
379 {
380 /* transfer attention to utility statement */
381 stmt = query->utilityStmt;
382 }
383 else
384 {
385 if (query->commandType == CMD_SELECT)
386 return query->targetList;
387 if (query->returningList)
388 return query->returningList;
389 return NIL;
390 }
391 }
392 if (IsA(stmt, PlannedStmt))
393 {
394 PlannedStmt *pstmt = (PlannedStmt *) stmt;
395
396 if (pstmt->commandType == CMD_UTILITY)
397 {
398 /* transfer attention to utility statement */
399 stmt = pstmt->utilityStmt;
400 }
401 else
402 {
403 if (pstmt->commandType == CMD_SELECT)
404 return pstmt->planTree->targetlist;
405 if (pstmt->hasReturning)
406 return pstmt->planTree->targetlist;
407 return NIL;
408 }
409 }
410 if (IsA(stmt, FetchStmt))
411 {
412 FetchStmt *fstmt = (FetchStmt *) stmt;
413 Portal subportal;
414
415 Assert(!fstmt->ismove);
416 subportal = GetPortalByName(fstmt->portalname);
417 Assert(PortalIsValid(subportal));
418 return FetchPortalTargetList(subportal);
419 }
420 if (IsA(stmt, ExecuteStmt))
421 {
422 ExecuteStmt *estmt = (ExecuteStmt *) stmt;
423 PreparedStatement *entry;
424
425 entry = FetchPreparedStatement(estmt->name, true);
427 }
428 return NIL;
429}
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:435
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:490
#define PortalIsValid(p)
Definition: portal.h:212
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
List * FetchPortalTargetList(Portal portal)
Definition: pquery.c:348
char * name
Definition: parsenodes.h:4143
bool ismove
Definition: parsenodes.h:3428
char * portalname
Definition: parsenodes.h:3427
List * targetlist
Definition: plannodes.h:209
struct Plan * planTree
Definition: plannodes.h:83
List * targetList
Definition: parsenodes.h:193

References Assert(), CMD_SELECT, CMD_UTILITY, Query::commandType, PlannedStmt::commandType, FetchPortalTargetList(), FetchPreparedStatement(), FetchPreparedStatementTargetList(), GetPortalByName(), PlannedStmt::hasReturning, IsA, FetchStmt::ismove, ExecuteStmt::name, NIL, PlannedStmt::planTree, PortalIsValid, FetchStmt::portalname, Query::returningList, stmt, Query::targetList, Plan::targetlist, Query::utilityStmt, and PlannedStmt::utilityStmt.

Referenced by CachedPlanGetTargetList(), and FetchPortalTargetList().

◆ FillPortalStore()

static void FillPortalStore ( Portal  portal,
bool  isTopLevel 
)
static

Definition at line 1027 of file pquery.c.

1028{
1029 DestReceiver *treceiver;
1030 QueryCompletion qc;
1031
1033 PortalCreateHoldStore(portal);
1036 portal->holdStore,
1037 portal->holdContext,
1038 false,
1039 NULL,
1040 NULL);
1041
1042 switch (portal->strategy)
1043 {
1046
1047 /*
1048 * Run the portal to completion just as for the default
1049 * PORTAL_MULTI_QUERY case, but send the primary query's output to
1050 * the tuplestore. Auxiliary query outputs are discarded. Set the
1051 * portal's holdSnapshot to the snapshot used (or a copy of it).
1052 */
1053 PortalRunMulti(portal, isTopLevel, true,
1054 treceiver, None_Receiver, &qc);
1055 break;
1056
1057 case PORTAL_UTIL_SELECT:
1059 isTopLevel, true, treceiver, &qc);
1060 break;
1061
1062 default:
1063 elog(ERROR, "unsupported portal strategy: %d",
1064 (int) portal->strategy);
1065 break;
1066 }
1067
1068 /* Override portal completion data with actual command results */
1069 if (qc.commandTag != CMDTAG_UNKNOWN)
1070 CopyQueryCompletion(&portal->qc, &qc);
1071
1072 treceiver->rDestroy(treceiver);
1073}
void InitializeQueryCompletion(QueryCompletion *qc)
Definition: cmdtag.c:40
static void CopyQueryCompletion(QueryCompletion *dst, const QueryCompletion *src)
Definition: cmdtag.h:45
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestTuplestore
Definition: dest.h:93
#define linitial_node(type, l)
Definition: pg_list.h:181
void PortalCreateHoldStore(Portal portal)
Definition: portalmem.c:333
static void PortalRunMulti(Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
Definition: pquery.c:1217
static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, QueryCompletion *qc)
Definition: pquery.c:1154
List * stmts
Definition: portal.h:139
QueryCompletion qc
Definition: portal.h:138
CommandTag commandTag
Definition: cmdtag.h:31
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
void SetTuplestoreDestReceiverParams(DestReceiver *self, Tuplestorestate *tStore, MemoryContext tContext, bool detoast, TupleDesc target_tupdesc, const char *map_failure_msg)

References QueryCompletion::commandTag, CopyQueryCompletion(), CreateDestReceiver(), DestTuplestore, elog, ERROR, PortalData::holdContext, PortalData::holdStore, InitializeQueryCompletion(), linitial_node, None_Receiver, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_UTIL_SELECT, PortalCreateHoldStore(), PortalRunMulti(), PortalRunUtility(), PortalData::qc, _DestReceiver::rDestroy, SetTuplestoreDestReceiverParams(), PortalData::stmts, and PortalData::strategy.

Referenced by PortalRun(), and PortalRunFetch().

◆ FreeQueryDesc()

void FreeQueryDesc ( QueryDesc qdesc)

Definition at line 112 of file pquery.c.

113{
114 /* Can't be a live query */
115 Assert(qdesc->estate == NULL);
116
117 /* forget our snapshots */
120
121 /* Only the QueryDesc itself need be freed */
122 pfree(qdesc);
123}
void pfree(void *pointer)
Definition: mcxt.c:2147
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:853

References Assert(), QueryDesc::crosscheck_snapshot, QueryDesc::estate, pfree(), QueryDesc::snapshot, and UnregisterSnapshot().

Referenced by _SPI_execute_plan(), EndCopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), ParallelQueryMain(), PersistHoldablePortal(), PortalCleanup(), postquel_end(), ProcessQuery(), and refresh_matview_datafill().

◆ PlannedStmtRequiresSnapshot()

bool PlannedStmtRequiresSnapshot ( PlannedStmt pstmt)

Definition at line 1765 of file pquery.c.

1766{
1767 Node *utilityStmt = pstmt->utilityStmt;
1768
1769 /* If it's not a utility statement, it definitely needs a snapshot */
1770 if (utilityStmt == NULL)
1771 return true;
1772
1773 /*
1774 * Most utility statements need a snapshot, and the default presumption
1775 * about new ones should be that they do too. Hence, enumerate those that
1776 * do not need one.
1777 *
1778 * Transaction control, LOCK, and SET must *not* set a snapshot, since
1779 * they need to be executable at the start of a transaction-snapshot-mode
1780 * transaction without freezing a snapshot. By extension we allow SHOW
1781 * not to set a snapshot. The other stmts listed are just efficiency
1782 * hacks. Beware of listing anything that can modify the database --- if,
1783 * say, it has to update an index with expressions that invoke
1784 * user-defined functions, then it had better have a snapshot.
1785 */
1786 if (IsA(utilityStmt, TransactionStmt) ||
1787 IsA(utilityStmt, LockStmt) ||
1788 IsA(utilityStmt, VariableSetStmt) ||
1789 IsA(utilityStmt, VariableShowStmt) ||
1790 IsA(utilityStmt, ConstraintsSetStmt) ||
1791 /* efficiency hacks from here down */
1792 IsA(utilityStmt, FetchStmt) ||
1793 IsA(utilityStmt, ListenStmt) ||
1794 IsA(utilityStmt, NotifyStmt) ||
1795 IsA(utilityStmt, UnlistenStmt) ||
1796 IsA(utilityStmt, CheckPointStmt))
1797 return false;
1798
1799 return true;
1800}

References IsA, and PlannedStmt::utilityStmt.

Referenced by _SPI_execute_plan(), and PortalRunUtility().

◆ PortalRun()

bool PortalRun ( Portal  portal,
long  count,
bool  isTopLevel,
DestReceiver dest,
DestReceiver altdest,
QueryCompletion qc 
)

Definition at line 717 of file pquery.c.

720{
721 bool result;
722 uint64 nprocessed;
723 ResourceOwner saveTopTransactionResourceOwner;
724 MemoryContext saveTopTransactionContext;
725 Portal saveActivePortal;
726 ResourceOwner saveResourceOwner;
727 MemoryContext savePortalContext;
728 MemoryContext saveMemoryContext;
729
730 Assert(PortalIsValid(portal));
731
732 TRACE_POSTGRESQL_QUERY_EXECUTE_START();
733
734 /* Initialize empty completion data */
735 if (qc)
737
739 {
740 elog(DEBUG3, "PortalRun");
741 /* PORTAL_MULTI_QUERY logs its own stats per query */
742 ResetUsage();
743 }
744
745 /*
746 * Check for improper portal use, and mark portal active.
747 */
748 MarkPortalActive(portal);
749
750 /*
751 * Set up global portal context pointers.
752 *
753 * We have to play a special game here to support utility commands like
754 * VACUUM and CLUSTER, which internally start and commit transactions.
755 * When we are called to execute such a command, CurrentResourceOwner will
756 * be pointing to the TopTransactionResourceOwner --- which will be
757 * destroyed and replaced in the course of the internal commit and
758 * restart. So we need to be prepared to restore it as pointing to the
759 * exit-time TopTransactionResourceOwner. (Ain't that ugly? This idea of
760 * internally starting whole new transactions is not good.)
761 * CurrentMemoryContext has a similar problem, but the other pointers we
762 * save here will be NULL or pointing to longer-lived objects.
763 */
764 saveTopTransactionResourceOwner = TopTransactionResourceOwner;
765 saveTopTransactionContext = TopTransactionContext;
766 saveActivePortal = ActivePortal;
767 saveResourceOwner = CurrentResourceOwner;
768 savePortalContext = PortalContext;
769 saveMemoryContext = CurrentMemoryContext;
770 PG_TRY();
771 {
772 ActivePortal = portal;
773 if (portal->resowner)
776
778
779 switch (portal->strategy)
780 {
785
786 /*
787 * If we have not yet run the command, do so, storing its
788 * results in the portal's tuplestore. But we don't do that
789 * for the PORTAL_ONE_SELECT case.
790 */
791 if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
792 FillPortalStore(portal, isTopLevel);
793
794 /*
795 * Now fetch desired portion of results.
796 */
797 nprocessed = PortalRunSelect(portal, true, count, dest);
798
799 /*
800 * If the portal result contains a command tag and the caller
801 * gave us a pointer to store it, copy it and update the
802 * rowcount.
803 */
804 if (qc && portal->qc.commandTag != CMDTAG_UNKNOWN)
805 {
806 CopyQueryCompletion(qc, &portal->qc);
807 qc->nprocessed = nprocessed;
808 }
809
810 /* Mark portal not active */
811 portal->status = PORTAL_READY;
812
813 /*
814 * Since it's a forward fetch, say DONE iff atEnd is now true.
815 */
816 result = portal->atEnd;
817 break;
818
820 PortalRunMulti(portal, isTopLevel, false,
821 dest, altdest, qc);
822
823 /* Prevent portal's commands from being re-executed */
824 MarkPortalDone(portal);
825
826 /* Always complete at end of RunMulti */
827 result = true;
828 break;
829
830 default:
831 elog(ERROR, "unrecognized portal strategy: %d",
832 (int) portal->strategy);
833 result = false; /* keep compiler quiet */
834 break;
835 }
836 }
837 PG_CATCH();
838 {
839 /* Uncaught error while executing portal: mark it dead */
840 MarkPortalFailed(portal);
841
842 /* Restore global vars and propagate error */
843 if (saveMemoryContext == saveTopTransactionContext)
845 else
846 MemoryContextSwitchTo(saveMemoryContext);
847 ActivePortal = saveActivePortal;
848 if (saveResourceOwner == saveTopTransactionResourceOwner)
850 else
851 CurrentResourceOwner = saveResourceOwner;
852 PortalContext = savePortalContext;
853
854 PG_RE_THROW();
855 }
856 PG_END_TRY();
857
858 if (saveMemoryContext == saveTopTransactionContext)
860 else
861 MemoryContextSwitchTo(saveMemoryContext);
862 ActivePortal = saveActivePortal;
863 if (saveResourceOwner == saveTopTransactionResourceOwner)
865 else
866 CurrentResourceOwner = saveResourceOwner;
867 PortalContext = savePortalContext;
868
870 ShowUsage("EXECUTOR STATISTICS");
871
872 TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
873
874 return result;
875}
#define PG_RE_THROW()
Definition: elog.h:405
#define DEBUG3
Definition: elog.h:28
#define PG_TRY(...)
Definition: elog.h:372
#define PG_END_TRY(...)
Definition: elog.h:397
#define PG_CATCH(...)
Definition: elog.h:382
bool log_executor_stats
Definition: guc_tables.c:521
MemoryContext TopTransactionContext
Definition: mcxt.c:170
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
MemoryContext PortalContext
Definition: mcxt.c:174
@ PORTAL_READY
Definition: portal.h:107
void MarkPortalDone(Portal portal)
Definition: portalmem.c:416
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:444
void MarkPortalActive(Portal portal)
Definition: portalmem.c:397
void ShowUsage(const char *title)
Definition: postgres.c:5064
void ResetUsage(void)
Definition: postgres.c:5057
static void FillPortalStore(Portal portal, bool isTopLevel)
Definition: pquery.c:1027
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:175
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
ResourceOwner resowner
Definition: portal.h:121
MemoryContext portalContext
Definition: portal.h:120
PortalStatus status
Definition: portal.h:151
uint64 nprocessed
Definition: cmdtag.h:32

References ActivePortal, Assert(), PortalData::atEnd, QueryCompletion::commandTag, CopyQueryCompletion(), CurrentMemoryContext, CurrentResourceOwner, DEBUG3, generate_unaccent_rules::dest, elog, ERROR, FillPortalStore(), PortalData::holdStore, InitializeQueryCompletion(), log_executor_stats, MarkPortalActive(), MarkPortalDone(), MarkPortalFailed(), MemoryContextSwitchTo(), QueryCompletion::nprocessed, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PORTAL_MULTI_QUERY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_READY, PORTAL_UTIL_SELECT, PortalContext, PortalData::portalContext, PortalIsValid, PortalRunMulti(), PortalRunSelect(), PortalData::qc, ResetUsage(), PortalData::resowner, ShowUsage(), PortalData::status, PortalData::strategy, TopTransactionContext, and TopTransactionResourceOwner.

Referenced by exec_execute_message(), exec_simple_query(), and ExecuteQuery().

◆ PortalRunFetch()

uint64 PortalRunFetch ( Portal  portal,
FetchDirection  fdirection,
long  count,
DestReceiver dest 
)

Definition at line 1427 of file pquery.c.

1431{
1432 uint64 result;
1433 Portal saveActivePortal;
1434 ResourceOwner saveResourceOwner;
1435 MemoryContext savePortalContext;
1436 MemoryContext oldContext;
1437
1438 Assert(PortalIsValid(portal));
1439
1440 /*
1441 * Check for improper portal use, and mark portal active.
1442 */
1443 MarkPortalActive(portal);
1444
1445 /*
1446 * Set up global portal context pointers.
1447 */
1448 saveActivePortal = ActivePortal;
1449 saveResourceOwner = CurrentResourceOwner;
1450 savePortalContext = PortalContext;
1451 PG_TRY();
1452 {
1453 ActivePortal = portal;
1454 if (portal->resowner)
1456 PortalContext = portal->portalContext;
1457
1459
1460 switch (portal->strategy)
1461 {
1462 case PORTAL_ONE_SELECT:
1463 result = DoPortalRunFetch(portal, fdirection, count, dest);
1464 break;
1465
1468 case PORTAL_UTIL_SELECT:
1469
1470 /*
1471 * If we have not yet run the command, do so, storing its
1472 * results in the portal's tuplestore.
1473 */
1474 if (!portal->holdStore)
1475 FillPortalStore(portal, false /* isTopLevel */ );
1476
1477 /*
1478 * Now fetch desired portion of results.
1479 */
1480 result = DoPortalRunFetch(portal, fdirection, count, dest);
1481 break;
1482
1483 default:
1484 elog(ERROR, "unsupported portal strategy");
1485 result = 0; /* keep compiler quiet */
1486 break;
1487 }
1488 }
1489 PG_CATCH();
1490 {
1491 /* Uncaught error while executing portal: mark it dead */
1492 MarkPortalFailed(portal);
1493
1494 /* Restore global vars and propagate error */
1495 ActivePortal = saveActivePortal;
1496 CurrentResourceOwner = saveResourceOwner;
1497 PortalContext = savePortalContext;
1498
1499 PG_RE_THROW();
1500 }
1501 PG_END_TRY();
1502
1503 MemoryContextSwitchTo(oldContext);
1504
1505 /* Mark portal not active */
1506 portal->status = PORTAL_READY;
1507
1508 ActivePortal = saveActivePortal;
1509 CurrentResourceOwner = saveResourceOwner;
1510 PortalContext = savePortalContext;
1511
1512 return result;
1513}
static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1525

References ActivePortal, Assert(), CurrentResourceOwner, generate_unaccent_rules::dest, DoPortalRunFetch(), elog, ERROR, FillPortalStore(), PortalData::holdStore, MarkPortalActive(), MarkPortalFailed(), MemoryContextSwitchTo(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_READY, PORTAL_UTIL_SELECT, PortalContext, PortalData::portalContext, PortalIsValid, PortalData::resowner, PortalData::status, and PortalData::strategy.

Referenced by _SPI_cursor_operation(), and PerformPortalFetch().

◆ PortalRunMulti()

static void PortalRunMulti ( Portal  portal,
bool  isTopLevel,
bool  setHoldSnapshot,
DestReceiver dest,
DestReceiver altdest,
QueryCompletion qc 
)
static

Definition at line 1217 of file pquery.c.

1221{
1222 bool active_snapshot_set = false;
1223 ListCell *stmtlist_item;
1224 int query_index = 0;
1225
1226 /*
1227 * If the destination is DestRemoteExecute, change to DestNone. The
1228 * reason is that the client won't be expecting any tuples, and indeed has
1229 * no way to know what they are, since there is no provision for Describe
1230 * to send a RowDescription message when this portal execution strategy is
1231 * in effect. This presently will only affect SELECT commands added to
1232 * non-SELECT queries by rewrite rules: such commands will be executed,
1233 * but the results will be discarded unless you use "simple Query"
1234 * protocol.
1235 */
1236 if (dest->mydest == DestRemoteExecute)
1238 if (altdest->mydest == DestRemoteExecute)
1239 altdest = None_Receiver;
1240
1241 /*
1242 * Loop to handle the individual queries generated from a single parsetree
1243 * by analysis and rewrite.
1244 */
1245 foreach(stmtlist_item, portal->stmts)
1246 {
1247 PlannedStmt *pstmt = lfirst_node(PlannedStmt, stmtlist_item);
1248
1249 /*
1250 * If we got a cancel signal in prior command, quit
1251 */
1253
1254 if (pstmt->utilityStmt == NULL)
1255 {
1256 /*
1257 * process a plannable query.
1258 */
1259 TRACE_POSTGRESQL_QUERY_EXECUTE_START();
1260
1262 ResetUsage();
1263
1264 /*
1265 * Must always have a snapshot for plannable queries. First time
1266 * through, take a new snapshot; for subsequent queries in the
1267 * same portal, just update the snapshot's copy of the command
1268 * counter.
1269 */
1270 if (!active_snapshot_set)
1271 {
1272 Snapshot snapshot = GetTransactionSnapshot();
1273
1274 /* If told to, register the snapshot and save in portal */
1275 if (setHoldSnapshot)
1276 {
1277 snapshot = RegisterSnapshot(snapshot);
1278 portal->holdSnapshot = snapshot;
1279 }
1280
1281 /*
1282 * We can't have the holdSnapshot also be the active one,
1283 * because UpdateActiveSnapshotCommandId would complain. So
1284 * force an extra snapshot copy. Plain PushActiveSnapshot
1285 * would have copied the transaction snapshot anyway, so this
1286 * only adds a copy step when setHoldSnapshot is true. (It's
1287 * okay for the command ID of the active snapshot to diverge
1288 * from what holdSnapshot has.)
1289 */
1290 PushCopiedSnapshot(snapshot);
1291
1292 /*
1293 * As for PORTAL_ONE_SELECT portals, it does not seem
1294 * necessary to maintain portal->portalSnapshot here.
1295 */
1296
1297 active_snapshot_set = true;
1298 }
1299 else
1301
1302 if (pstmt->canSetTag)
1303 {
1304 /* statement can set tag string */
1305 ProcessQuery(pstmt,
1306 portal->cplan,
1307 portal->plansource,
1308 query_index,
1309 portal->sourceText,
1310 portal->portalParams,
1311 portal->queryEnv,
1312 dest, qc);
1313 }
1314 else
1315 {
1316 /* stmt added by rewrite cannot set tag */
1317 ProcessQuery(pstmt,
1318 portal->cplan,
1319 portal->plansource,
1320 query_index,
1321 portal->sourceText,
1322 portal->portalParams,
1323 portal->queryEnv,
1324 altdest, NULL);
1325 }
1326
1328 ShowUsage("EXECUTOR STATISTICS");
1329
1330 TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
1331 }
1332 else
1333 {
1334 /*
1335 * process utility functions (create, destroy, etc..)
1336 *
1337 * We must not set a snapshot here for utility commands (if one is
1338 * needed, PortalRunUtility will do it). If a utility command is
1339 * alone in a portal then everything's fine. The only case where
1340 * a utility command can be part of a longer list is that rules
1341 * are allowed to include NotifyStmt. NotifyStmt doesn't care
1342 * whether it has a snapshot or not, so we just leave the current
1343 * snapshot alone if we have one.
1344 */
1345 if (pstmt->canSetTag)
1346 {
1347 Assert(!active_snapshot_set);
1348 /* statement can set tag string */
1349 PortalRunUtility(portal, pstmt, isTopLevel, false,
1350 dest, qc);
1351 }
1352 else
1353 {
1354 Assert(IsA(pstmt->utilityStmt, NotifyStmt));
1355 /* stmt added by rewrite cannot set tag */
1356 PortalRunUtility(portal, pstmt, isTopLevel, false,
1357 altdest, NULL);
1358 }
1359 }
1360
1361 /*
1362 * Clear subsidiary contexts to recover temporary memory.
1363 */
1365
1367
1368 /*
1369 * Avoid crashing if portal->stmts has been reset. This can only
1370 * occur if a CALL or DO utility statement executed an internal
1371 * COMMIT/ROLLBACK (cf PortalReleaseCachedPlan). The CALL or DO must
1372 * have been the only statement in the portal, so there's nothing left
1373 * for us to do; but we don't want to dereference a now-dangling list
1374 * pointer.
1375 */
1376 if (portal->stmts == NIL)
1377 break;
1378
1379 /*
1380 * Increment command counter between queries, but not after the last
1381 * one.
1382 */
1383 if (lnext(portal->stmts, stmtlist_item) != NULL)
1385
1386 query_index++;
1387 }
1388
1389 /* Pop the snapshot if we pushed one. */
1390 if (active_snapshot_set)
1392
1393 /*
1394 * If a query completion data was supplied, use it. Otherwise use the
1395 * portal's query completion data.
1396 *
1397 * Exception: Clients expect INSERT/UPDATE/DELETE tags to have counts, so
1398 * fake them with zeros. This can happen with DO INSTEAD rules if there
1399 * is no replacement query of the same type as the original. We print "0
1400 * 0" here because technically there is no query of the matching tag type,
1401 * and printing a non-zero count for a different query type seems wrong,
1402 * e.g. an INSERT that does an UPDATE instead should not print "0 1" if
1403 * one row was updated. See QueryRewrite(), step 3, for details.
1404 */
1405 if (qc && qc->commandTag == CMDTAG_UNKNOWN)
1406 {
1407 if (portal->qc.commandTag != CMDTAG_UNKNOWN)
1408 CopyQueryCompletion(qc, &portal->qc);
1409 /* If the caller supplied a qc, we should have set it by now. */
1410 Assert(qc->commandTag != CMDTAG_UNKNOWN);
1411 }
1412}
@ DestRemoteExecute
Definition: dest.h:90
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:570
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
static void ProcessQuery(PlannedStmt *plan, CachedPlan *cplan, CachedPlanSource *plansource, int query_index, const char *sourceText, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: pquery.c:146
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:731
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:719
CachedPlanSource * plansource
Definition: portal.h:141
const char * sourceText
Definition: portal.h:136
QueryEnvironment * queryEnv
Definition: portal.h:144
ParamListInfo portalParams
Definition: portal.h:143
Snapshot holdSnapshot
Definition: portal.h:188
CachedPlan * cplan
Definition: portal.h:140
CommandDest mydest
Definition: dest.h:128
void CommandCounterIncrement(void)
Definition: xact.c:1100

References Assert(), PlannedStmt::canSetTag, CHECK_FOR_INTERRUPTS, CommandCounterIncrement(), QueryCompletion::commandTag, CopyQueryCompletion(), PortalData::cplan, CurrentMemoryContext, generate_unaccent_rules::dest, DestRemoteExecute, GetTransactionSnapshot(), PortalData::holdSnapshot, IsA, lfirst_node, lnext(), log_executor_stats, MemoryContextDeleteChildren(), _DestReceiver::mydest, NIL, None_Receiver, PortalData::plansource, PopActiveSnapshot(), PortalData::portalContext, PortalData::portalParams, PortalRunUtility(), ProcessQuery(), PushCopiedSnapshot(), PortalData::qc, PortalData::queryEnv, RegisterSnapshot(), ResetUsage(), ShowUsage(), PortalData::sourceText, PortalData::stmts, UpdateActiveSnapshotCommandId(), and PlannedStmt::utilityStmt.

Referenced by FillPortalStore(), and PortalRun().

◆ PortalRunSelect()

static uint64 PortalRunSelect ( Portal  portal,
bool  forward,
long  count,
DestReceiver dest 
)
static

Definition at line 896 of file pquery.c.

900{
901 QueryDesc *queryDesc;
902 ScanDirection direction;
903 uint64 nprocessed;
904
905 /*
906 * NB: queryDesc will be NULL if we are fetching from a held cursor or a
907 * completed utility query; can't use it in that path.
908 */
909 queryDesc = portal->queryDesc;
910
911 /* Caller messed up if we have neither a ready query nor held data. */
912 Assert(queryDesc || portal->holdStore);
913
914 /*
915 * Force the queryDesc destination to the right thing. This supports
916 * MOVE, for example, which will pass in dest = DestNone. This is okay to
917 * change as long as we do it on every fetch. (The Executor must not
918 * assume that dest never changes.)
919 */
920 if (queryDesc)
921 queryDesc->dest = dest;
922
923 /*
924 * Determine which direction to go in, and check to see if we're already
925 * at the end of the available tuples in that direction. If so, set the
926 * direction to NoMovement to avoid trying to fetch any tuples. (This
927 * check exists because not all plan node types are robust about being
928 * called again if they've already returned NULL once.) Then call the
929 * executor (we must not skip this, because the destination needs to see a
930 * setup and shutdown even if no tuples are available). Finally, update
931 * the portal position state depending on the number of tuples that were
932 * retrieved.
933 */
934 if (forward)
935 {
936 if (portal->atEnd || count <= 0)
937 {
938 direction = NoMovementScanDirection;
939 count = 0; /* don't pass negative count to executor */
940 }
941 else
942 direction = ForwardScanDirection;
943
944 /* In the executor, zero count processes all rows */
945 if (count == FETCH_ALL)
946 count = 0;
947
948 if (portal->holdStore)
949 nprocessed = RunFromStore(portal, direction, (uint64) count, dest);
950 else
951 {
952 PushActiveSnapshot(queryDesc->snapshot);
953 ExecutorRun(queryDesc, direction, (uint64) count);
954 nprocessed = queryDesc->estate->es_processed;
956 }
957
958 if (!ScanDirectionIsNoMovement(direction))
959 {
960 if (nprocessed > 0)
961 portal->atStart = false; /* OK to go backward now */
962 if (count == 0 || nprocessed < (uint64) count)
963 portal->atEnd = true; /* we retrieved 'em all */
964 portal->portalPos += nprocessed;
965 }
966 }
967 else
968 {
971 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
972 errmsg("cursor can only scan forward"),
973 errhint("Declare it with SCROLL option to enable backward scan.")));
974
975 if (portal->atStart || count <= 0)
976 {
977 direction = NoMovementScanDirection;
978 count = 0; /* don't pass negative count to executor */
979 }
980 else
981 direction = BackwardScanDirection;
982
983 /* In the executor, zero count processes all rows */
984 if (count == FETCH_ALL)
985 count = 0;
986
987 if (portal->holdStore)
988 nprocessed = RunFromStore(portal, direction, (uint64) count, dest);
989 else
990 {
991 PushActiveSnapshot(queryDesc->snapshot);
992 ExecutorRun(queryDesc, direction, (uint64) count);
993 nprocessed = queryDesc->estate->es_processed;
995 }
996
997 if (!ScanDirectionIsNoMovement(direction))
998 {
999 if (nprocessed > 0 && portal->atEnd)
1000 {
1001 portal->atEnd = false; /* OK to go forward now */
1002 portal->portalPos++; /* adjust for endpoint case */
1003 }
1004 if (count == 0 || nprocessed < (uint64) count)
1005 {
1006 portal->atStart = true; /* we retrieved 'em all */
1007 portal->portalPos = 0;
1008 }
1009 else
1010 {
1011 portal->portalPos -= nprocessed;
1012 }
1013 }
1014 }
1015
1016 return nprocessed;
1017}
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:365
static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest)
Definition: pquery.c:1088
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:57
ScanDirection
Definition: sdir.h:25
@ NoMovementScanDirection
Definition: sdir.h:27
@ BackwardScanDirection
Definition: sdir.h:26
@ ForwardScanDirection
Definition: sdir.h:28
uint64 es_processed
Definition: execnodes.h:712

References Assert(), PortalData::atEnd, PortalData::atStart, BackwardScanDirection, CURSOR_OPT_NO_SCROLL, PortalData::cursorOptions, generate_unaccent_rules::dest, QueryDesc::dest, ereport, errcode(), errhint(), errmsg(), ERROR, EState::es_processed, QueryDesc::estate, ExecutorRun(), FETCH_ALL, ForwardScanDirection, PortalData::holdStore, NoMovementScanDirection, PopActiveSnapshot(), PortalData::portalPos, PushActiveSnapshot(), PortalData::queryDesc, RunFromStore(), ScanDirectionIsNoMovement, and QueryDesc::snapshot.

Referenced by DoPortalRunFetch(), and PortalRun().

◆ PortalRunUtility()

static void PortalRunUtility ( Portal  portal,
PlannedStmt pstmt,
bool  isTopLevel,
bool  setHoldSnapshot,
DestReceiver dest,
QueryCompletion qc 
)
static

Definition at line 1154 of file pquery.c.

1157{
1158 /*
1159 * Set snapshot if utility stmt needs one.
1160 */
1161 if (PlannedStmtRequiresSnapshot(pstmt))
1162 {
1163 Snapshot snapshot = GetTransactionSnapshot();
1164
1165 /* If told to, register the snapshot we're using and save in portal */
1166 if (setHoldSnapshot)
1167 {
1168 snapshot = RegisterSnapshot(snapshot);
1169 portal->holdSnapshot = snapshot;
1170 }
1171
1172 /*
1173 * In any case, make the snapshot active and remember it in portal.
1174 * Because the portal now references the snapshot, we must tell
1175 * snapmgr.c that the snapshot belongs to the portal's transaction
1176 * level, else we risk portalSnapshot becoming a dangling pointer.
1177 */
1178 PushActiveSnapshotWithLevel(snapshot, portal->createLevel);
1179 /* PushActiveSnapshotWithLevel might have copied the snapshot */
1181 }
1182 else
1183 portal->portalSnapshot = NULL;
1184
1185 ProcessUtility(pstmt,
1186 portal->sourceText,
1187 (portal->cplan != NULL), /* protect tree if in plancache */
1189 portal->portalParams,
1190 portal->queryEnv,
1191 dest,
1192 qc);
1193
1194 /* Some utility statements may change context on us */
1196
1197 /*
1198 * Some utility commands (e.g., VACUUM) pop the ActiveSnapshot stack from
1199 * under us, so don't complain if it's now empty. Otherwise, our snapshot
1200 * should be the top one; pop it. Note that this could be a different
1201 * snapshot from the one we made above; see EnsurePortalSnapshotExists.
1202 */
1203 if (portal->portalSnapshot != NULL && ActiveSnapshotSet())
1204 {
1207 }
1208 portal->portalSnapshot = NULL;
1209}
bool PlannedStmtRequiresSnapshot(PlannedStmt *pstmt)
Definition: pquery.c:1765
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:499
@ PROCESS_UTILITY_TOPLEVEL
Definition: utility.h:22
@ PROCESS_UTILITY_QUERY
Definition: utility.h:23

References ActiveSnapshotSet(), Assert(), PortalData::cplan, PortalData::createLevel, generate_unaccent_rules::dest, GetActiveSnapshot(), GetTransactionSnapshot(), PortalData::holdSnapshot, MemoryContextSwitchTo(), PlannedStmtRequiresSnapshot(), PopActiveSnapshot(), PortalData::portalContext, PortalData::portalParams, PortalData::portalSnapshot, PROCESS_UTILITY_QUERY, PROCESS_UTILITY_TOPLEVEL, ProcessUtility(), PushActiveSnapshotWithLevel(), PortalData::queryEnv, RegisterSnapshot(), and PortalData::sourceText.

Referenced by FillPortalStore(), and PortalRunMulti().

◆ PortalSetResultFormat()

void PortalSetResultFormat ( Portal  portal,
int  nFormats,
int16 formats 
)

Definition at line 656 of file pquery.c.

657{
658 int natts;
659 int i;
660
661 /* Do nothing if portal won't return tuples */
662 if (portal->tupDesc == NULL)
663 return;
664 natts = portal->tupDesc->natts;
665 portal->formats = (int16 *)
667 natts * sizeof(int16));
668 if (nFormats > 1)
669 {
670 /* format specified for each column */
671 if (nFormats != natts)
673 (errcode(ERRCODE_PROTOCOL_VIOLATION),
674 errmsg("bind message has %d result formats but query has %d columns",
675 nFormats, natts)));
676 memcpy(portal->formats, formats, natts * sizeof(int16));
677 }
678 else if (nFormats > 0)
679 {
680 /* single format specified, use for all columns */
681 int16 format1 = formats[0];
682
683 for (i = 0; i < natts; i++)
684 portal->formats[i] = format1;
685 }
686 else
687 {
688 /* use default format for all columns */
689 for (i = 0; i < natts; i++)
690 portal->formats[i] = 0;
691 }
692}
int16_t int16
Definition: c.h:497
int i
Definition: isn.c:77
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1256
int16 * formats
Definition: portal.h:162
TupleDesc tupDesc
Definition: portal.h:160

References ereport, errcode(), errmsg(), ERROR, PortalData::formats, i, MemoryContextAlloc(), TupleDescData::natts, PortalData::portalContext, and PortalData::tupDesc.

Referenced by exec_bind_message(), and exec_simple_query().

◆ PortalStart()

void PortalStart ( Portal  portal,
ParamListInfo  params,
int  eflags,
Snapshot  snapshot 
)

Definition at line 455 of file pquery.c.

457{
458 Portal saveActivePortal;
459 ResourceOwner saveResourceOwner;
460 MemoryContext savePortalContext;
461 MemoryContext oldContext;
462 QueryDesc *queryDesc;
463 int myeflags;
464
465 Assert(PortalIsValid(portal));
466 Assert(portal->status == PORTAL_DEFINED);
467
468 /*
469 * Set up global portal context pointers.
470 */
471 saveActivePortal = ActivePortal;
472 saveResourceOwner = CurrentResourceOwner;
473 savePortalContext = PortalContext;
474 PG_TRY();
475 {
476 ActivePortal = portal;
477 if (portal->resowner)
480
482
483 /* Must remember portal param list, if any */
484 portal->portalParams = params;
485
486 /*
487 * Determine the portal execution strategy
488 */
489 portal->strategy = ChoosePortalStrategy(portal->stmts);
490
491 /*
492 * Fire her up according to the strategy
493 */
494 switch (portal->strategy)
495 {
497
498 /* Must set snapshot before starting executor. */
499 if (snapshot)
500 PushActiveSnapshot(snapshot);
501 else
503
504 /*
505 * We could remember the snapshot in portal->portalSnapshot,
506 * but presently there seems no need to, as this code path
507 * cannot be used for non-atomic execution. Hence there can't
508 * be any commit/abort that might destroy the snapshot. Since
509 * we don't do that, there's also no need to force a
510 * non-default nesting level for the snapshot.
511 */
512
513 /*
514 * Create QueryDesc in portal's context; for the moment, set
515 * the destination to DestNone.
516 */
517 queryDesc = CreateQueryDesc(linitial_node(PlannedStmt, portal->stmts),
518 portal->cplan,
519 portal->sourceText,
523 params,
524 portal->queryEnv,
525 0);
526
527 /*
528 * If it's a scrollable cursor, executor needs to support
529 * REWIND and backwards scan, as well as whatever the caller
530 * might've asked for.
531 */
532 if (portal->cursorOptions & CURSOR_OPT_SCROLL)
533 myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
534 else
535 myeflags = eflags;
536
537 /*
538 * Prepare the plan for execution.
539 */
540 if (portal->cplan)
541 {
542 ExecutorStartCachedPlan(queryDesc, myeflags,
543 portal->plansource, 0);
544 Assert(queryDesc->planstate);
545 }
546 else
547 {
548 if (!ExecutorStart(queryDesc, myeflags))
549 elog(ERROR, "ExecutorStart() failed unexpectedly");
550 }
551
552 /*
553 * This tells PortalCleanup to shut down the executor
554 */
555 portal->queryDesc = queryDesc;
556
557 /*
558 * Remember tuple descriptor (computed by ExecutorStart)
559 */
560 portal->tupDesc = queryDesc->tupDesc;
561
562 /*
563 * Reset cursor position data to "start of query"
564 */
565 portal->atStart = true;
566 portal->atEnd = false; /* allow fetches */
567 portal->portalPos = 0;
568
570 break;
571
574
575 /*
576 * We don't start the executor until we are told to run the
577 * portal. We do need to set up the result tupdesc.
578 */
579 {
580 PlannedStmt *pstmt;
581
582 pstmt = PortalGetPrimaryStmt(portal);
583 portal->tupDesc =
585 }
586
587 /*
588 * Reset cursor position data to "start of query"
589 */
590 portal->atStart = true;
591 portal->atEnd = false; /* allow fetches */
592 portal->portalPos = 0;
593 break;
594
596
597 /*
598 * We don't set snapshot here, because PortalRunUtility will
599 * take care of it if needed.
600 */
601 {
602 PlannedStmt *pstmt = PortalGetPrimaryStmt(portal);
603
604 Assert(pstmt->commandType == CMD_UTILITY);
606 }
607
608 /*
609 * Reset cursor position data to "start of query"
610 */
611 portal->atStart = true;
612 portal->atEnd = false; /* allow fetches */
613 portal->portalPos = 0;
614 break;
615
617 /* Need do nothing now */
618 portal->tupDesc = NULL;
619 break;
620 }
621 }
622 PG_CATCH();
623 {
624 /* Uncaught error while executing portal: mark it dead */
625 MarkPortalFailed(portal);
626
627 /* Restore global vars and propagate error */
628 ActivePortal = saveActivePortal;
629 CurrentResourceOwner = saveResourceOwner;
630 PortalContext = savePortalContext;
631
632 PG_RE_THROW();
633 }
634 PG_END_TRY();
635
636 MemoryContextSwitchTo(oldContext);
637
638 ActivePortal = saveActivePortal;
639 CurrentResourceOwner = saveResourceOwner;
640 PortalContext = savePortalContext;
641
642 portal->status = PORTAL_READY;
643}
bool ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:128
void ExecutorStartCachedPlan(QueryDesc *queryDesc, int eflags, CachedPlanSource *plansource, int query_index)
Definition: execMain.c:295
TupleDesc ExecCleanTypeFromTL(List *targetList)
Definition: execTuples.c:2139
#define EXEC_FLAG_BACKWARD
Definition: executor.h:69
#define EXEC_FLAG_REWIND
Definition: executor.h:68
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3376
@ PORTAL_DEFINED
Definition: portal.h:106
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:231
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:72
#define InvalidSnapshot
Definition: snapshot.h:119
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:2084

References ActivePortal, Assert(), PortalData::atEnd, PortalData::atStart, ChoosePortalStrategy(), CMD_UTILITY, PlannedStmt::commandType, PortalData::cplan, CreateQueryDesc(), CurrentResourceOwner, CURSOR_OPT_SCROLL, PortalData::cursorOptions, elog, ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_REWIND, ExecCleanTypeFromTL(), ExecutorStart(), ExecutorStartCachedPlan(), GetActiveSnapshot(), GetTransactionSnapshot(), InvalidSnapshot, linitial_node, MarkPortalFailed(), MemoryContextSwitchTo(), None_Receiver, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PortalData::plansource, QueryDesc::planstate, PlannedStmt::planTree, PopActiveSnapshot(), PORTAL_DEFINED, PORTAL_MULTI_QUERY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_READY, PORTAL_UTIL_SELECT, PortalContext, PortalData::portalContext, PortalGetPrimaryStmt(), PortalIsValid, PortalData::portalParams, PortalData::portalPos, PushActiveSnapshot(), PortalData::queryDesc, PortalData::queryEnv, PortalData::resowner, PortalData::sourceText, PortalData::status, PortalData::stmts, PortalData::strategy, Plan::targetlist, QueryDesc::tupDesc, PortalData::tupDesc, PlannedStmt::utilityStmt, and UtilityTupleDescriptor().

Referenced by exec_bind_message(), exec_simple_query(), ExecuteQuery(), PerformCursorOpen(), and SPI_cursor_open_internal().

◆ ProcessQuery()

static void ProcessQuery ( PlannedStmt plan,
CachedPlan cplan,
CachedPlanSource plansource,
int  query_index,
const char *  sourceText,
ParamListInfo  params,
QueryEnvironment queryEnv,
DestReceiver dest,
QueryCompletion qc 
)
static

Definition at line 146 of file pquery.c.

155{
156 QueryDesc *queryDesc;
157
158 /*
159 * Create the QueryDesc object
160 */
161 queryDesc = CreateQueryDesc(plan, cplan, sourceText,
163 dest, params, queryEnv, 0);
164
165 /*
166 * Prepare the plan for execution
167 */
168 if (queryDesc->cplan)
169 {
170 ExecutorStartCachedPlan(queryDesc, 0, plansource, query_index);
171 Assert(queryDesc->planstate);
172 }
173 else
174 {
175 if (!ExecutorStart(queryDesc, 0))
176 elog(ERROR, "ExecutorStart() failed unexpectedly");
177 }
178
179 /*
180 * Run the plan to completion.
181 */
182 ExecutorRun(queryDesc, ForwardScanDirection, 0);
183
184 /*
185 * Build command completion status data, if caller wants one.
186 */
187 if (qc)
188 {
189 switch (queryDesc->operation)
190 {
191 case CMD_SELECT:
192 SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
193 break;
194 case CMD_INSERT:
195 SetQueryCompletion(qc, CMDTAG_INSERT, queryDesc->estate->es_processed);
196 break;
197 case CMD_UPDATE:
198 SetQueryCompletion(qc, CMDTAG_UPDATE, queryDesc->estate->es_processed);
199 break;
200 case CMD_DELETE:
201 SetQueryCompletion(qc, CMDTAG_DELETE, queryDesc->estate->es_processed);
202 break;
203 case CMD_MERGE:
204 SetQueryCompletion(qc, CMDTAG_MERGE, queryDesc->estate->es_processed);
205 break;
206 default:
207 SetQueryCompletion(qc, CMDTAG_UNKNOWN, queryDesc->estate->es_processed);
208 break;
209 }
210 }
211
212 /*
213 * Now, we close down all the scans and free allocated resources.
214 */
215 ExecutorFinish(queryDesc);
216 ExecutorEnd(queryDesc);
217
218 FreeQueryDesc(queryDesc);
219}
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
Definition: cmdtag.h:37
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:538
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:475
@ CMD_MERGE
Definition: nodes.h:275
@ CMD_INSERT
Definition: nodes.h:273
@ CMD_DELETE
Definition: nodes.h:274
@ CMD_UPDATE
Definition: nodes.h:272
#define plan(x)
Definition: pg_regress.c:161
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:112

References Assert(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_SELECT, CMD_UPDATE, QueryDesc::cplan, CreateQueryDesc(), generate_unaccent_rules::dest, elog, ERROR, EState::es_processed, QueryDesc::estate, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), ExecutorStartCachedPlan(), ForwardScanDirection, FreeQueryDesc(), GetActiveSnapshot(), InvalidSnapshot, QueryDesc::operation, plan, QueryDesc::planstate, and SetQueryCompletion().

Referenced by PortalRunMulti().

◆ RunFromStore()

static uint64 RunFromStore ( Portal  portal,
ScanDirection  direction,
uint64  count,
DestReceiver dest 
)
static

Definition at line 1088 of file pquery.c.

1090{
1091 uint64 current_tuple_count = 0;
1092 TupleTableSlot *slot;
1093
1095
1096 dest->rStartup(dest, CMD_SELECT, portal->tupDesc);
1097
1098 if (ScanDirectionIsNoMovement(direction))
1099 {
1100 /* do nothing except start/stop the destination */
1101 }
1102 else
1103 {
1104 bool forward = ScanDirectionIsForward(direction);
1105
1106 for (;;)
1107 {
1108 MemoryContext oldcontext;
1109 bool ok;
1110
1111 oldcontext = MemoryContextSwitchTo(portal->holdContext);
1112
1113 ok = tuplestore_gettupleslot(portal->holdStore, forward, false,
1114 slot);
1115
1116 MemoryContextSwitchTo(oldcontext);
1117
1118 if (!ok)
1119 break;
1120
1121 /*
1122 * If we are not able to send the tuple, we assume the destination
1123 * has closed and no more tuples can be sent. If that's the case,
1124 * end the loop.
1125 */
1126 if (!dest->receiveSlot(slot, dest))
1127 break;
1128
1129 ExecClearTuple(slot);
1130
1131 /*
1132 * check our tuple count.. if we've processed the proper number
1133 * then quit, else loop again and process more tuples. Zero count
1134 * means no limit.
1135 */
1136 current_tuple_count++;
1137 if (count && count == current_tuple_count)
1138 break;
1139 }
1140 }
1141
1142 dest->rShutdown(dest);
1143
1145
1146 return current_tuple_count;
1147}
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1427
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86
#define ScanDirectionIsForward(direction)
Definition: sdir.h:64
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1130
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:458

References CMD_SELECT, generate_unaccent_rules::dest, ExecClearTuple(), ExecDropSingleTupleTableSlot(), PortalData::holdContext, PortalData::holdStore, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), ScanDirectionIsForward, ScanDirectionIsNoMovement, TTSOpsMinimalTuple, PortalData::tupDesc, and tuplestore_gettupleslot().

Referenced by PortalRunSelect().

Variable Documentation

◆ ActivePortal