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, 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 210 of file pquery.c.

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

1773{
1774 Portal portal;
1775
1776 /*
1777 * Nothing to do if a snapshot is set. (We take it on faith that the
1778 * outermost active snapshot belongs to some Portal; or if there is no
1779 * Portal, it's somebody else's responsibility to manage things.)
1780 */
1781 if (ActiveSnapshotSet())
1782 return;
1783
1784 /* Otherwise, we'd better have an active Portal */
1785 portal = ActivePortal;
1786 if (unlikely(portal == NULL))
1787 elog(ERROR, "cannot execute SQL without an outer snapshot or portal");
1788 Assert(portal->portalSnapshot == NULL);
1789
1790 /*
1791 * Create a new snapshot, make it active, and remember it in portal.
1792 * Because the portal now references the snapshot, we must tell snapmgr.c
1793 * that the snapshot belongs to the portal's transaction level, else we
1794 * risk portalSnapshot becoming a dangling pointer.
1795 */
1797 /* PushActiveSnapshotWithLevel might have copied the snapshot */
1799}
#define unlikely(x)
Definition: c.h:347
Assert(PointerIsAligned(start, uint64))
Portal ActivePortal
Definition: pquery.c:36
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:169
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 327 of file pquery.c.

328{
329 /* no point in looking if we determined it doesn't return tuples */
330 if (portal->strategy == PORTAL_MULTI_QUERY)
331 return NIL;
332 /* get the primary statement and find out what it returns */
334}
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
Definition: portalmem.c:151
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:349
PortalStrategy strategy
Definition: portal.h:146

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 349 of file pquery.c.

350{
351 if (stmt == NULL)
352 return NIL;
353 if (IsA(stmt, Query))
354 {
355 Query *query = (Query *) stmt;
356
357 if (query->commandType == CMD_UTILITY)
358 {
359 /* transfer attention to utility statement */
360 stmt = query->utilityStmt;
361 }
362 else
363 {
364 if (query->commandType == CMD_SELECT)
365 return query->targetList;
366 if (query->returningList)
367 return query->returningList;
368 return NIL;
369 }
370 }
371 if (IsA(stmt, PlannedStmt))
372 {
373 PlannedStmt *pstmt = (PlannedStmt *) stmt;
374
375 if (pstmt->commandType == CMD_UTILITY)
376 {
377 /* transfer attention to utility statement */
378 stmt = pstmt->utilityStmt;
379 }
380 else
381 {
382 if (pstmt->commandType == CMD_SELECT)
383 return pstmt->planTree->targetlist;
384 if (pstmt->hasReturning)
385 return pstmt->planTree->targetlist;
386 return NIL;
387 }
388 }
389 if (IsA(stmt, FetchStmt))
390 {
391 FetchStmt *fstmt = (FetchStmt *) stmt;
392 Portal subportal;
393
394 Assert(!fstmt->ismove);
395 subportal = GetPortalByName(fstmt->portalname);
396 Assert(PortalIsValid(subportal));
397 return FetchPortalTargetList(subportal);
398 }
399 if (IsA(stmt, ExecuteStmt))
400 {
401 ExecuteStmt *estmt = (ExecuteStmt *) stmt;
402 PreparedStatement *entry;
403
404 entry = FetchPreparedStatement(estmt->name, true);
406 }
407 return NIL;
408}
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:434
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:489
#define PortalIsValid(p)
Definition: portal.h:211
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
List * FetchPortalTargetList(Portal portal)
Definition: pquery.c:327
char * name
Definition: parsenodes.h:4143
bool ismove
Definition: parsenodes.h:3428
char * portalname
Definition: parsenodes.h:3427
List * targetlist
Definition: plannodes.h:202
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 1724 of file pquery.c.

1725{
1726 Node *utilityStmt = pstmt->utilityStmt;
1727
1728 /* If it's not a utility statement, it definitely needs a snapshot */
1729 if (utilityStmt == NULL)
1730 return true;
1731
1732 /*
1733 * Most utility statements need a snapshot, and the default presumption
1734 * about new ones should be that they do too. Hence, enumerate those that
1735 * do not need one.
1736 *
1737 * Transaction control, LOCK, and SET must *not* set a snapshot, since
1738 * they need to be executable at the start of a transaction-snapshot-mode
1739 * transaction without freezing a snapshot. By extension we allow SHOW
1740 * not to set a snapshot. The other stmts listed are just efficiency
1741 * hacks. Beware of listing anything that can modify the database --- if,
1742 * say, it has to update an index with expressions that invoke
1743 * user-defined functions, then it had better have a snapshot.
1744 */
1745 if (IsA(utilityStmt, TransactionStmt) ||
1746 IsA(utilityStmt, LockStmt) ||
1747 IsA(utilityStmt, VariableSetStmt) ||
1748 IsA(utilityStmt, VariableShowStmt) ||
1749 IsA(utilityStmt, ConstraintsSetStmt) ||
1750 /* efficiency hacks from here down */
1751 IsA(utilityStmt, FetchStmt) ||
1752 IsA(utilityStmt, ListenStmt) ||
1753 IsA(utilityStmt, NotifyStmt) ||
1754 IsA(utilityStmt, UnlistenStmt) ||
1755 IsA(utilityStmt, CheckPointStmt))
1756 return false;
1757
1758 return true;
1759}

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 685 of file pquery.c.

688{
689 bool result;
690 uint64 nprocessed;
691 ResourceOwner saveTopTransactionResourceOwner;
692 MemoryContext saveTopTransactionContext;
693 Portal saveActivePortal;
694 ResourceOwner saveResourceOwner;
695 MemoryContext savePortalContext;
696 MemoryContext saveMemoryContext;
697
698 Assert(PortalIsValid(portal));
699
700 TRACE_POSTGRESQL_QUERY_EXECUTE_START();
701
702 /* Initialize empty completion data */
703 if (qc)
705
707 {
708 elog(DEBUG3, "PortalRun");
709 /* PORTAL_MULTI_QUERY logs its own stats per query */
710 ResetUsage();
711 }
712
713 /*
714 * Check for improper portal use, and mark portal active.
715 */
716 MarkPortalActive(portal);
717
718 /*
719 * Set up global portal context pointers.
720 *
721 * We have to play a special game here to support utility commands like
722 * VACUUM and CLUSTER, which internally start and commit transactions.
723 * When we are called to execute such a command, CurrentResourceOwner will
724 * be pointing to the TopTransactionResourceOwner --- which will be
725 * destroyed and replaced in the course of the internal commit and
726 * restart. So we need to be prepared to restore it as pointing to the
727 * exit-time TopTransactionResourceOwner. (Ain't that ugly? This idea of
728 * internally starting whole new transactions is not good.)
729 * CurrentMemoryContext has a similar problem, but the other pointers we
730 * save here will be NULL or pointing to longer-lived objects.
731 */
732 saveTopTransactionResourceOwner = TopTransactionResourceOwner;
733 saveTopTransactionContext = TopTransactionContext;
734 saveActivePortal = ActivePortal;
735 saveResourceOwner = CurrentResourceOwner;
736 savePortalContext = PortalContext;
737 saveMemoryContext = CurrentMemoryContext;
738 PG_TRY();
739 {
740 ActivePortal = portal;
741 if (portal->resowner)
744
746
747 switch (portal->strategy)
748 {
753
754 /*
755 * If we have not yet run the command, do so, storing its
756 * results in the portal's tuplestore. But we don't do that
757 * for the PORTAL_ONE_SELECT case.
758 */
759 if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
760 FillPortalStore(portal, isTopLevel);
761
762 /*
763 * Now fetch desired portion of results.
764 */
765 nprocessed = PortalRunSelect(portal, true, count, dest);
766
767 /*
768 * If the portal result contains a command tag and the caller
769 * gave us a pointer to store it, copy it and update the
770 * rowcount.
771 */
772 if (qc && portal->qc.commandTag != CMDTAG_UNKNOWN)
773 {
774 CopyQueryCompletion(qc, &portal->qc);
775 qc->nprocessed = nprocessed;
776 }
777
778 /* Mark portal not active */
779 portal->status = PORTAL_READY;
780
781 /*
782 * Since it's a forward fetch, say DONE iff atEnd is now true.
783 */
784 result = portal->atEnd;
785 break;
786
788 PortalRunMulti(portal, isTopLevel, false,
789 dest, altdest, qc);
790
791 /* Prevent portal's commands from being re-executed */
792 MarkPortalDone(portal);
793
794 /* Always complete at end of RunMulti */
795 result = true;
796 break;
797
798 default:
799 elog(ERROR, "unrecognized portal strategy: %d",
800 (int) portal->strategy);
801 result = false; /* keep compiler quiet */
802 break;
803 }
804 }
805 PG_CATCH();
806 {
807 /* Uncaught error while executing portal: mark it dead */
808 MarkPortalFailed(portal);
809
810 /* Restore global vars and propagate error */
811 if (saveMemoryContext == saveTopTransactionContext)
813 else
814 MemoryContextSwitchTo(saveMemoryContext);
815 ActivePortal = saveActivePortal;
816 if (saveResourceOwner == saveTopTransactionResourceOwner)
818 else
819 CurrentResourceOwner = saveResourceOwner;
820 PortalContext = savePortalContext;
821
822 PG_RE_THROW();
823 }
824 PG_END_TRY();
825
826 if (saveMemoryContext == saveTopTransactionContext)
828 else
829 MemoryContextSwitchTo(saveMemoryContext);
830 ActivePortal = saveActivePortal;
831 if (saveResourceOwner == saveTopTransactionResourceOwner)
833 else
834 CurrentResourceOwner = saveResourceOwner;
835 PortalContext = savePortalContext;
836
838 ShowUsage("EXECUTOR STATISTICS");
839
840 TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
841
842 return result;
843}
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:404
#define DEBUG3
Definition: elog.h:28
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define PG_CATCH(...)
Definition: elog.h:381
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:414
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:442
void MarkPortalActive(Portal portal)
Definition: portalmem.c:395
void ShowUsage(const char *title)
Definition: postgres.c:5062
void ResetUsage(void)
Definition: postgres.c:5055
static void PortalRunMulti(Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
Definition: pquery.c:1185
static void FillPortalStore(Portal portal, bool isTopLevel)
Definition: pquery.c:995
static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest)
Definition: pquery.c:864
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:175
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
bool atEnd
Definition: portal.h:199
ResourceOwner resowner
Definition: portal.h:121
QueryCompletion qc
Definition: portal.h:138
MemoryContext portalContext
Definition: portal.h:120
Tuplestorestate * holdStore
Definition: portal.h:176
PortalStatus status
Definition: portal.h:150
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 1386 of file pquery.c.

1390{
1391 uint64 result;
1392 Portal saveActivePortal;
1393 ResourceOwner saveResourceOwner;
1394 MemoryContext savePortalContext;
1395 MemoryContext oldContext;
1396
1397 Assert(PortalIsValid(portal));
1398
1399 /*
1400 * Check for improper portal use, and mark portal active.
1401 */
1402 MarkPortalActive(portal);
1403
1404 /*
1405 * Set up global portal context pointers.
1406 */
1407 saveActivePortal = ActivePortal;
1408 saveResourceOwner = CurrentResourceOwner;
1409 savePortalContext = PortalContext;
1410 PG_TRY();
1411 {
1412 ActivePortal = portal;
1413 if (portal->resowner)
1415 PortalContext = portal->portalContext;
1416
1418
1419 switch (portal->strategy)
1420 {
1421 case PORTAL_ONE_SELECT:
1422 result = DoPortalRunFetch(portal, fdirection, count, dest);
1423 break;
1424
1427 case PORTAL_UTIL_SELECT:
1428
1429 /*
1430 * If we have not yet run the command, do so, storing its
1431 * results in the portal's tuplestore.
1432 */
1433 if (!portal->holdStore)
1434 FillPortalStore(portal, false /* isTopLevel */ );
1435
1436 /*
1437 * Now fetch desired portion of results.
1438 */
1439 result = DoPortalRunFetch(portal, fdirection, count, dest);
1440 break;
1441
1442 default:
1443 elog(ERROR, "unsupported portal strategy");
1444 result = 0; /* keep compiler quiet */
1445 break;
1446 }
1447 }
1448 PG_CATCH();
1449 {
1450 /* Uncaught error while executing portal: mark it dead */
1451 MarkPortalFailed(portal);
1452
1453 /* Restore global vars and propagate error */
1454 ActivePortal = saveActivePortal;
1455 CurrentResourceOwner = saveResourceOwner;
1456 PortalContext = savePortalContext;
1457
1458 PG_RE_THROW();
1459 }
1460 PG_END_TRY();
1461
1462 MemoryContextSwitchTo(oldContext);
1463
1464 /* Mark portal not active */
1465 portal->status = PORTAL_READY;
1466
1467 ActivePortal = saveActivePortal;
1468 CurrentResourceOwner = saveResourceOwner;
1469 PortalContext = savePortalContext;
1470
1471 return result;
1472}
static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1484

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 624 of file pquery.c.

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)
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}
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:1260
int16 * formats
Definition: portal.h:161
TupleDesc tupDesc
Definition: portal.h:159

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 434 of file pquery.c.

436{
437 Portal saveActivePortal;
438 ResourceOwner saveResourceOwner;
439 MemoryContext savePortalContext;
440 MemoryContext oldContext;
441 QueryDesc *queryDesc;
442 int myeflags;
443
444 Assert(PortalIsValid(portal));
445 Assert(portal->status == PORTAL_DEFINED);
446
447 /*
448 * Set up global portal context pointers.
449 */
450 saveActivePortal = ActivePortal;
451 saveResourceOwner = CurrentResourceOwner;
452 savePortalContext = PortalContext;
453 PG_TRY();
454 {
455 ActivePortal = portal;
456 if (portal->resowner)
459
461
462 /* Must remember portal param list, if any */
463 portal->portalParams = params;
464
465 /*
466 * Determine the portal execution strategy
467 */
468 portal->strategy = ChoosePortalStrategy(portal->stmts);
469
470 /*
471 * Fire her up according to the strategy
472 */
473 switch (portal->strategy)
474 {
476
477 /* Must set snapshot before starting executor. */
478 if (snapshot)
479 PushActiveSnapshot(snapshot);
480 else
482
483 /*
484 * We could remember the snapshot in portal->portalSnapshot,
485 * but presently there seems no need to, as this code path
486 * cannot be used for non-atomic execution. Hence there can't
487 * be any commit/abort that might destroy the snapshot. Since
488 * we don't do that, there's also no need to force a
489 * non-default nesting level for the snapshot.
490 */
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
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
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);
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
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}
DestReceiver * None_Receiver
Definition: dest.c:96
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:123
TupleDesc ExecCleanTypeFromTL(List *targetList)
Definition: execTuples.c:2139
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
#define EXEC_FLAG_REWIND
Definition: executor.h:67
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3376
#define linitial_node(type, l)
Definition: pg_list.h:181
@ PORTAL_DEFINED
Definition: portal.h:106
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:68
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:210
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:669
void PopActiveSnapshot(void)
Definition: snapmgr.c:762
#define InvalidSnapshot
Definition: snapshot.h:119
uint64 portalPos
Definition: portal.h:200
QueryDesc * queryDesc
Definition: portal.h:156
const char * sourceText
Definition: portal.h:136
bool atStart
Definition: portal.h:198
List * stmts
Definition: portal.h:139
QueryEnvironment * queryEnv
Definition: portal.h:143
ParamListInfo portalParams
Definition: portal.h:142
int cursorOptions
Definition: portal.h:147
TupleDesc tupDesc
Definition: execdesc.h:47
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:2084

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

Variable Documentation

◆ ActivePortal