PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pquery.c File Reference
#include "postgres.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, 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 213 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().

214 {
215  int nSetTag;
216  ListCell *lc;
217 
218  /*
219  * PORTAL_ONE_SELECT and PORTAL_UTIL_SELECT need only consider the
220  * single-statement case, since there are no rewrite rules that can add
221  * auxiliary queries to a SELECT or a utility command. PORTAL_ONE_MOD_WITH
222  * likewise allows only one top-level statement.
223  */
224  if (list_length(stmts) == 1)
225  {
226  Node *stmt = (Node *) linitial(stmts);
227 
228  if (IsA(stmt, Query))
229  {
230  Query *query = (Query *) stmt;
231 
232  if (query->canSetTag)
233  {
234  if (query->commandType == CMD_SELECT)
235  {
236  if (query->hasModifyingCTE)
237  return PORTAL_ONE_MOD_WITH;
238  else
239  return PORTAL_ONE_SELECT;
240  }
241  if (query->commandType == CMD_UTILITY)
242  {
243  if (UtilityReturnsTuples(query->utilityStmt))
244  return PORTAL_UTIL_SELECT;
245  /* it can't be ONE_RETURNING, so give up */
246  return PORTAL_MULTI_QUERY;
247  }
248  }
249  }
250  else if (IsA(stmt, PlannedStmt))
251  {
252  PlannedStmt *pstmt = (PlannedStmt *) stmt;
253 
254  if (pstmt->canSetTag)
255  {
256  if (pstmt->commandType == CMD_SELECT)
257  {
258  if (pstmt->hasModifyingCTE)
259  return PORTAL_ONE_MOD_WITH;
260  else
261  return PORTAL_ONE_SELECT;
262  }
263  if (pstmt->commandType == CMD_UTILITY)
264  {
265  if (UtilityReturnsTuples(pstmt->utilityStmt))
266  return PORTAL_UTIL_SELECT;
267  /* it can't be ONE_RETURNING, so give up */
268  return PORTAL_MULTI_QUERY;
269  }
270  }
271  }
272  else
273  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
274  }
275 
276  /*
277  * PORTAL_ONE_RETURNING has to allow auxiliary queries added by rewrite.
278  * Choose PORTAL_ONE_RETURNING if there is exactly one canSetTag query and
279  * it has a RETURNING list.
280  */
281  nSetTag = 0;
282  foreach(lc, stmts)
283  {
284  Node *stmt = (Node *) lfirst(lc);
285 
286  if (IsA(stmt, Query))
287  {
288  Query *query = (Query *) stmt;
289 
290  if (query->canSetTag)
291  {
292  if (++nSetTag > 1)
293  return PORTAL_MULTI_QUERY; /* no need to look further */
294  if (query->commandType == CMD_UTILITY ||
295  query->returningList == NIL)
296  return PORTAL_MULTI_QUERY; /* no need to look further */
297  }
298  }
299  else if (IsA(stmt, PlannedStmt))
300  {
301  PlannedStmt *pstmt = (PlannedStmt *) stmt;
302 
303  if (pstmt->canSetTag)
304  {
305  if (++nSetTag > 1)
306  return PORTAL_MULTI_QUERY; /* no need to look further */
307  if (pstmt->commandType == CMD_UTILITY ||
308  !pstmt->hasReturning)
309  return PORTAL_MULTI_QUERY; /* no need to look further */
310  }
311  }
312  else
313  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
314  }
315  if (nSetTag == 1)
316  return PORTAL_ONE_RETURNING;
317 
318  /* Else, it's the general case... */
319  return PORTAL_MULTI_QUERY;
320 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Definition: nodes.h:508
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:80
bool UtilityReturnsTuples(Node *parsetree)
Definition: utility.c:1694
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:513
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 64 of file pquery.c.

References 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().

71 {
72  QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
73 
74  qd->operation = plannedstmt->commandType; /* operation */
75  qd->plannedstmt = plannedstmt; /* plan */
76  qd->sourceText = sourceText; /* query text */
77  qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */
78  /* RI check snapshot */
79  qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot);
80  qd->dest = dest; /* output dest */
81  qd->params = params; /* parameter values passed into query */
82  qd->instrument_options = instrument_options; /* instrumentation
83  * wanted? */
84 
85  /* null these fields until set by ExecutorStart */
86  qd->tupDesc = NULL;
87  qd->estate = NULL;
88  qd->planstate = NULL;
89  qd->totaltime = NULL;
90 
91  return qd;
92 }
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
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
struct Instrumentation * totaltime
Definition: execdesc.h:51
#define NULL
Definition: c.h:226
const char * sourceText
Definition: execdesc.h:38
DestReceiver * dest
Definition: execdesc.h:41
void * palloc(Size size)
Definition: mcxt.c:891
PlannedStmt * plannedstmt
Definition: execdesc.h:37
static void DoPortalRewind ( Portal  portal)
static

Definition at line 1661 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().

1662 {
1663  QueryDesc *queryDesc;
1664 
1665  /* Rewind holdStore, if we have one */
1666  if (portal->holdStore)
1667  {
1668  MemoryContext oldcontext;
1669 
1670  oldcontext = MemoryContextSwitchTo(portal->holdContext);
1671  tuplestore_rescan(portal->holdStore);
1672  MemoryContextSwitchTo(oldcontext);
1673  }
1674 
1675  /* Rewind executor, if active */
1676  queryDesc = PortalGetQueryDesc(portal);
1677  if (queryDesc)
1678  {
1679  PushActiveSnapshot(queryDesc->snapshot);
1680  ExecutorRewind(queryDesc);
1682  }
1683 
1684  portal->atStart = true;
1685  portal->atEnd = false;
1686  portal->portalPos = 0;
1687 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1216
bool atEnd
Definition: portal.h:185
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext holdContext
Definition: portal.h:163
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:505
#define PortalGetQueryDesc(portal)
Definition: portal.h:202
bool atStart
Definition: portal.h:184
Tuplestorestate * holdStore
Definition: portal.h:162
uint64 portalPos
Definition: portal.h:186
static uint64 DoPortalRunFetch ( Portal  portal,
FetchDirection  fdirection,
long  count,
DestReceiver dest 
)
static

Definition at line 1476 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(), and PortalData::strategy.

Referenced by PortalRunFetch().

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

Definition at line 330 of file pquery.c.

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

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

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

Definition at line 352 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, Plan::targetlist, Query::targetList, PlannedStmt::utilityStmt, and Query::utilityStmt.

Referenced by CachedPlanGetTargetList(), and FetchPortalTargetList().

353 {
354  if (stmt == NULL)
355  return NIL;
356  if (IsA(stmt, Query))
357  {
358  Query *query = (Query *) stmt;
359 
360  if (query->commandType == CMD_UTILITY)
361  {
362  /* transfer attention to utility statement */
363  stmt = query->utilityStmt;
364  }
365  else
366  {
367  if (query->commandType == CMD_SELECT)
368  return query->targetList;
369  if (query->returningList)
370  return query->returningList;
371  return NIL;
372  }
373  }
374  if (IsA(stmt, PlannedStmt))
375  {
376  PlannedStmt *pstmt = (PlannedStmt *) stmt;
377 
378  if (pstmt->commandType == CMD_UTILITY)
379  {
380  /* transfer attention to utility statement */
381  stmt = pstmt->utilityStmt;
382  }
383  else
384  {
385  if (pstmt->commandType == CMD_SELECT)
386  return pstmt->planTree->targetlist;
387  if (pstmt->hasReturning)
388  return pstmt->planTree->targetlist;
389  return NIL;
390  }
391  }
392  if (IsA(stmt, FetchStmt))
393  {
394  FetchStmt *fstmt = (FetchStmt *) stmt;
395  Portal subportal;
396 
397  Assert(!fstmt->ismove);
398  subportal = GetPortalByName(fstmt->portalname);
399  Assert(PortalIsValid(subportal));
400  return FetchPortalTargetList(subportal);
401  }
402  if (IsA(stmt, ExecuteStmt))
403  {
404  ExecuteStmt *estmt = (ExecuteStmt *) stmt;
405  PreparedStatement *entry;
406 
407  entry = FetchPreparedStatement(estmt->name, true);
408  return FetchPreparedStatementTargetList(entry);
409  }
410  return NIL;
411 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
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:80
List * returningList
Definition: parsenodes.h:135
char * portalname
Definition: parsenodes.h:2570
#define PortalIsValid(p)
Definition: portal.h:197
bool ismove
Definition: parsenodes.h:2571
CmdType commandType
Definition: plannodes.h:45
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:547
CmdType commandType
Definition: parsenodes.h:103
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
List * targetlist
Definition: plannodes.h:129
char * name
Definition: parsenodes.h:3180
List * FetchPortalTargetList(Portal portal)
Definition: pquery.c:330
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:492
static void FillPortalStore ( Portal  portal,
bool  isTopLevel 
)
static

Definition at line 993 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().

994 {
995  DestReceiver *treceiver;
996  char completionTag[COMPLETION_TAG_BUFSIZE];
997 
998  PortalCreateHoldStore(portal);
999  treceiver = CreateDestReceiver(DestTuplestore);
1001  portal->holdStore,
1002  portal->holdContext,
1003  false);
1004 
1005  completionTag[0] = '\0';
1006 
1007  switch (portal->strategy)
1008  {
1009  case PORTAL_ONE_RETURNING:
1010  case PORTAL_ONE_MOD_WITH:
1011 
1012  /*
1013  * Run the portal to completion just as for the default
1014  * MULTI_QUERY case, but send the primary query's output to the
1015  * tuplestore. Auxiliary query outputs are discarded. Set the
1016  * portal's holdSnapshot to the snapshot used (or a copy of it).
1017  */
1018  PortalRunMulti(portal, isTopLevel, true,
1019  treceiver, None_Receiver, completionTag);
1020  break;
1021 
1022  case PORTAL_UTIL_SELECT:
1023  PortalRunUtility(portal, castNode(PlannedStmt, linitial(portal->stmts)),
1024  isTopLevel, true, treceiver, completionTag);
1025  break;
1026 
1027  default:
1028  elog(ERROR, "unsupported portal strategy: %d",
1029  (int) portal->strategy);
1030  break;
1031  }
1032 
1033  /* Override default completion tag with actual command result */
1034  if (completionTag[0] != '\0')
1035  portal->commandTag = pstrdup(completionTag);
1036 
1037  (*treceiver->rDestroy) (treceiver);
1038 }
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
char * pstrdup(const char *in)
Definition: mcxt.c:1165
void SetTuplestoreDestReceiverParams(DestReceiver *self, Tuplestorestate *tStore, MemoryContext tContext, bool detoast)
MemoryContext holdContext
Definition: portal.h:163
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:1119
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:1189
void PortalCreateHoldStore(Portal portal)
Definition: portalmem.c:324
Tuplestorestate * holdStore
Definition: portal.h:162
#define elog
Definition: elog.h:219
void FreeQueryDesc ( QueryDesc qdesc)

Definition at line 98 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().

99 {
100  /* Can't be a live query */
101  Assert(qdesc->estate == NULL);
102 
103  /* forget our snapshots */
106 
107  /* Only the QueryDesc itself need be freed */
108  pfree(qdesc);
109 }
EState * estate
Definition: execdesc.h:47
Snapshot snapshot
Definition: execdesc.h:39
void pfree(void *pointer)
Definition: mcxt.c:992
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:900
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
bool PortalRun ( Portal  portal,
long  count,
bool  isTopLevel,
DestReceiver dest,
DestReceiver altdest,
char *  completionTag 
)

Definition at line 680 of file pquery.c.

References ActivePortal, 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, ShowUsage(), snprintf(), PortalData::status, PortalData::strategy, TopTransactionContext, TopTransactionResourceOwner, and UINT64_FORMAT.

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

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

Definition at line 1377 of file pquery.c.

References ActivePortal, 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, PortalData::status, and PortalData::strategy.

Referenced by _SPI_cursor_operation(), and PerformPortalFetch().

1381 {
1382  uint64 result;
1383  Portal saveActivePortal;
1384  ResourceOwner saveResourceOwner;
1385  MemoryContext savePortalContext;
1386  MemoryContext oldContext;
1387 
1388  AssertArg(PortalIsValid(portal));
1389 
1390  /*
1391  * Check for improper portal use, and mark portal active.
1392  */
1393  MarkPortalActive(portal);
1394 
1395  /*
1396  * Set up global portal context pointers.
1397  */
1398  saveActivePortal = ActivePortal;
1399  saveResourceOwner = CurrentResourceOwner;
1400  savePortalContext = PortalContext;
1401  PG_TRY();
1402  {
1403  ActivePortal = portal;
1404  if (portal->resowner)
1405  CurrentResourceOwner = portal->resowner;
1407 
1408  oldContext = MemoryContextSwitchTo(PortalContext);
1409 
1410  switch (portal->strategy)
1411  {
1412  case PORTAL_ONE_SELECT:
1413  result = DoPortalRunFetch(portal, fdirection, count, dest);
1414  break;
1415 
1416  case PORTAL_ONE_RETURNING:
1417  case PORTAL_ONE_MOD_WITH:
1418  case PORTAL_UTIL_SELECT:
1419 
1420  /*
1421  * If we have not yet run the command, do so, storing its
1422  * results in the portal's tuplestore.
1423  */
1424  if (!portal->holdStore)
1425  FillPortalStore(portal, false /* isTopLevel */ );
1426 
1427  /*
1428  * Now fetch desired portion of results.
1429  */
1430  result = DoPortalRunFetch(portal, fdirection, count, dest);
1431  break;
1432 
1433  default:
1434  elog(ERROR, "unsupported portal strategy");
1435  result = 0; /* keep compiler quiet */
1436  break;
1437  }
1438  }
1439  PG_CATCH();
1440  {
1441  /* Uncaught error while executing portal: mark it dead */
1442  MarkPortalFailed(portal);
1443 
1444  /* Restore global vars and propagate error */
1445  ActivePortal = saveActivePortal;
1446  CurrentResourceOwner = saveResourceOwner;
1447  PortalContext = savePortalContext;
1448 
1449  PG_RE_THROW();
1450  }
1451  PG_END_TRY();
1452 
1453  MemoryContextSwitchTo(oldContext);
1454 
1455  /* Mark portal not active */
1456  portal->status = PORTAL_READY;
1457 
1458  ActivePortal = saveActivePortal;
1459  CurrentResourceOwner = saveResourceOwner;
1460  PortalContext = savePortalContext;
1461 
1462  return result;
1463 }
Portal ActivePortal
Definition: pquery.c:33
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void MarkPortalActive(Portal portal)
Definition: portalmem.c:388
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1476
MemoryContext PortalContext
Definition: mcxt.c:52
#define ERROR
Definition: elog.h:43
static void FillPortalStore(Portal portal, bool isTopLevel)
Definition: pquery.c:993
PortalStrategy strategy
Definition: portal.h:142
#define AssertArg(condition)
Definition: c.h:672
#define PortalIsValid(p)
Definition: portal.h:197
#define PG_CATCH()
Definition: elog.h:293
#define PortalGetHeapMemory(portal)
Definition: portal.h:203
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:435
PortalStatus status
Definition: portal.h:146
#define PG_RE_THROW()
Definition: elog.h:314
ResourceOwner resowner
Definition: portal.h:120
Tuplestorestate * holdStore
Definition: portal.h:162
#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 1189 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().

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

Definition at line 862 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(), RunFromStore(), ScanDirectionIsNoMovement, and QueryDesc::snapshot.

Referenced by DoPortalRunFetch(), and PortalRun().

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

Definition at line 1119 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().

1122 {
1123  Node *utilityStmt = pstmt->utilityStmt;
1124  Snapshot snapshot;
1125 
1126  /*
1127  * Set snapshot if utility stmt needs one. Most reliable way to do this
1128  * seems to be to enumerate those that do not need one; this is a short
1129  * list. Transaction control, LOCK, and SET must *not* set a snapshot
1130  * since they need to be executable at the start of a transaction-snapshot
1131  * mode transaction without freezing a snapshot. By extension we allow
1132  * SHOW not to set a snapshot. The other stmts listed are just efficiency
1133  * hacks. Beware of listing anything that can modify the database --- if,
1134  * say, it has to update an index with expressions that invoke
1135  * user-defined functions, then it had better have a snapshot.
1136  */
1137  if (!(IsA(utilityStmt, TransactionStmt) ||
1138  IsA(utilityStmt, LockStmt) ||
1139  IsA(utilityStmt, VariableSetStmt) ||
1140  IsA(utilityStmt, VariableShowStmt) ||
1141  IsA(utilityStmt, ConstraintsSetStmt) ||
1142  /* efficiency hacks from here down */
1143  IsA(utilityStmt, FetchStmt) ||
1144  IsA(utilityStmt, ListenStmt) ||
1145  IsA(utilityStmt, NotifyStmt) ||
1146  IsA(utilityStmt, UnlistenStmt) ||
1147  IsA(utilityStmt, CheckPointStmt)))
1148  {
1149  snapshot = GetTransactionSnapshot();
1150  /* If told to, register the snapshot we're using and save in portal */
1151  if (setHoldSnapshot)
1152  {
1153  snapshot = RegisterSnapshot(snapshot);
1154  portal->holdSnapshot = snapshot;
1155  }
1156  PushActiveSnapshot(snapshot);
1157  /* PushActiveSnapshot might have copied the snapshot */
1158  snapshot = GetActiveSnapshot();
1159  }
1160  else
1161  snapshot = NULL;
1162 
1163  ProcessUtility(pstmt,
1164  portal->sourceText,
1166  portal->portalParams,
1167  dest,
1168  completionTag);
1169 
1170  /* Some utility statements may change context on us */
1172 
1173  /*
1174  * Some utility commands may pop the ActiveSnapshot stack from under us,
1175  * so be careful to only pop the stack if our snapshot is still at the
1176  * top.
1177  */
1178  if (snapshot != NULL && ActiveSnapshotSet() &&
1179  snapshot == GetActiveSnapshot())
1181 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
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:508
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:80
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:226
#define PortalGetHeapMemory(portal)
Definition: portal.h:203
Snapshot holdSnapshot
Definition: portal.h:173
void PortalSetResultFormat ( Portal  portal,
int  nFormats,
int16 formats 
)

Definition at line 618 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().

619 {
620  int natts;
621  int i;
622 
623  /* Do nothing if portal won't return tuples */
624  if (portal->tupDesc == NULL)
625  return;
626  natts = portal->tupDesc->natts;
627  portal->formats = (int16 *)
629  natts * sizeof(int16));
630  if (nFormats > 1)
631  {
632  /* format specified for each column */
633  if (nFormats != natts)
634  ereport(ERROR,
635  (errcode(ERRCODE_PROTOCOL_VIOLATION),
636  errmsg("bind message has %d result formats but query has %d columns",
637  nFormats, natts)));
638  memcpy(portal->formats, formats, natts * sizeof(int16));
639  }
640  else if (nFormats > 0)
641  {
642  /* single format specified, use for all columns */
643  int16 format1 = formats[0];
644 
645  for (i = 0; i < natts; i++)
646  portal->formats[i] = format1;
647  }
648  else
649  {
650  /* use default format for all columns */
651  for (i = 0; i < natts; i++)
652  portal->formats[i] = 0;
653  }
654 }
signed short int16
Definition: c.h:252
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:155
TupleDesc tupDesc
Definition: portal.h:153
#define NULL
Definition: c.h:226
#define PortalGetHeapMemory(portal)
Definition: portal.h:203
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
void PortalStart ( Portal  portal,
ParamListInfo  params,
int  eflags,
Snapshot  snapshot 
)

Definition at line 437 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().

439 {
440  Portal saveActivePortal;
441  ResourceOwner saveResourceOwner;
442  MemoryContext savePortalContext;
443  MemoryContext oldContext;
444  QueryDesc *queryDesc;
445  int myeflags;
446 
447  AssertArg(PortalIsValid(portal));
448  AssertState(portal->status == PORTAL_DEFINED);
449 
450  /*
451  * Set up global portal context pointers.
452  */
453  saveActivePortal = ActivePortal;
454  saveResourceOwner = CurrentResourceOwner;
455  savePortalContext = PortalContext;
456  PG_TRY();
457  {
458  ActivePortal = portal;
459  if (portal->resowner)
460  CurrentResourceOwner = portal->resowner;
462 
463  oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
464 
465  /* Must remember portal param list, if any */
466  portal->portalParams = params;
467 
468  /*
469  * Determine the portal execution strategy
470  */
471  portal->strategy = ChoosePortalStrategy(portal->stmts);
472 
473  /*
474  * Fire her up according to the strategy
475  */
476  switch (portal->strategy)
477  {
478  case PORTAL_ONE_SELECT:
479 
480  /* Must set snapshot before starting executor. */
481  if (snapshot)
482  PushActiveSnapshot(snapshot);
483  else
485 
486  /*
487  * Create QueryDesc in portal's context; for the moment, set
488  * the destination to DestNone.
489  */
490  queryDesc = CreateQueryDesc(castNode(PlannedStmt, linitial(portal->stmts)),
491  portal->sourceText,
495  params,
496  0);
497 
498  /*
499  * If it's a scrollable cursor, executor needs to support
500  * REWIND and backwards scan, as well as whatever the caller
501  * might've asked for.
502  */
503  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
504  myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
505  else
506  myeflags = eflags;
507 
508  /*
509  * Call ExecutorStart to prepare the plan for execution
510  */
511  ExecutorStart(queryDesc, myeflags);
512 
513  /*
514  * This tells PortalCleanup to shut down the executor
515  */
516  portal->queryDesc = queryDesc;
517 
518  /*
519  * Remember tuple descriptor (computed by ExecutorStart)
520  */
521  portal->tupDesc = queryDesc->tupDesc;
522 
523  /*
524  * Reset cursor position data to "start of query"
525  */
526  portal->atStart = true;
527  portal->atEnd = false; /* allow fetches */
528  portal->portalPos = 0;
529 
531  break;
532 
534  case PORTAL_ONE_MOD_WITH:
535 
536  /*
537  * We don't start the executor until we are told to run the
538  * portal. We do need to set up the result tupdesc.
539  */
540  {
541  PlannedStmt *pstmt;
542 
543  pstmt = PortalGetPrimaryStmt(portal);
544  portal->tupDesc =
546  false);
547  }
548 
549  /*
550  * Reset cursor position data to "start of query"
551  */
552  portal->atStart = true;
553  portal->atEnd = false; /* allow fetches */
554  portal->portalPos = 0;
555  break;
556 
557  case PORTAL_UTIL_SELECT:
558 
559  /*
560  * We don't set snapshot here, because PortalRunUtility will
561  * take care of it if needed.
562  */
563  {
564  PlannedStmt *pstmt = PortalGetPrimaryStmt(portal);
565 
566  Assert(pstmt->commandType == CMD_UTILITY);
567  portal->tupDesc = UtilityTupleDescriptor(pstmt->utilityStmt);
568  }
569 
570  /*
571  * Reset cursor position data to "start of query"
572  */
573  portal->atStart = true;
574  portal->atEnd = false; /* allow fetches */
575  portal->portalPos = 0;
576  break;
577 
578  case PORTAL_MULTI_QUERY:
579  /* Need do nothing now */
580  portal->tupDesc = NULL;
581  break;
582  }
583  }
584  PG_CATCH();
585  {
586  /* Uncaught error while executing portal: mark it dead */
587  MarkPortalFailed(portal);
588 
589  /* Restore global vars and propagate error */
590  ActivePortal = saveActivePortal;
591  CurrentResourceOwner = saveResourceOwner;
592  PortalContext = savePortalContext;
593 
594  PG_RE_THROW();
595  }
596  PG_END_TRY();
597 
598  MemoryContextSwitchTo(oldContext);
599 
600  ActivePortal = saveActivePortal;
601  CurrentResourceOwner = saveResourceOwner;
602  PortalContext = savePortalContext;
603 
604  portal->status = PORTAL_READY;
605 }
#define AssertState(condition)
Definition: c.h:673
bool atEnd
Definition: portal.h:185
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
Portal ActivePortal
Definition: pquery.c:33
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:138
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:64
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:80
PortalStrategy strategy
Definition: portal.h:142
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define AssertArg(condition)
Definition: c.h:672
QueryDesc * queryDesc
Definition: portal.h:150
TupleDesc tupDesc
Definition: execdesc.h:46
#define InvalidSnapshot
Definition: snapshot.h:24
#define PortalIsValid(p)
Definition: portal.h:197
CmdType commandType
Definition: plannodes.h:45
const char * sourceText
Definition: portal.h:134
TupleDesc tupDesc
Definition: portal.h:153
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define PortalGetHeapMemory(portal)
Definition: portal.h:203
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:435
PortalStatus status
Definition: portal.h:146
#define PG_RE_THROW()
Definition: elog.h:314
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:213
List * targetlist
Definition: plannodes.h:129
ResourceOwner resowner
Definition: portal.h:120
bool atStart
Definition: portal.h:184
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2520
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:1744
#define PG_END_TRY()
Definition: elog.h:300
uint64 portalPos
Definition: portal.h:186
static void ProcessQuery ( PlannedStmt plan,
const char *  sourceText,
ParamListInfo  params,
DestReceiver dest,
char *  completionTag 
)
static

Definition at line 130 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().

135 {
136  QueryDesc *queryDesc;
137 
138  /*
139  * Create the QueryDesc object
140  */
141  queryDesc = CreateQueryDesc(plan, sourceText,
143  dest, params, 0);
144 
145  /*
146  * Call ExecutorStart to prepare the plan for execution
147  */
148  ExecutorStart(queryDesc, 0);
149 
150  /*
151  * Run the plan to completion.
152  */
153  ExecutorRun(queryDesc, ForwardScanDirection, 0L);
154 
155  /*
156  * Build command completion status string, if caller wants one.
157  */
158  if (completionTag)
159  {
160  Oid lastOid;
161 
162  switch (queryDesc->operation)
163  {
164  case CMD_SELECT:
165  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
166  "SELECT " UINT64_FORMAT,
167  queryDesc->estate->es_processed);
168  break;
169  case CMD_INSERT:
170  if (queryDesc->estate->es_processed == 1)
171  lastOid = queryDesc->estate->es_lastoid;
172  else
173  lastOid = InvalidOid;
174  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
175  "INSERT %u " UINT64_FORMAT,
176  lastOid, queryDesc->estate->es_processed);
177  break;
178  case CMD_UPDATE:
179  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
180  "UPDATE " UINT64_FORMAT,
181  queryDesc->estate->es_processed);
182  break;
183  case CMD_DELETE:
184  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
185  "DELETE " UINT64_FORMAT,
186  queryDesc->estate->es_processed);
187  break;
188  default:
189  strcpy(completionTag, "???");
190  break;
191  }
192  }
193 
194  /*
195  * Now, we close down all the scans and free allocated resources.
196  */
197  ExecutorFinish(queryDesc);
198  ExecutorEnd(queryDesc);
199 
200  FreeQueryDesc(queryDesc);
201 }
EState * estate
Definition: execdesc.h:47
Oid es_lastoid
Definition: execnodes.h:404
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:98
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:138
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:285
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:64
unsigned int Oid
Definition: postgres_ext.h:31
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:439
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:379
CmdType operation
Definition: execdesc.h:36
#define InvalidSnapshot
Definition: snapshot.h:24
#define InvalidOid
Definition: postgres_ext.h:36
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
uint64 es_processed
Definition: execnodes.h:403
#define UINT64_FORMAT
Definition: c.h:313
static uint64 RunFromStore ( Portal  portal,
ScanDirection  direction,
uint64  count,
DestReceiver dest 
)
static

Definition at line 1053 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().

1055 {
1056  uint64 current_tuple_count = 0;
1057  TupleTableSlot *slot;
1058 
1059  slot = MakeSingleTupleTableSlot(portal->tupDesc);
1060 
1061  (*dest->rStartup) (dest, CMD_SELECT, portal->tupDesc);
1062 
1063  if (ScanDirectionIsNoMovement(direction))
1064  {
1065  /* do nothing except start/stop the destination */
1066  }
1067  else
1068  {
1069  bool forward = ScanDirectionIsForward(direction);
1070 
1071  for (;;)
1072  {
1073  MemoryContext oldcontext;
1074  bool ok;
1075 
1076  oldcontext = MemoryContextSwitchTo(portal->holdContext);
1077 
1078  ok = tuplestore_gettupleslot(portal->holdStore, forward, false,
1079  slot);
1080 
1081  MemoryContextSwitchTo(oldcontext);
1082 
1083  if (!ok)
1084  break;
1085 
1086  /*
1087  * If we are not able to send the tuple, we assume the destination
1088  * has closed and no more tuples can be sent. If that's the case,
1089  * end the loop.
1090  */
1091  if (!((*dest->receiveSlot) (slot, dest)))
1092  break;
1093 
1094  ExecClearTuple(slot);
1095 
1096  /*
1097  * check our tuple count.. if we've processed the proper number
1098  * then quit, else loop again and process more tuples. Zero count
1099  * means no limit.
1100  */
1101  current_tuple_count++;
1102  if (count && count == current_tuple_count)
1103  break;
1104  }
1105  }
1106 
1107  (*dest->rShutdown) (dest);
1108 
1110 
1111  return current_tuple_count;
1112 }
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:163
#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:153
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1061
Tuplestorestate * holdStore
Definition: portal.h:162
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118

Variable Documentation