PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
 
uint64 PortalRunFetch (Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
 
bool PlannedStmtRequiresSnapshot (struct PlannedStmt *pstmt)
 
void EnsurePortalSnapshotExists (void)
 

Variables

PGDLLIMPORT Portal ActivePortal
 

Function Documentation

◆ ChoosePortalStrategy()

PortalStrategy ChoosePortalStrategy ( List stmts)

Definition at line 231 of file pquery.c.

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

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

Referenced by PlanCacheComputeResultDesc(), and PortalStart().

◆ EnsurePortalSnapshotExists()

void EnsurePortalSnapshotExists ( void  )

Definition at line 1813 of file pquery.c.

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

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

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

◆ FetchPortalTargetList()

List * FetchPortalTargetList ( Portal  portal)

Definition at line 348 of file pquery.c.

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

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

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

◆ FetchStatementTargetList()

List * FetchStatementTargetList ( Node stmt)

Definition at line 370 of file pquery.c.

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

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

Referenced by CachedPlanGetTargetList(), and FetchPortalTargetList().

◆ PlannedStmtRequiresSnapshot()

bool PlannedStmtRequiresSnapshot ( struct PlannedStmt pstmt)

Definition at line 1765 of file pquery.c.

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

References IsA, and PlannedStmt::utilityStmt.

Referenced by _SPI_execute_plan(), and PortalRunUtility().

◆ PortalRun()

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

Definition at line 717 of file pquery.c.

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

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

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

◆ PortalRunFetch()

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

Definition at line 1427 of file pquery.c.

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

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

Referenced by _SPI_cursor_operation(), and PerformPortalFetch().

◆ PortalSetResultFormat()

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

Definition at line 656 of file pquery.c.

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

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

Referenced by exec_bind_message(), and exec_simple_query().

◆ PortalStart()

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

Definition at line 455 of file pquery.c.

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

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

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

Variable Documentation

◆ ActivePortal