PostgreSQL Source Code  git master
pquery.h File Reference
#include "nodes/parsenodes.h"
#include "utils/portal.h"
Include dependency graph for pquery.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

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

PGDLLIMPORT Portal ActivePortal
 

Function Documentation

◆ ChoosePortalStrategy()

PortalStrategy ChoosePortalStrategy ( List stmts)

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

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

◆ FetchPortalTargetList()

List* FetchPortalTargetList ( Portal  portal)

Definition at line 336 of file pquery.c.

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

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

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

◆ FetchStatementTargetList()

List* FetchStatementTargetList ( Node stmt)

Definition at line 358 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, PlannedStmt::planTree, PortalIsValid, FetchStmt::portalname, Query::returningList, Query::targetList, Plan::targetlist, PlannedStmt::utilityStmt, and Query::utilityStmt.

Referenced by CachedPlanGetTargetList(), and FetchPortalTargetList().

359 {
360  if (stmt == NULL)
361  return NIL;
362  if (IsA(stmt, Query))
363  {
364  Query *query = (Query *) stmt;
365 
366  if (query->commandType == CMD_UTILITY)
367  {
368  /* transfer attention to utility statement */
369  stmt = query->utilityStmt;
370  }
371  else
372  {
373  if (query->commandType == CMD_SELECT)
374  return query->targetList;
375  if (query->returningList)
376  return query->returningList;
377  return NIL;
378  }
379  }
380  if (IsA(stmt, PlannedStmt))
381  {
382  PlannedStmt *pstmt = (PlannedStmt *) stmt;
383 
384  if (pstmt->commandType == CMD_UTILITY)
385  {
386  /* transfer attention to utility statement */
387  stmt = pstmt->utilityStmt;
388  }
389  else
390  {
391  if (pstmt->commandType == CMD_SELECT)
392  return pstmt->planTree->targetlist;
393  if (pstmt->hasReturning)
394  return pstmt->planTree->targetlist;
395  return NIL;
396  }
397  }
398  if (IsA(stmt, FetchStmt))
399  {
400  FetchStmt *fstmt = (FetchStmt *) stmt;
401  Portal subportal;
402 
403  Assert(!fstmt->ismove);
404  subportal = GetPortalByName(fstmt->portalname);
405  Assert(PortalIsValid(subportal));
406  return FetchPortalTargetList(subportal);
407  }
408  if (IsA(stmt, ExecuteStmt))
409  {
410  ExecuteStmt *estmt = (ExecuteStmt *) stmt;
411  PreparedStatement *entry;
412 
413  entry = FetchPreparedStatement(estmt->name, true);
414  return FetchPreparedStatementTargetList(entry);
415  }
416  return NIL;
417 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
Node * utilityStmt
Definition: parsenodes.h:120
struct Plan * planTree
Definition: plannodes.h:64
List * targetList
Definition: parsenodes.h:140
bool hasReturning
Definition: plannodes.h:50
Node * utilityStmt
Definition: plannodes.h:90
List * returningList
Definition: parsenodes.h:146
char * portalname
Definition: parsenodes.h:2734
#define PortalIsValid(p)
Definition: portal.h:201
bool ismove
Definition: parsenodes.h:2735
CmdType commandType
Definition: plannodes.h:46
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:540
CmdType commandType
Definition: parsenodes.h:112
#define Assert(condition)
Definition: c.h:732
List * targetlist
Definition: plannodes.h:140
char * name
Definition: parsenodes.h:3401
List * FetchPortalTargetList(Portal portal)
Definition: pquery.c:336
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:485

◆ PortalRun()

bool PortalRun ( Portal  portal,
long  count,
bool  isTopLevel,
bool  run_once,
DestReceiver dest,
DestReceiver altdest,
char *  completionTag 
)

Definition at line 686 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, PortalData::portalContext, PortalIsValid, PortalRunMulti(), PortalRunSelect(), ResetUsage(), PortalData::resowner, PortalData::run_once, ShowUsage(), snprintf, PortalData::status, PortalData::strategy, TopTransactionContext, TopTransactionResourceOwner, and UINT64_FORMAT.

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

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

◆ PortalRunFetch()

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

Definition at line 1392 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, PortalData::portalContext, PortalIsValid, PortalData::resowner, PortalData::run_once, PortalData::status, and PortalData::strategy.

Referenced by _SPI_cursor_operation(), and PerformPortalFetch().

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

◆ PortalSetResultFormat()

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

Definition at line 624 of file pquery.c.

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

Referenced by exec_bind_message(), and exec_simple_query().

625 {
626  int natts;
627  int i;
628 
629  /* Do nothing if portal won't return tuples */
630  if (portal->tupDesc == NULL)
631  return;
632  natts = portal->tupDesc->natts;
633  portal->formats = (int16 *)
635  natts * sizeof(int16));
636  if (nFormats > 1)
637  {
638  /* format specified for each column */
639  if (nFormats != natts)
640  ereport(ERROR,
641  (errcode(ERRCODE_PROTOCOL_VIOLATION),
642  errmsg("bind message has %d result formats but query has %d columns",
643  nFormats, natts)));
644  memcpy(portal->formats, formats, natts * sizeof(int16));
645  }
646  else if (nFormats > 0)
647  {
648  /* single format specified, use for all columns */
649  int16 format1 = formats[0];
650 
651  for (i = 0; i < natts; i++)
652  portal->formats[i] = format1;
653  }
654  else
655  {
656  /* use default format for all columns */
657  for (i = 0; i < natts; i++)
658  portal->formats[i] = 0;
659  }
660 }
signed short int16
Definition: c.h:345
int errcode(int sqlerrcode)
Definition: elog.c:570
MemoryContext portalContext
Definition: portal.h:119
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
int16 * formats
Definition: portal.h:159
TupleDesc tupDesc
Definition: portal.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:784
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
int i

◆ PortalStart()

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

Definition at line 443 of file pquery.c.

References ActivePortal, Assert, AssertArg, AssertState, PortalData::atEnd, PortalData::atStart, ChoosePortalStrategy(), CMD_UTILITY, PlannedStmt::commandType, CreateQueryDesc(), CurrentResourceOwner, CURSOR_OPT_SCROLL, PortalData::cursorOptions, EXEC_FLAG_BACKWARD, EXEC_FLAG_REWIND, ExecCleanTypeFromTL(), ExecutorStart(), GetActiveSnapshot(), GetTransactionSnapshot(), InvalidSnapshot, linitial_node, MarkPortalFailed(), MemoryContextSwitchTo(), None_Receiver, 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, PortalData::portalContext, PortalGetPrimaryStmt(), PortalIsValid, PortalData::portalParams, PortalData::portalPos, PushActiveSnapshot(), PortalData::queryDesc, PortalData::queryEnv, PortalData::resowner, PortalData::sourceText, PortalData::status, PortalData::stmts, PortalData::strategy, Plan::targetlist, QueryDesc::tupDesc, PortalData::tupDesc, PlannedStmt::utilityStmt, and UtilityTupleDescriptor().

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

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

Variable Documentation

◆ ActivePortal