PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pquery.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/xact.h"
#include "commands/prepare.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, const char *sourceText, ParamListInfo params, DestReceiver *dest, char *completionTag)
 
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, char *completionTag)
 
static void PortalRunMulti (Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
 
static uint64 DoPortalRunFetch (Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
 
static void DoPortalRewind (Portal portal)
 
QueryDescCreateQueryDesc (PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, 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, bool run_once, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
 
uint64 PortalRunFetch (Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
 

Variables

Portal ActivePortal = NULL
 

Function Documentation

PortalStrategy ChoosePortalStrategy ( List stmts)

Definition at line 218 of file pquery.c.

References PlannedStmt::canSetTag, Query::canSetTag, CMD_SELECT, CMD_UTILITY, PlannedStmt::commandType, Query::commandType, elog, ERROR, PlannedStmt::hasModifyingCTE, Query::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, UtilityReturnsTuples(), PlannedStmt::utilityStmt, and Query::utilityStmt.

Referenced by PlanCacheComputeResultDesc(), and PortalStart().

219 {
220  int nSetTag;
221  ListCell *lc;
222 
223  /*
224  * PORTAL_ONE_SELECT and PORTAL_UTIL_SELECT need only consider the
225  * single-statement case, since there are no rewrite rules that can add
226  * auxiliary queries to a SELECT or a utility command. PORTAL_ONE_MOD_WITH
227  * likewise allows only one top-level statement.
228  */
229  if (list_length(stmts) == 1)
230  {
231  Node *stmt = (Node *) linitial(stmts);
232 
233  if (IsA(stmt, Query))
234  {
235  Query *query = (Query *) stmt;
236 
237  if (query->canSetTag)
238  {
239  if (query->commandType == CMD_SELECT)
240  {
241  if (query->hasModifyingCTE)
242  return PORTAL_ONE_MOD_WITH;
243  else
244  return PORTAL_ONE_SELECT;
245  }
246  if (query->commandType == CMD_UTILITY)
247  {
248  if (UtilityReturnsTuples(query->utilityStmt))
249  return PORTAL_UTIL_SELECT;
250  /* it can't be ONE_RETURNING, so give up */
251  return PORTAL_MULTI_QUERY;
252  }
253  }
254  }
255  else if (IsA(stmt, PlannedStmt))
256  {
257  PlannedStmt *pstmt = (PlannedStmt *) stmt;
258 
259  if (pstmt->canSetTag)
260  {
261  if (pstmt->commandType == CMD_SELECT)
262  {
263  if (pstmt->hasModifyingCTE)
264  return PORTAL_ONE_MOD_WITH;
265  else
266  return PORTAL_ONE_SELECT;
267  }
268  if (pstmt->commandType == CMD_UTILITY)
269  {
270  if (UtilityReturnsTuples(pstmt->utilityStmt))
271  return PORTAL_UTIL_SELECT;
272  /* it can't be ONE_RETURNING, so give up */
273  return PORTAL_MULTI_QUERY;
274  }
275  }
276  }
277  else
278  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
279  }
280 
281  /*
282  * PORTAL_ONE_RETURNING has to allow auxiliary queries added by rewrite.
283  * Choose PORTAL_ONE_RETURNING if there is exactly one canSetTag query and
284  * it has a RETURNING list.
285  */
286  nSetTag = 0;
287  foreach(lc, stmts)
288  {
289  Node *stmt = (Node *) lfirst(lc);
290 
291  if (IsA(stmt, Query))
292  {
293  Query *query = (Query *) stmt;
294 
295  if (query->canSetTag)
296  {
297  if (++nSetTag > 1)
298  return PORTAL_MULTI_QUERY; /* no need to look further */
299  if (query->commandType == CMD_UTILITY ||
300  query->returningList == NIL)
301  return PORTAL_MULTI_QUERY; /* no need to look further */
302  }
303  }
304  else if (IsA(stmt, PlannedStmt))
305  {
306  PlannedStmt *pstmt = (PlannedStmt *) stmt;
307 
308  if (pstmt->canSetTag)
309  {
310  if (++nSetTag > 1)
311  return PORTAL_MULTI_QUERY; /* no need to look further */
312  if (pstmt->commandType == CMD_UTILITY ||
313  !pstmt->hasReturning)
314  return PORTAL_MULTI_QUERY; /* no need to look further */
315  }
316  }
317  else
318  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
319  }
320  if (nSetTag == 1)
321  return PORTAL_ONE_RETURNING;
322 
323  /* Else, it's the general case... */
324  return PORTAL_MULTI_QUERY;
325 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
Definition: nodes.h:504
Node * utilityStmt
Definition: parsenodes.h:111
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
bool hasReturning
Definition: plannodes.h:49
Node * utilityStmt
Definition: plannodes.h:83
bool UtilityReturnsTuples(Node *parsetree)
Definition: utility.c:1703
List * returningList
Definition: parsenodes.h:135
bool canSetTag
Definition: plannodes.h:53
CmdType commandType
Definition: plannodes.h:45
CmdType commandType
Definition: parsenodes.h:103
#define lfirst(lc)
Definition: pg_list.h:106
bool hasModifyingCTE
Definition: plannodes.h:51
bool canSetTag
Definition: parsenodes.h:109
static int list_length(const List *l)
Definition: pg_list.h:89
#define nodeTag(nodeptr)
Definition: nodes.h:509
bool hasModifyingCTE
Definition: parsenodes.h:122
#define elog
Definition: elog.h:219
QueryDesc* CreateQueryDesc ( PlannedStmt plannedstmt,
const char *  sourceText,
Snapshot  snapshot,
Snapshot  crosscheck_snapshot,
DestReceiver dest,
ParamListInfo  params,
int  instrument_options 
)

Definition at line 66 of file pquery.c.

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

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

73 {
74  QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
75 
76  qd->operation = plannedstmt->commandType; /* operation */
77  qd->plannedstmt = plannedstmt; /* plan */
78  qd->sourceText = sourceText; /* query text */
79  qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */
80  /* RI check snapshot */
81  qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot);
82  qd->dest = dest; /* output dest */
83  qd->params = params; /* parameter values passed into query */
84  qd->instrument_options = instrument_options; /* instrumentation
85  * wanted? */
86 
87  /* null these fields until set by ExecutorStart */
88  qd->tupDesc = NULL;
89  qd->estate = NULL;
90  qd->planstate = NULL;
91  qd->totaltime = NULL;
92 
93  /* not yet executed */
94  qd->already_executed = false;
95 
96  return qd;
97 }
EState * estate
Definition: execdesc.h:47
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:858
Snapshot snapshot
Definition: execdesc.h:39
int instrument_options
Definition: execdesc.h:43
PlanState * planstate
Definition: execdesc.h:48
ParamListInfo params
Definition: execdesc.h:42
TupleDesc tupDesc
Definition: execdesc.h:46
CmdType operation
Definition: execdesc.h:36
CmdType commandType
Definition: plannodes.h:45
bool already_executed
Definition: execdesc.h:51
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
struct Instrumentation * totaltime
Definition: execdesc.h:54
#define NULL
Definition: c.h:229
const char * sourceText
Definition: execdesc.h:38
DestReceiver * dest
Definition: execdesc.h:41
void * palloc(Size size)
Definition: mcxt.c:849
PlannedStmt * plannedstmt
Definition: execdesc.h:37
static void DoPortalRewind ( Portal  portal)
static

Definition at line 1675 of file pquery.c.

References PortalData::atEnd, PortalData::atStart, ExecutorRewind(), PortalData::holdContext, PortalData::holdStore, MemoryContextSwitchTo(), PopActiveSnapshot(), PortalGetQueryDesc, PortalData::portalPos, PushActiveSnapshot(), QueryDesc::snapshot, and tuplestore_rescan().

Referenced by DoPortalRunFetch().

1676 {
1677  QueryDesc *queryDesc;
1678 
1679  /* Rewind holdStore, if we have one */
1680  if (portal->holdStore)
1681  {
1682  MemoryContext oldcontext;
1683 
1684  oldcontext = MemoryContextSwitchTo(portal->holdContext);
1685  tuplestore_rescan(portal->holdStore);
1686  MemoryContextSwitchTo(oldcontext);
1687  }
1688 
1689  /* Rewind executor, if active */
1690  queryDesc = PortalGetQueryDesc(portal);
1691  if (queryDesc)
1692  {
1693  PushActiveSnapshot(queryDesc->snapshot);
1694  ExecutorRewind(queryDesc);
1696  }
1697 
1698  portal->atStart = true;
1699  portal->atEnd = false;
1700  portal->portalPos = 0;
1701 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1216
bool atEnd
Definition: portal.h:186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext holdContext
Definition: portal.h:164
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
Snapshot snapshot
Definition: execdesc.h:39
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
void ExecutorRewind(QueryDesc *queryDesc)
Definition: execMain.c:519
#define PortalGetQueryDesc(portal)
Definition: portal.h:203
bool atStart
Definition: portal.h:185
Tuplestorestate * holdStore
Definition: portal.h:163
uint64 portalPos
Definition: portal.h:187
static uint64 DoPortalRunFetch ( Portal  portal,
FetchDirection  fdirection,
long  count,
DestReceiver dest 
)
static

Definition at line 1490 of file pquery.c.

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

Referenced by PortalRunFetch().

1494 {
1495  bool forward;
1496 
1497  Assert(portal->strategy == PORTAL_ONE_SELECT ||
1498  portal->strategy == PORTAL_ONE_RETURNING ||
1499  portal->strategy == PORTAL_ONE_MOD_WITH ||
1500  portal->strategy == PORTAL_UTIL_SELECT);
1501 
1502  switch (fdirection)
1503  {
1504  case FETCH_FORWARD:
1505  if (count < 0)
1506  {
1507  fdirection = FETCH_BACKWARD;
1508  count = -count;
1509  }
1510  /* fall out of switch to share code with FETCH_BACKWARD */
1511  break;
1512  case FETCH_BACKWARD:
1513  if (count < 0)
1514  {
1515  fdirection = FETCH_FORWARD;
1516  count = -count;
1517  }
1518  /* fall out of switch to share code with FETCH_FORWARD */
1519  break;
1520  case FETCH_ABSOLUTE:
1521  if (count > 0)
1522  {
1523  /*
1524  * Definition: Rewind to start, advance count-1 rows, return
1525  * next row (if any).
1526  *
1527  * In practice, if the goal is less than halfway back to the
1528  * start, it's better to scan from where we are.
1529  *
1530  * Also, if current portalPos is outside the range of "long",
1531  * do it the hard way to avoid possible overflow of the count
1532  * argument to PortalRunSelect. We must exclude exactly
1533  * LONG_MAX, as well, lest the count look like FETCH_ALL.
1534  *
1535  * In any case, we arrange to fetch the target row going
1536  * forwards.
1537  */
1538  if ((uint64) (count - 1) <= portal->portalPos / 2 ||
1539  portal->portalPos >= (uint64) LONG_MAX)
1540  {
1541  DoPortalRewind(portal);
1542  if (count > 1)
1543  PortalRunSelect(portal, true, count - 1,
1544  None_Receiver);
1545  }
1546  else
1547  {
1548  long pos = (long) portal->portalPos;
1549 
1550  if (portal->atEnd)
1551  pos++; /* need one extra fetch if off end */
1552  if (count <= pos)
1553  PortalRunSelect(portal, false, pos - count + 1,
1554  None_Receiver);
1555  else if (count > pos + 1)
1556  PortalRunSelect(portal, true, count - pos - 1,
1557  None_Receiver);
1558  }
1559  return PortalRunSelect(portal, true, 1L, dest);
1560  }
1561  else if (count < 0)
1562  {
1563  /*
1564  * Definition: Advance to end, back up abs(count)-1 rows,
1565  * return prior row (if any). We could optimize this if we
1566  * knew in advance where the end was, but typically we won't.
1567  * (Is it worth considering case where count > half of size of
1568  * query? We could rewind once we know the size ...)
1569  */
1570  PortalRunSelect(portal, true, FETCH_ALL, None_Receiver);
1571  if (count < -1)
1572  PortalRunSelect(portal, false, -count - 1, None_Receiver);
1573  return PortalRunSelect(portal, false, 1L, dest);
1574  }
1575  else
1576  {
1577  /* count == 0 */
1578  /* Rewind to start, return zero rows */
1579  DoPortalRewind(portal);
1580  return PortalRunSelect(portal, true, 0L, dest);
1581  }
1582  break;
1583  case FETCH_RELATIVE:
1584  if (count > 0)
1585  {
1586  /*
1587  * Definition: advance count-1 rows, return next row (if any).
1588  */
1589  if (count > 1)
1590  PortalRunSelect(portal, true, count - 1, None_Receiver);
1591  return PortalRunSelect(portal, true, 1L, dest);
1592  }
1593  else if (count < 0)
1594  {
1595  /*
1596  * Definition: back up abs(count)-1 rows, return prior row (if
1597  * any).
1598  */
1599  if (count < -1)
1600  PortalRunSelect(portal, false, -count - 1, None_Receiver);
1601  return PortalRunSelect(portal, false, 1L, dest);
1602  }
1603  else
1604  {
1605  /* count == 0 */
1606  /* Same as FETCH FORWARD 0, so fall out of switch */
1607  fdirection = FETCH_FORWARD;
1608  }
1609  break;
1610  default:
1611  elog(ERROR, "bogus direction");
1612  break;
1613  }
1614 
1615  /*
1616  * Get here with fdirection == FETCH_FORWARD or FETCH_BACKWARD, and count
1617  * >= 0.
1618  */
1619  forward = (fdirection == FETCH_FORWARD);
1620 
1621  /*
1622  * Zero count means to re-fetch the current row, if any (per SQL)
1623  */
1624  if (count == 0)
1625  {
1626  bool on_row;
1627 
1628  /* Are we sitting on a row? */
1629  on_row = (!portal->atStart && !portal->atEnd);
1630 
1631  if (dest->mydest == DestNone)
1632  {
1633  /* MOVE 0 returns 0/1 based on if FETCH 0 would return a row */
1634  return on_row ? 1 : 0;
1635  }
1636  else
1637  {
1638  /*
1639  * If we are sitting on a row, back up one so we can re-fetch it.
1640  * If we are not sitting on a row, we still have to start up and
1641  * shut down the executor so that the destination is initialized
1642  * and shut down correctly; so keep going. To PortalRunSelect,
1643  * count == 0 means we will retrieve no row.
1644  */
1645  if (on_row)
1646  {
1647  PortalRunSelect(portal, false, 1L, None_Receiver);
1648  /* Set up to fetch one row forward */
1649  count = 1;
1650  forward = true;
1651  }
1652  }
1653  }
1654 
1655  /*
1656  * Optimize MOVE BACKWARD ALL into a Rewind.
1657  */
1658  if (!forward && count == FETCH_ALL && dest->mydest == DestNone)
1659  {
1660  uint64 result = portal->portalPos;
1661 
1662  if (result > 0 && !portal->atEnd)
1663  result--;
1664  DoPortalRewind(portal);
1665  return result;
1666  }
1667 
1668  return PortalRunSelect(portal, forward, count, dest);
1669 }
bool atEnd
Definition: portal.h:186
CommandDest mydest
Definition: dest.h:128
return result
Definition: formatting.c:1618
DestReceiver * None_Receiver
Definition: dest.c:91
static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest)
Definition: pquery.c:871
#define ERROR
Definition: elog.h:43
Definition: dest.h:88
PortalStrategy strategy
Definition: portal.h:142
#define Assert(condition)
Definition: c.h:675
bool atStart
Definition: portal.h:185
#define elog
Definition: elog.h:219
static void DoPortalRewind(Portal portal)
Definition: pquery.c:1675
uint64 portalPos
Definition: portal.h:187
#define FETCH_ALL
Definition: parsenodes.h:2614
List* FetchPortalTargetList ( Portal  portal)

Definition at line 335 of file pquery.c.

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

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

336 {
337  /* no point in looking if we determined it doesn't return tuples */
338  if (portal->strategy == PORTAL_MULTI_QUERY)
339  return NIL;
340  /* get the primary statement and find out what it returns */
342 }
#define NIL
Definition: pg_list.h:69
Definition: nodes.h:504
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
Definition: portalmem.c:150
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:357
PortalStrategy strategy
Definition: portal.h:142
List* FetchStatementTargetList ( Node stmt)

Definition at line 357 of file pquery.c.

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

Referenced by CachedPlanGetTargetList(), and FetchPortalTargetList().

358 {
359  if (stmt == NULL)
360  return NIL;
361  if (IsA(stmt, Query))
362  {
363  Query *query = (Query *) stmt;
364 
365  if (query->commandType == CMD_UTILITY)
366  {
367  /* transfer attention to utility statement */
368  stmt = query->utilityStmt;
369  }
370  else
371  {
372  if (query->commandType == CMD_SELECT)
373  return query->targetList;
374  if (query->returningList)
375  return query->returningList;
376  return NIL;
377  }
378  }
379  if (IsA(stmt, PlannedStmt))
380  {
381  PlannedStmt *pstmt = (PlannedStmt *) stmt;
382 
383  if (pstmt->commandType == CMD_UTILITY)
384  {
385  /* transfer attention to utility statement */
386  stmt = pstmt->utilityStmt;
387  }
388  else
389  {
390  if (pstmt->commandType == CMD_SELECT)
391  return pstmt->planTree->targetlist;
392  if (pstmt->hasReturning)
393  return pstmt->planTree->targetlist;
394  return NIL;
395  }
396  }
397  if (IsA(stmt, FetchStmt))
398  {
399  FetchStmt *fstmt = (FetchStmt *) stmt;
400  Portal subportal;
401 
402  Assert(!fstmt->ismove);
403  subportal = GetPortalByName(fstmt->portalname);
404  Assert(PortalIsValid(subportal));
405  return FetchPortalTargetList(subportal);
406  }
407  if (IsA(stmt, ExecuteStmt))
408  {
409  ExecuteStmt *estmt = (ExecuteStmt *) stmt;
410  PreparedStatement *entry;
411 
412  entry = FetchPreparedStatement(estmt->name, true);
413  return FetchPreparedStatementTargetList(entry);
414  }
415  return NIL;
416 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
Node * utilityStmt
Definition: parsenodes.h:111
struct Plan * planTree
Definition: plannodes.h:61
List * targetList
Definition: parsenodes.h:131
bool hasReturning
Definition: plannodes.h:49
Node * utilityStmt
Definition: plannodes.h:83
List * returningList
Definition: parsenodes.h:135
char * portalname
Definition: parsenodes.h:2621
#define PortalIsValid(p)
Definition: portal.h:198
bool ismove
Definition: parsenodes.h:2622
CmdType commandType
Definition: plannodes.h:45
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:549
CmdType commandType
Definition: parsenodes.h:103
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
List * targetlist
Definition: plannodes.h:132
char * name
Definition: parsenodes.h:3240
List * FetchPortalTargetList(Portal portal)
Definition: pquery.c:335
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:494
static void FillPortalStore ( Portal  portal,
bool  isTopLevel 
)
static

Definition at line 1004 of file pquery.c.

References castNode, PortalData::commandTag, COMPLETION_TAG_BUFSIZE, CreateDestReceiver(), DestTuplestore, elog, ERROR, PortalData::holdContext, PortalData::holdStore, linitial, None_Receiver, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_UTIL_SELECT, PortalCreateHoldStore(), PortalRunMulti(), PortalRunUtility(), pstrdup(), _DestReceiver::rDestroy, SetTuplestoreDestReceiverParams(), PortalData::stmts, and PortalData::strategy.

Referenced by PortalRun(), and PortalRunFetch().

1005 {
1006  DestReceiver *treceiver;
1007  char completionTag[COMPLETION_TAG_BUFSIZE];
1008 
1009  PortalCreateHoldStore(portal);
1010  treceiver = CreateDestReceiver(DestTuplestore);
1012  portal->holdStore,
1013  portal->holdContext,
1014  false);
1015 
1016  completionTag[0] = '\0';
1017 
1018  switch (portal->strategy)
1019  {
1020  case PORTAL_ONE_RETURNING:
1021  case PORTAL_ONE_MOD_WITH:
1022 
1023  /*
1024  * Run the portal to completion just as for the default
1025  * MULTI_QUERY case, but send the primary query's output to the
1026  * tuplestore. Auxiliary query outputs are discarded. Set the
1027  * portal's holdSnapshot to the snapshot used (or a copy of it).
1028  */
1029  PortalRunMulti(portal, isTopLevel, true,
1030  treceiver, None_Receiver, completionTag);
1031  break;
1032 
1033  case PORTAL_UTIL_SELECT:
1034  PortalRunUtility(portal, castNode(PlannedStmt, linitial(portal->stmts)),
1035  isTopLevel, true, treceiver, completionTag);
1036  break;
1037 
1038  default:
1039  elog(ERROR, "unsupported portal strategy: %d",
1040  (int) portal->strategy);
1041  break;
1042  }
1043 
1044  /* Override default completion tag with actual command result */
1045  if (completionTag[0] != '\0')
1046  portal->commandTag = pstrdup(completionTag);
1047 
1048  (*treceiver->rDestroy) (treceiver);
1049 }
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
#define castNode(_type_, nodeptr)
Definition: nodes.h:573
char * pstrdup(const char *in)
Definition: mcxt.c:1077
void SetTuplestoreDestReceiverParams(DestReceiver *self, Tuplestorestate *tStore, MemoryContext tContext, bool detoast)
MemoryContext holdContext
Definition: portal.h:164
List * stmts
Definition: portal.h:136
DestReceiver * None_Receiver
Definition: dest.c:91
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
const char * commandTag
Definition: portal.h:135
static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, char *completionTag)
Definition: pquery.c:1130
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
PortalStrategy strategy
Definition: portal.h:142
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
static void PortalRunMulti(Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
Definition: pquery.c:1200
void PortalCreateHoldStore(Portal portal)
Definition: portalmem.c:324
Tuplestorestate * holdStore
Definition: portal.h:163
#define elog
Definition: elog.h:219
void FreeQueryDesc ( QueryDesc qdesc)

Definition at line 103 of file pquery.c.

References Assert, QueryDesc::crosscheck_snapshot, QueryDesc::estate, NULL, 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().

104 {
105  /* Can't be a live query */
106  Assert(qdesc->estate == NULL);
107 
108  /* forget our snapshots */
111 
112  /* Only the QueryDesc itself need be freed */
113  pfree(qdesc);
114 }
EState * estate
Definition: execdesc.h:47
Snapshot snapshot
Definition: execdesc.h:39
void pfree(void *pointer)
Definition: mcxt.c:950
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:900
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool PortalRun ( Portal  portal,
long  count,
bool  isTopLevel,
bool  run_once,
DestReceiver dest,
DestReceiver altdest,
char *  completionTag 
)

Definition at line 685 of file pquery.c.

References ActivePortal, Assert, AssertArg, PortalData::atEnd, PortalData::commandTag, COMPLETION_TAG_BUFSIZE, CurrentMemoryContext, CurrentResourceOwner, DEBUG3, elog, ERROR, FillPortalStore(), PortalData::holdStore, log_executor_stats, MarkPortalActive(), MarkPortalDone(), MarkPortalFailed(), MemoryContextSwitchTo(), 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, PortalGetHeapMemory, PortalIsValid, PortalRunMulti(), PortalRunSelect(), ResetUsage(), PortalData::resowner, result, PortalData::run_once, ShowUsage(), snprintf(), PortalData::status, PortalData::strategy, TopTransactionContext, TopTransactionResourceOwner, and UINT64_FORMAT.

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

688 {
689  bool result;
690  uint64 nprocessed;
691  ResourceOwner saveTopTransactionResourceOwner;
692  MemoryContext saveTopTransactionContext;
693  Portal saveActivePortal;
694  ResourceOwner saveResourceOwner;
695  MemoryContext savePortalContext;
696  MemoryContext saveMemoryContext;
697 
698  AssertArg(PortalIsValid(portal));
699 
700  TRACE_POSTGRESQL_QUERY_EXECUTE_START();
701 
702  /* Initialize completion tag to empty string */
703  if (completionTag)
704  completionTag[0] = '\0';
705 
707  {
708  elog(DEBUG3, "PortalRun");
709  /* PORTAL_MULTI_QUERY logs its own stats per query */
710  ResetUsage();
711  }
712 
713  /*
714  * Check for improper portal use, and mark portal active.
715  */
716  MarkPortalActive(portal);
717 
718  /* Set run_once flag. Shouldn't be clear if previously set. */
719  Assert(!portal->run_once || run_once);
720  portal->run_once = run_once;
721 
722  /*
723  * Set up global portal context pointers.
724  *
725  * We have to play a special game here to support utility commands like
726  * VACUUM and CLUSTER, which internally start and commit transactions.
727  * When we are called to execute such a command, CurrentResourceOwner will
728  * be pointing to the TopTransactionResourceOwner --- which will be
729  * destroyed and replaced in the course of the internal commit and
730  * restart. So we need to be prepared to restore it as pointing to the
731  * exit-time TopTransactionResourceOwner. (Ain't that ugly? This idea of
732  * internally starting whole new transactions is not good.)
733  * CurrentMemoryContext has a similar problem, but the other pointers we
734  * save here will be NULL or pointing to longer-lived objects.
735  */
736  saveTopTransactionResourceOwner = TopTransactionResourceOwner;
737  saveTopTransactionContext = TopTransactionContext;
738  saveActivePortal = ActivePortal;
739  saveResourceOwner = CurrentResourceOwner;
740  savePortalContext = PortalContext;
741  saveMemoryContext = CurrentMemoryContext;
742  PG_TRY();
743  {
744  ActivePortal = portal;
745  if (portal->resowner)
746  CurrentResourceOwner = portal->resowner;
748 
750 
751  switch (portal->strategy)
752  {
753  case PORTAL_ONE_SELECT:
755  case PORTAL_ONE_MOD_WITH:
756  case PORTAL_UTIL_SELECT:
757 
758  /*
759  * If we have not yet run the command, do so, storing its
760  * results in the portal's tuplestore. But we don't do that
761  * for the PORTAL_ONE_SELECT case.
762  */
763  if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
764  FillPortalStore(portal, isTopLevel);
765 
766  /*
767  * Now fetch desired portion of results.
768  */
769  nprocessed = PortalRunSelect(portal, true, count, dest);
770 
771  /*
772  * If the portal result contains a command tag and the caller
773  * gave us a pointer to store it, copy it. Patch the "SELECT"
774  * tag to also provide the rowcount.
775  */
776  if (completionTag && portal->commandTag)
777  {
778  if (strcmp(portal->commandTag, "SELECT") == 0)
779  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
780  "SELECT " UINT64_FORMAT, nprocessed);
781  else
782  strcpy(completionTag, portal->commandTag);
783  }
784 
785  /* Mark portal not active */
786  portal->status = PORTAL_READY;
787 
788  /*
789  * Since it's a forward fetch, say DONE iff atEnd is now true.
790  */
791  result = portal->atEnd;
792  break;
793 
794  case PORTAL_MULTI_QUERY:
795  PortalRunMulti(portal, isTopLevel, false,
796  dest, altdest, completionTag);
797 
798  /* Prevent portal's commands from being re-executed */
799  MarkPortalDone(portal);
800 
801  /* Always complete at end of RunMulti */
802  result = true;
803  break;
804 
805  default:
806  elog(ERROR, "unrecognized portal strategy: %d",
807  (int) portal->strategy);
808  result = false; /* keep compiler quiet */
809  break;
810  }
811  }
812  PG_CATCH();
813  {
814  /* Uncaught error while executing portal: mark it dead */
815  MarkPortalFailed(portal);
816 
817  /* Restore global vars and propagate error */
818  if (saveMemoryContext == saveTopTransactionContext)
820  else
821  MemoryContextSwitchTo(saveMemoryContext);
822  ActivePortal = saveActivePortal;
823  if (saveResourceOwner == saveTopTransactionResourceOwner)
825  else
826  CurrentResourceOwner = saveResourceOwner;
827  PortalContext = savePortalContext;
828 
829  PG_RE_THROW();
830  }
831  PG_END_TRY();
832 
833  if (saveMemoryContext == saveTopTransactionContext)
835  else
836  MemoryContextSwitchTo(saveMemoryContext);
837  ActivePortal = saveActivePortal;
838  if (saveResourceOwner == saveTopTransactionResourceOwner)
840  else
841  CurrentResourceOwner = saveResourceOwner;
842  PortalContext = savePortalContext;
843 
845  ShowUsage("EXECUTOR STATISTICS");
846 
847  TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
848 
849  return result;
850 }
bool atEnd
Definition: portal.h:186
MemoryContext TopTransactionContext
Definition: mcxt.c:48
#define DEBUG3
Definition: elog.h:23
Portal ActivePortal
Definition: pquery.c:35
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:140
void ShowUsage(const char *title)
Definition: postgres.c:4388
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void MarkPortalActive(Portal portal)
Definition: portalmem.c:388
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1618
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest)
Definition: pquery.c:871
bool run_once
Definition: portal.h:144
MemoryContext PortalContext
Definition: mcxt.c:52
void ResetUsage(void)
Definition: postgres.c:4381
#define ERROR
Definition: elog.h:43
static void FillPortalStore(Portal portal, bool isTopLevel)
Definition: pquery.c:1004
const char * commandTag
Definition: portal.h:135
void MarkPortalDone(Portal portal)
Definition: portalmem.c:407
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
PortalStrategy strategy
Definition: portal.h:142
#define AssertArg(condition)
Definition: c.h:677
#define PortalIsValid(p)
Definition: portal.h:198
#define PG_CATCH()
Definition: elog.h:293
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
#define Assert(condition)
Definition: c.h:675
static void PortalRunMulti(Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
Definition: pquery.c:1200
#define PortalGetHeapMemory(portal)
Definition: portal.h:204
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:435
PortalStatus status
Definition: portal.h:147
#define PG_RE_THROW()
Definition: elog.h:314
ResourceOwner resowner
Definition: portal.h:120
Tuplestorestate * holdStore
Definition: portal.h:163
bool log_executor_stats
Definition: guc.c:443
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define UINT64_FORMAT
Definition: c.h:316
#define PG_END_TRY()
Definition: elog.h:300
uint64 PortalRunFetch ( Portal  portal,
FetchDirection  fdirection,
long  count,
DestReceiver dest 
)

Definition at line 1388 of file pquery.c.

References ActivePortal, Assert, AssertArg, CurrentResourceOwner, 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, PortalGetHeapMemory, PortalIsValid, PortalData::resowner, result, PortalData::run_once, PortalData::status, and PortalData::strategy.

Referenced by _SPI_cursor_operation(), and PerformPortalFetch().

1392 {
1393  uint64 result;
1394  Portal saveActivePortal;
1395  ResourceOwner saveResourceOwner;
1396  MemoryContext savePortalContext;
1397  MemoryContext oldContext;
1398 
1399  AssertArg(PortalIsValid(portal));
1400 
1401  /*
1402  * Check for improper portal use, and mark portal active.
1403  */
1404  MarkPortalActive(portal);
1405 
1406  /* If supporting FETCH, portal can't be run-once. */
1407  Assert(!portal->run_once);
1408 
1409  /*
1410  * Set up global portal context pointers.
1411  */
1412  saveActivePortal = ActivePortal;
1413  saveResourceOwner = CurrentResourceOwner;
1414  savePortalContext = PortalContext;
1415  PG_TRY();
1416  {
1417  ActivePortal = portal;
1418  if (portal->resowner)
1419  CurrentResourceOwner = portal->resowner;
1421 
1422  oldContext = MemoryContextSwitchTo(PortalContext);
1423 
1424  switch (portal->strategy)
1425  {
1426  case PORTAL_ONE_SELECT:
1427  result = DoPortalRunFetch(portal, fdirection, count, dest);
1428  break;
1429 
1430  case PORTAL_ONE_RETURNING:
1431  case PORTAL_ONE_MOD_WITH:
1432  case PORTAL_UTIL_SELECT:
1433 
1434  /*
1435  * If we have not yet run the command, do so, storing its
1436  * results in the portal's tuplestore.
1437  */
1438  if (!portal->holdStore)
1439  FillPortalStore(portal, false /* isTopLevel */ );
1440 
1441  /*
1442  * Now fetch desired portion of results.
1443  */
1444  result = DoPortalRunFetch(portal, fdirection, count, dest);
1445  break;
1446 
1447  default:
1448  elog(ERROR, "unsupported portal strategy");
1449  result = 0; /* keep compiler quiet */
1450  break;
1451  }
1452  }
1453  PG_CATCH();
1454  {
1455  /* Uncaught error while executing portal: mark it dead */
1456  MarkPortalFailed(portal);
1457 
1458  /* Restore global vars and propagate error */
1459  ActivePortal = saveActivePortal;
1460  CurrentResourceOwner = saveResourceOwner;
1461  PortalContext = savePortalContext;
1462 
1463  PG_RE_THROW();
1464  }
1465  PG_END_TRY();
1466 
1467  MemoryContextSwitchTo(oldContext);
1468 
1469  /* Mark portal not active */
1470  portal->status = PORTAL_READY;
1471 
1472  ActivePortal = saveActivePortal;
1473  CurrentResourceOwner = saveResourceOwner;
1474  PortalContext = savePortalContext;
1475 
1476  return result;
1477 }
Portal ActivePortal
Definition: pquery.c:35
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void MarkPortalActive(Portal portal)
Definition: portalmem.c:388
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1618
static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1490
bool run_once
Definition: portal.h:144
MemoryContext PortalContext
Definition: mcxt.c:52
#define ERROR
Definition: elog.h:43
static void FillPortalStore(Portal portal, bool isTopLevel)
Definition: pquery.c:1004
PortalStrategy strategy
Definition: portal.h:142
#define AssertArg(condition)
Definition: c.h:677
#define PortalIsValid(p)
Definition: portal.h:198
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:675
#define PortalGetHeapMemory(portal)
Definition: portal.h:204
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:435
PortalStatus status
Definition: portal.h:147
#define PG_RE_THROW()
Definition: elog.h:314
ResourceOwner resowner
Definition: portal.h:120
Tuplestorestate * holdStore
Definition: portal.h:163
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
static void PortalRunMulti ( Portal  portal,
bool  isTopLevel,
bool  setHoldSnapshot,
DestReceiver dest,
DestReceiver altdest,
char *  completionTag 
)
static

Definition at line 1200 of file pquery.c.

References Assert, PlannedStmt::canSetTag, castNode, CHECK_FOR_INTERRUPTS, CommandCounterIncrement(), PortalData::commandTag, CurrentMemoryContext, DestRemoteExecute, GetTransactionSnapshot(), PortalData::holdSnapshot, IsA, lfirst, lnext, log_executor_stats, MemoryContextDeleteChildren(), _DestReceiver::mydest, None_Receiver, NULL, PopActiveSnapshot(), PortalGetHeapMemory, PortalData::portalParams, PortalRunUtility(), ProcessQuery(), PushCopiedSnapshot(), RegisterSnapshot(), ResetUsage(), ShowUsage(), PortalData::sourceText, PortalData::stmts, UpdateActiveSnapshotCommandId(), and PlannedStmt::utilityStmt.

Referenced by FillPortalStore(), and PortalRun().

1204 {
1205  bool active_snapshot_set = false;
1206  ListCell *stmtlist_item;
1207 
1208  /*
1209  * If the destination is DestRemoteExecute, change to DestNone. The
1210  * reason is that the client won't be expecting any tuples, and indeed has
1211  * no way to know what they are, since there is no provision for Describe
1212  * to send a RowDescription message when this portal execution strategy is
1213  * in effect. This presently will only affect SELECT commands added to
1214  * non-SELECT queries by rewrite rules: such commands will be executed,
1215  * but the results will be discarded unless you use "simple Query"
1216  * protocol.
1217  */
1218  if (dest->mydest == DestRemoteExecute)
1219  dest = None_Receiver;
1220  if (altdest->mydest == DestRemoteExecute)
1221  altdest = None_Receiver;
1222 
1223  /*
1224  * Loop to handle the individual queries generated from a single parsetree
1225  * by analysis and rewrite.
1226  */
1227  foreach(stmtlist_item, portal->stmts)
1228  {
1229  PlannedStmt *pstmt = castNode(PlannedStmt, lfirst(stmtlist_item));
1230 
1231  /*
1232  * If we got a cancel signal in prior command, quit
1233  */
1235 
1236  if (pstmt->utilityStmt == NULL)
1237  {
1238  /*
1239  * process a plannable query.
1240  */
1241  TRACE_POSTGRESQL_QUERY_EXECUTE_START();
1242 
1243  if (log_executor_stats)
1244  ResetUsage();
1245 
1246  /*
1247  * Must always have a snapshot for plannable queries. First time
1248  * through, take a new snapshot; for subsequent queries in the
1249  * same portal, just update the snapshot's copy of the command
1250  * counter.
1251  */
1252  if (!active_snapshot_set)
1253  {
1254  Snapshot snapshot = GetTransactionSnapshot();
1255 
1256  /* If told to, register the snapshot and save in portal */
1257  if (setHoldSnapshot)
1258  {
1259  snapshot = RegisterSnapshot(snapshot);
1260  portal->holdSnapshot = snapshot;
1261  }
1262 
1263  /*
1264  * We can't have the holdSnapshot also be the active one,
1265  * because UpdateActiveSnapshotCommandId would complain. So
1266  * force an extra snapshot copy. Plain PushActiveSnapshot
1267  * would have copied the transaction snapshot anyway, so this
1268  * only adds a copy step when setHoldSnapshot is true. (It's
1269  * okay for the command ID of the active snapshot to diverge
1270  * from what holdSnapshot has.)
1271  */
1272  PushCopiedSnapshot(snapshot);
1273  active_snapshot_set = true;
1274  }
1275  else
1277 
1278  if (pstmt->canSetTag)
1279  {
1280  /* statement can set tag string */
1281  ProcessQuery(pstmt,
1282  portal->sourceText,
1283  portal->portalParams,
1284  dest, completionTag);
1285  }
1286  else
1287  {
1288  /* stmt added by rewrite cannot set tag */
1289  ProcessQuery(pstmt,
1290  portal->sourceText,
1291  portal->portalParams,
1292  altdest, NULL);
1293  }
1294 
1295  if (log_executor_stats)
1296  ShowUsage("EXECUTOR STATISTICS");
1297 
1298  TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
1299  }
1300  else
1301  {
1302  /*
1303  * process utility functions (create, destroy, etc..)
1304  *
1305  * We must not set a snapshot here for utility commands (if one is
1306  * needed, PortalRunUtility will do it). If a utility command is
1307  * alone in a portal then everything's fine. The only case where
1308  * a utility command can be part of a longer list is that rules
1309  * are allowed to include NotifyStmt. NotifyStmt doesn't care
1310  * whether it has a snapshot or not, so we just leave the current
1311  * snapshot alone if we have one.
1312  */
1313  if (pstmt->canSetTag)
1314  {
1315  Assert(!active_snapshot_set);
1316  /* statement can set tag string */
1317  PortalRunUtility(portal, pstmt, isTopLevel, false,
1318  dest, completionTag);
1319  }
1320  else
1321  {
1322  Assert(IsA(pstmt->utilityStmt, NotifyStmt));
1323  /* stmt added by rewrite cannot set tag */
1324  PortalRunUtility(portal, pstmt, isTopLevel, false,
1325  altdest, NULL);
1326  }
1327  }
1328 
1329  /*
1330  * Increment command counter between queries, but not after the last
1331  * one.
1332  */
1333  if (lnext(stmtlist_item) != NULL)
1335 
1336  /*
1337  * Clear subsidiary contexts to recover temporary memory.
1338  */
1340 
1342  }
1343 
1344  /* Pop the snapshot if we pushed one. */
1345  if (active_snapshot_set)
1347 
1348  /*
1349  * If a command completion tag was supplied, use it. Otherwise use the
1350  * portal's commandTag as the default completion tag.
1351  *
1352  * Exception: Clients expect INSERT/UPDATE/DELETE tags to have counts, so
1353  * fake them with zeros. This can happen with DO INSTEAD rules if there
1354  * is no replacement query of the same type as the original. We print "0
1355  * 0" here because technically there is no query of the matching tag type,
1356  * and printing a non-zero count for a different query type seems wrong,
1357  * e.g. an INSERT that does an UPDATE instead should not print "0 1" if
1358  * one row was updated. See QueryRewrite(), step 3, for details.
1359  */
1360  if (completionTag && completionTag[0] == '\0')
1361  {
1362  if (portal->commandTag)
1363  strcpy(completionTag, portal->commandTag);
1364  if (strcmp(completionTag, "SELECT") == 0)
1365  sprintf(completionTag, "SELECT 0 0");
1366  else if (strcmp(completionTag, "INSERT") == 0)
1367  strcpy(completionTag, "INSERT 0 0");
1368  else if (strcmp(completionTag, "UPDATE") == 0)
1369  strcpy(completionTag, "UPDATE 0");
1370  else if (strcmp(completionTag, "DELETE") == 0)
1371  strcpy(completionTag, "DELETE 0");
1372  }
1373 }
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:776
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:858
#define castNode(_type_, nodeptr)
Definition: nodes.h:573
void ShowUsage(const char *title)
Definition: postgres.c:4388
CommandDest mydest
Definition: dest.h:128
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
List * stmts
Definition: portal.h:136
DestReceiver * None_Receiver
Definition: dest.c:91
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
void ResetUsage(void)
Definition: postgres.c:4381
ParamListInfo portalParams
Definition: portal.h:139
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:764
const char * commandTag
Definition: portal.h:135
static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, char *completionTag)
Definition: pquery.c:1130
Node * utilityStmt
Definition: plannodes.h:83
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define lnext(lc)
Definition: pg_list.h:105
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:236
bool canSetTag
Definition: plannodes.h:53
void CommandCounterIncrement(void)
Definition: xact.c:922
const char * sourceText
Definition: portal.h:134
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
#define PortalGetHeapMemory(portal)
Definition: portal.h:204
Snapshot holdSnapshot
Definition: portal.h:174
bool log_executor_stats
Definition: guc.c:443
static void ProcessQuery(PlannedStmt *plan, const char *sourceText, ParamListInfo params, DestReceiver *dest, char *completionTag)
Definition: pquery.c:135
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
static uint64 PortalRunSelect ( Portal  portal,
bool  forward,
long  count,
DestReceiver dest 
)
static

Definition at line 871 of file pquery.c.

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

Referenced by DoPortalRunFetch(), and PortalRun().

875 {
876  QueryDesc *queryDesc;
877  ScanDirection direction;
878  uint64 nprocessed;
879 
880  /*
881  * NB: queryDesc will be NULL if we are fetching from a held cursor or a
882  * completed utility query; can't use it in that path.
883  */
884  queryDesc = PortalGetQueryDesc(portal);
885 
886  /* Caller messed up if we have neither a ready query nor held data. */
887  Assert(queryDesc || portal->holdStore);
888 
889  /*
890  * Force the queryDesc destination to the right thing. This supports
891  * MOVE, for example, which will pass in dest = DestNone. This is okay to
892  * change as long as we do it on every fetch. (The Executor must not
893  * assume that dest never changes.)
894  */
895  if (queryDesc)
896  queryDesc->dest = dest;
897 
898  /*
899  * Determine which direction to go in, and check to see if we're already
900  * at the end of the available tuples in that direction. If so, set the
901  * direction to NoMovement to avoid trying to fetch any tuples. (This
902  * check exists because not all plan node types are robust about being
903  * called again if they've already returned NULL once.) Then call the
904  * executor (we must not skip this, because the destination needs to see a
905  * setup and shutdown even if no tuples are available). Finally, update
906  * the portal position state depending on the number of tuples that were
907  * retrieved.
908  */
909  if (forward)
910  {
911  if (portal->atEnd || count <= 0)
912  {
913  direction = NoMovementScanDirection;
914  count = 0; /* don't pass negative count to executor */
915  }
916  else
917  direction = ForwardScanDirection;
918 
919  /* In the executor, zero count processes all rows */
920  if (count == FETCH_ALL)
921  count = 0;
922 
923  if (portal->holdStore)
924  nprocessed = RunFromStore(portal, direction, (uint64) count, dest);
925  else
926  {
927  PushActiveSnapshot(queryDesc->snapshot);
928  ExecutorRun(queryDesc, direction, (uint64) count,
929  portal->run_once);
930  nprocessed = queryDesc->estate->es_processed;
932  }
933 
934  if (!ScanDirectionIsNoMovement(direction))
935  {
936  if (nprocessed > 0)
937  portal->atStart = false; /* OK to go backward now */
938  if (count == 0 || nprocessed < (uint64) count)
939  portal->atEnd = true; /* we retrieved 'em all */
940  portal->portalPos += nprocessed;
941  }
942  }
943  else
944  {
945  if (portal->cursorOptions & CURSOR_OPT_NO_SCROLL)
946  ereport(ERROR,
947  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
948  errmsg("cursor can only scan forward"),
949  errhint("Declare it with SCROLL option to enable backward scan.")));
950 
951  if (portal->atStart || count <= 0)
952  {
953  direction = NoMovementScanDirection;
954  count = 0; /* don't pass negative count to executor */
955  }
956  else
957  direction = BackwardScanDirection;
958 
959  /* In the executor, zero count processes all rows */
960  if (count == FETCH_ALL)
961  count = 0;
962 
963  if (portal->holdStore)
964  nprocessed = RunFromStore(portal, direction, (uint64) count, dest);
965  else
966  {
967  PushActiveSnapshot(queryDesc->snapshot);
968  ExecutorRun(queryDesc, direction, (uint64) count,
969  portal->run_once);
970  nprocessed = queryDesc->estate->es_processed;
972  }
973 
974  if (!ScanDirectionIsNoMovement(direction))
975  {
976  if (nprocessed > 0 && portal->atEnd)
977  {
978  portal->atEnd = false; /* OK to go forward now */
979  portal->portalPos++; /* adjust for endpoint case */
980  }
981  if (count == 0 || nprocessed < (uint64) count)
982  {
983  portal->atStart = true; /* we retrieved 'em all */
984  portal->portalPos = 0;
985  }
986  else
987  {
988  portal->portalPos -= nprocessed;
989  }
990  }
991  }
992 
993  return nprocessed;
994 }
static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest)
Definition: pquery.c:1064
int errhint(const char *fmt,...)
Definition: elog.c:987
bool atEnd
Definition: portal.h:186
EState * estate
Definition: execdesc.h:47
int errcode(int sqlerrcode)
Definition: elog.c:575
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2572
Snapshot snapshot
Definition: execdesc.h:39
bool run_once
Definition: portal.h:144
#define ERROR
Definition: elog.h:43
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:291
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
ScanDirection
Definition: sdir.h:22
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:675
uint64 es_processed
Definition: execnodes.h:441
#define PortalGetQueryDesc(portal)
Definition: portal.h:203
DestReceiver * dest
Definition: execdesc.h:41
bool atStart
Definition: portal.h:185
Tuplestorestate * holdStore
Definition: portal.h:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
int cursorOptions
Definition: portal.h:143
uint64 portalPos
Definition: portal.h:187
#define FETCH_ALL
Definition: parsenodes.h:2614
static void PortalRunUtility ( Portal  portal,
PlannedStmt pstmt,
bool  isTopLevel,
bool  setHoldSnapshot,
DestReceiver dest,
char *  completionTag 
)
static

Definition at line 1130 of file pquery.c.

References ActiveSnapshotSet(), GetActiveSnapshot(), GetTransactionSnapshot(), PortalData::holdSnapshot, IsA, MemoryContextSwitchTo(), NULL, PopActiveSnapshot(), PortalGetHeapMemory, PortalData::portalParams, PROCESS_UTILITY_QUERY, PROCESS_UTILITY_TOPLEVEL, ProcessUtility(), PushActiveSnapshot(), RegisterSnapshot(), PortalData::sourceText, and PlannedStmt::utilityStmt.

Referenced by FillPortalStore(), and PortalRunMulti().

1133 {
1134  Node *utilityStmt = pstmt->utilityStmt;
1135  Snapshot snapshot;
1136 
1137  /*
1138  * Set snapshot if utility stmt needs one. Most reliable way to do this
1139  * seems to be to enumerate those that do not need one; this is a short
1140  * list. Transaction control, LOCK, and SET must *not* set a snapshot
1141  * since they need to be executable at the start of a transaction-snapshot
1142  * mode transaction without freezing a snapshot. By extension we allow
1143  * SHOW not to set a snapshot. The other stmts listed are just efficiency
1144  * hacks. Beware of listing anything that can modify the database --- if,
1145  * say, it has to update an index with expressions that invoke
1146  * user-defined functions, then it had better have a snapshot.
1147  */
1148  if (!(IsA(utilityStmt, TransactionStmt) ||
1149  IsA(utilityStmt, LockStmt) ||
1150  IsA(utilityStmt, VariableSetStmt) ||
1151  IsA(utilityStmt, VariableShowStmt) ||
1152  IsA(utilityStmt, ConstraintsSetStmt) ||
1153  /* efficiency hacks from here down */
1154  IsA(utilityStmt, FetchStmt) ||
1155  IsA(utilityStmt, ListenStmt) ||
1156  IsA(utilityStmt, NotifyStmt) ||
1157  IsA(utilityStmt, UnlistenStmt) ||
1158  IsA(utilityStmt, CheckPointStmt)))
1159  {
1160  snapshot = GetTransactionSnapshot();
1161  /* If told to, register the snapshot we're using and save in portal */
1162  if (setHoldSnapshot)
1163  {
1164  snapshot = RegisterSnapshot(snapshot);
1165  portal->holdSnapshot = snapshot;
1166  }
1167  PushActiveSnapshot(snapshot);
1168  /* PushActiveSnapshot might have copied the snapshot */
1169  snapshot = GetActiveSnapshot();
1170  }
1171  else
1172  snapshot = NULL;
1173 
1174  ProcessUtility(pstmt,
1175  portal->sourceText,
1177  portal->portalParams,
1178  dest,
1179  completionTag);
1180 
1181  /* Some utility statements may change context on us */
1183 
1184  /*
1185  * Some utility commands may pop the ActiveSnapshot stack from under us,
1186  * so be careful to only pop the stack if our snapshot is still at the
1187  * top.
1188  */
1189  if (snapshot != NULL && ActiveSnapshotSet() &&
1190  snapshot == GetActiveSnapshot())
1192 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:858
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
Definition: nodes.h:504
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
ParamListInfo portalParams
Definition: portal.h:139
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
Node * utilityStmt
Definition: plannodes.h:83
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:846
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, DestReceiver *dest, char *completionTag)
Definition: utility.c:332
const char * sourceText
Definition: portal.h:134
#define NULL
Definition: c.h:229
#define PortalGetHeapMemory(portal)
Definition: portal.h:204
Snapshot holdSnapshot
Definition: portal.h:174
void PortalSetResultFormat ( Portal  portal,
int  nFormats,
int16 formats 
)

Definition at line 623 of file pquery.c.

References ereport, errcode(), errmsg(), ERROR, PortalData::formats, i, MemoryContextAlloc(), tupleDesc::natts, NULL, PortalGetHeapMemory, and PortalData::tupDesc.

Referenced by exec_bind_message(), and exec_simple_query().

624 {
625  int natts;
626  int i;
627 
628  /* Do nothing if portal won't return tuples */
629  if (portal->tupDesc == NULL)
630  return;
631  natts = portal->tupDesc->natts;
632  portal->formats = (int16 *)
634  natts * sizeof(int16));
635  if (nFormats > 1)
636  {
637  /* format specified for each column */
638  if (nFormats != natts)
639  ereport(ERROR,
640  (errcode(ERRCODE_PROTOCOL_VIOLATION),
641  errmsg("bind message has %d result formats but query has %d columns",
642  nFormats, natts)));
643  memcpy(portal->formats, formats, natts * sizeof(int16));
644  }
645  else if (nFormats > 0)
646  {
647  /* single format specified, use for all columns */
648  int16 format1 = formats[0];
649 
650  for (i = 0; i < natts; i++)
651  portal->formats[i] = format1;
652  }
653  else
654  {
655  /* use default format for all columns */
656  for (i = 0; i < natts; i++)
657  portal->formats[i] = 0;
658  }
659 }
signed short int16
Definition: c.h:255
int errcode(int sqlerrcode)
Definition: elog.c:575
int natts
Definition: tupdesc.h:73
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int16 * formats
Definition: portal.h:156
TupleDesc tupDesc
Definition: portal.h:154
#define NULL
Definition: c.h:229
#define PortalGetHeapMemory(portal)
Definition: portal.h:204
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
int i
void PortalStart ( Portal  portal,
ParamListInfo  params,
int  eflags,
Snapshot  snapshot 
)

Definition at line 442 of file pquery.c.

References ActivePortal, Assert, AssertArg, AssertState, PortalData::atEnd, PortalData::atStart, castNode, ChoosePortalStrategy(), CMD_UTILITY, PlannedStmt::commandType, CreateQueryDesc(), CurrentResourceOwner, CURSOR_OPT_SCROLL, PortalData::cursorOptions, EXEC_FLAG_BACKWARD, EXEC_FLAG_REWIND, ExecCleanTypeFromTL(), ExecutorStart(), GetActiveSnapshot(), GetTransactionSnapshot(), InvalidSnapshot, linitial, MarkPortalFailed(), MemoryContextSwitchTo(), None_Receiver, NULL, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PlannedStmt::planTree, PopActiveSnapshot(), PORTAL_DEFINED, PORTAL_MULTI_QUERY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_READY, PORTAL_UTIL_SELECT, PortalContext, PortalGetHeapMemory, PortalGetPrimaryStmt(), PortalIsValid, PortalData::portalParams, PortalData::portalPos, PushActiveSnapshot(), PortalData::queryDesc, 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().

444 {
445  Portal saveActivePortal;
446  ResourceOwner saveResourceOwner;
447  MemoryContext savePortalContext;
448  MemoryContext oldContext;
449  QueryDesc *queryDesc;
450  int myeflags;
451 
452  AssertArg(PortalIsValid(portal));
453  AssertState(portal->status == PORTAL_DEFINED);
454 
455  /*
456  * Set up global portal context pointers.
457  */
458  saveActivePortal = ActivePortal;
459  saveResourceOwner = CurrentResourceOwner;
460  savePortalContext = PortalContext;
461  PG_TRY();
462  {
463  ActivePortal = portal;
464  if (portal->resowner)
465  CurrentResourceOwner = portal->resowner;
467 
468  oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
469 
470  /* Must remember portal param list, if any */
471  portal->portalParams = params;
472 
473  /*
474  * Determine the portal execution strategy
475  */
476  portal->strategy = ChoosePortalStrategy(portal->stmts);
477 
478  /*
479  * Fire her up according to the strategy
480  */
481  switch (portal->strategy)
482  {
483  case PORTAL_ONE_SELECT:
484 
485  /* Must set snapshot before starting executor. */
486  if (snapshot)
487  PushActiveSnapshot(snapshot);
488  else
490 
491  /*
492  * Create QueryDesc in portal's context; for the moment, set
493  * the destination to DestNone.
494  */
495  queryDesc = CreateQueryDesc(castNode(PlannedStmt, linitial(portal->stmts)),
496  portal->sourceText,
500  params,
501  0);
502 
503  /*
504  * If it's a scrollable cursor, executor needs to support
505  * REWIND and backwards scan, as well as whatever the caller
506  * might've asked for.
507  */
508  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
509  myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
510  else
511  myeflags = eflags;
512 
513  /*
514  * Call ExecutorStart to prepare the plan for execution
515  */
516  ExecutorStart(queryDesc, myeflags);
517 
518  /*
519  * This tells PortalCleanup to shut down the executor
520  */
521  portal->queryDesc = queryDesc;
522 
523  /*
524  * Remember tuple descriptor (computed by ExecutorStart)
525  */
526  portal->tupDesc = queryDesc->tupDesc;
527 
528  /*
529  * Reset cursor position data to "start of query"
530  */
531  portal->atStart = true;
532  portal->atEnd = false; /* allow fetches */
533  portal->portalPos = 0;
534 
536  break;
537 
539  case PORTAL_ONE_MOD_WITH:
540 
541  /*
542  * We don't start the executor until we are told to run the
543  * portal. We do need to set up the result tupdesc.
544  */
545  {
546  PlannedStmt *pstmt;
547 
548  pstmt = PortalGetPrimaryStmt(portal);
549  portal->tupDesc =
551  false);
552  }
553 
554  /*
555  * Reset cursor position data to "start of query"
556  */
557  portal->atStart = true;
558  portal->atEnd = false; /* allow fetches */
559  portal->portalPos = 0;
560  break;
561 
562  case PORTAL_UTIL_SELECT:
563 
564  /*
565  * We don't set snapshot here, because PortalRunUtility will
566  * take care of it if needed.
567  */
568  {
569  PlannedStmt *pstmt = PortalGetPrimaryStmt(portal);
570 
571  Assert(pstmt->commandType == CMD_UTILITY);
572  portal->tupDesc = UtilityTupleDescriptor(pstmt->utilityStmt);
573  }
574 
575  /*
576  * Reset cursor position data to "start of query"
577  */
578  portal->atStart = true;
579  portal->atEnd = false; /* allow fetches */
580  portal->portalPos = 0;
581  break;
582 
583  case PORTAL_MULTI_QUERY:
584  /* Need do nothing now */
585  portal->tupDesc = NULL;
586  break;
587  }
588  }
589  PG_CATCH();
590  {
591  /* Uncaught error while executing portal: mark it dead */
592  MarkPortalFailed(portal);
593 
594  /* Restore global vars and propagate error */
595  ActivePortal = saveActivePortal;
596  CurrentResourceOwner = saveResourceOwner;
597  PortalContext = savePortalContext;
598 
599  PG_RE_THROW();
600  }
601  PG_END_TRY();
602 
603  MemoryContextSwitchTo(oldContext);
604 
605  ActivePortal = saveActivePortal;
606  CurrentResourceOwner = saveResourceOwner;
607  PortalContext = savePortalContext;
608 
609  portal->status = PORTAL_READY;
610 }
#define AssertState(condition)
Definition: c.h:678
bool atEnd
Definition: portal.h:186
#define castNode(_type_, nodeptr)
Definition: nodes.h:573
Portal ActivePortal
Definition: pquery.c:35
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:144
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, int instrument_options)
Definition: pquery.c:66
List * stmts
Definition: portal.h:136
DestReceiver * None_Receiver
Definition: dest.c:91
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
struct Plan * planTree
Definition: plannodes.h:61
MemoryContext PortalContext
Definition: mcxt.c:52
ParamListInfo portalParams
Definition: portal.h:139
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
Definition: portalmem.c:150
#define linitial(l)
Definition: pg_list.h:110
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
Node * utilityStmt
Definition: plannodes.h:83
PortalStrategy strategy
Definition: portal.h:142
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define AssertArg(condition)
Definition: c.h:677
QueryDesc * queryDesc
Definition: portal.h:151
TupleDesc tupDesc
Definition: execdesc.h:46
#define InvalidSnapshot
Definition: snapshot.h:25
#define PortalIsValid(p)
Definition: portal.h:198
CmdType commandType
Definition: plannodes.h:45
const char * sourceText
Definition: portal.h:134
TupleDesc tupDesc
Definition: portal.h:154
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define PortalGetHeapMemory(portal)
Definition: portal.h:204
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:435
PortalStatus status
Definition: portal.h:147
#define PG_RE_THROW()
Definition: elog.h:314
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:218
List * targetlist
Definition: plannodes.h:132
ResourceOwner resowner
Definition: portal.h:120
bool atStart
Definition: portal.h:185
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2571
TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:900
int cursorOptions
Definition: portal.h:143
#define PG_TRY()
Definition: elog.h:284
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:1753
#define PG_END_TRY()
Definition: elog.h:300
uint64 portalPos
Definition: portal.h:187
static void ProcessQuery ( PlannedStmt plan,
const char *  sourceText,
ParamListInfo  params,
DestReceiver dest,
char *  completionTag 
)
static

Definition at line 135 of file pquery.c.

References CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, COMPLETION_TAG_BUFSIZE, CreateQueryDesc(), EState::es_lastoid, EState::es_processed, QueryDesc::estate, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), ForwardScanDirection, FreeQueryDesc(), GetActiveSnapshot(), InvalidOid, InvalidSnapshot, QueryDesc::operation, snprintf(), and UINT64_FORMAT.

Referenced by PortalRunMulti().

140 {
141  QueryDesc *queryDesc;
142 
143  /*
144  * Create the QueryDesc object
145  */
146  queryDesc = CreateQueryDesc(plan, sourceText,
148  dest, params, 0);
149 
150  /*
151  * Call ExecutorStart to prepare the plan for execution
152  */
153  ExecutorStart(queryDesc, 0);
154 
155  /*
156  * Run the plan to completion.
157  */
158  ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
159 
160  /*
161  * Build command completion status string, if caller wants one.
162  */
163  if (completionTag)
164  {
165  Oid lastOid;
166 
167  switch (queryDesc->operation)
168  {
169  case CMD_SELECT:
170  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
171  "SELECT " UINT64_FORMAT,
172  queryDesc->estate->es_processed);
173  break;
174  case CMD_INSERT:
175  if (queryDesc->estate->es_processed == 1)
176  lastOid = queryDesc->estate->es_lastoid;
177  else
178  lastOid = InvalidOid;
179  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
180  "INSERT %u " UINT64_FORMAT,
181  lastOid, queryDesc->estate->es_processed);
182  break;
183  case CMD_UPDATE:
184  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
185  "UPDATE " UINT64_FORMAT,
186  queryDesc->estate->es_processed);
187  break;
188  case CMD_DELETE:
189  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
190  "DELETE " UINT64_FORMAT,
191  queryDesc->estate->es_processed);
192  break;
193  default:
194  strcpy(completionTag, "???");
195  break;
196  }
197  }
198 
199  /*
200  * Now, we close down all the scans and free allocated resources.
201  */
202  ExecutorFinish(queryDesc);
203  ExecutorEnd(queryDesc);
204 
205  FreeQueryDesc(queryDesc);
206 }
EState * estate
Definition: execdesc.h:47
Oid es_lastoid
Definition: execnodes.h:442
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:103
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:144
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, int instrument_options)
Definition: pquery.c:66
unsigned int Oid
Definition: postgres_ext.h:31
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:453
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:291
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:393
CmdType operation
Definition: execdesc.h:36
#define InvalidSnapshot
Definition: snapshot.h:25
#define InvalidOid
Definition: postgres_ext.h:36
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
uint64 es_processed
Definition: execnodes.h:441
#define UINT64_FORMAT
Definition: c.h:316
static uint64 RunFromStore ( Portal  portal,
ScanDirection  direction,
uint64  count,
DestReceiver dest 
)
static

Definition at line 1064 of file pquery.c.

References CMD_SELECT, ExecClearTuple(), ExecDropSingleTupleTableSlot(), PortalData::holdContext, PortalData::holdStore, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), _DestReceiver::receiveSlot, _DestReceiver::rShutdown, _DestReceiver::rStartup, ScanDirectionIsForward, ScanDirectionIsNoMovement, PortalData::tupDesc, and tuplestore_gettupleslot().

Referenced by PortalRunSelect().

1066 {
1067  uint64 current_tuple_count = 0;
1068  TupleTableSlot *slot;
1069 
1070  slot = MakeSingleTupleTableSlot(portal->tupDesc);
1071 
1072  (*dest->rStartup) (dest, CMD_SELECT, portal->tupDesc);
1073 
1074  if (ScanDirectionIsNoMovement(direction))
1075  {
1076  /* do nothing except start/stop the destination */
1077  }
1078  else
1079  {
1080  bool forward = ScanDirectionIsForward(direction);
1081 
1082  for (;;)
1083  {
1084  MemoryContext oldcontext;
1085  bool ok;
1086 
1087  oldcontext = MemoryContextSwitchTo(portal->holdContext);
1088 
1089  ok = tuplestore_gettupleslot(portal->holdStore, forward, false,
1090  slot);
1091 
1092  MemoryContextSwitchTo(oldcontext);
1093 
1094  if (!ok)
1095  break;
1096 
1097  /*
1098  * If we are not able to send the tuple, we assume the destination
1099  * has closed and no more tuples can be sent. If that's the case,
1100  * end the loop.
1101  */
1102  if (!((*dest->receiveSlot) (slot, dest)))
1103  break;
1104 
1105  ExecClearTuple(slot);
1106 
1107  /*
1108  * check our tuple count.. if we've processed the proper number
1109  * then quit, else loop again and process more tuples. Zero count
1110  * means no limit.
1111  */
1112  current_tuple_count++;
1113  if (count && count == current_tuple_count)
1114  break;
1115  }
1116  }
1117 
1118  (*dest->rShutdown) (dest);
1119 
1121 
1122  return current_tuple_count;
1123 }
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext holdContext
Definition: portal.h:164
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
TupleDesc tupDesc
Definition: portal.h:154
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1061
Tuplestorestate * holdStore
Definition: portal.h:163
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118

Variable Documentation