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.

Typedefs

typedef struct PlannedStmt PlannedStmt
 

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 (PlannedStmt *pstmt)
 
void EnsurePortalSnapshotExists (void)
 

Variables

PGDLLIMPORT Portal ActivePortal
 

Typedef Documentation

◆ PlannedStmt

typedef struct PlannedStmt PlannedStmt

Definition at line 20 of file pquery.h.

Function Documentation

◆ ChoosePortalStrategy()

PortalStrategy ChoosePortalStrategy ( List stmts)

Definition at line 205 of file pquery.c.

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

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

1759{
1760 Portal portal;
1761
1762 /*
1763 * Nothing to do if a snapshot is set. (We take it on faith that the
1764 * outermost active snapshot belongs to some Portal; or if there is no
1765 * Portal, it's somebody else's responsibility to manage things.)
1766 */
1767 if (ActiveSnapshotSet())
1768 return;
1769
1770 /* Otherwise, we'd better have an active Portal */
1771 portal = ActivePortal;
1772 if (unlikely(portal == NULL))
1773 elog(ERROR, "cannot execute SQL without an outer snapshot or portal");
1774 Assert(portal->portalSnapshot == NULL);
1775
1776 /*
1777 * Create a new snapshot, make it active, and remember it in portal.
1778 * Because the portal now references the snapshot, we must tell snapmgr.c
1779 * that the snapshot belongs to the portal's transaction level, else we
1780 * risk portalSnapshot becoming a dangling pointer.
1781 */
1783 /* PushActiveSnapshotWithLevel might have copied the snapshot */
1785}
#define unlikely(x)
Definition: c.h:406
Assert(PointerIsAligned(start, uint64))
Portal ActivePortal
Definition: pquery.c:36
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:271
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:810
void PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level)
Definition: snapmgr.c:694
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:798
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 322 of file pquery.c.

323{
324 /* no point in looking if we determined it doesn't return tuples */
325 if (portal->strategy == PORTAL_MULTI_QUERY)
326 return NIL;
327 /* get the primary statement and find out what it returns */
329}
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
Definition: portalmem.c:151
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:344
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 344 of file pquery.c.

345{
346 if (stmt == NULL)
347 return NIL;
348 if (IsA(stmt, Query))
349 {
350 Query *query = (Query *) stmt;
351
352 if (query->commandType == CMD_UTILITY)
353 {
354 /* transfer attention to utility statement */
355 stmt = query->utilityStmt;
356 }
357 else
358 {
359 if (query->commandType == CMD_SELECT)
360 return query->targetList;
361 if (query->returningList)
362 return query->returningList;
363 return NIL;
364 }
365 }
366 if (IsA(stmt, PlannedStmt))
367 {
368 PlannedStmt *pstmt = (PlannedStmt *) stmt;
369
370 if (pstmt->commandType == CMD_UTILITY)
371 {
372 /* transfer attention to utility statement */
373 stmt = pstmt->utilityStmt;
374 }
375 else
376 {
377 if (pstmt->commandType == CMD_SELECT)
378 return pstmt->planTree->targetlist;
379 if (pstmt->hasReturning)
380 return pstmt->planTree->targetlist;
381 return NIL;
382 }
383 }
384 if (IsA(stmt, FetchStmt))
385 {
386 FetchStmt *fstmt = (FetchStmt *) stmt;
387 Portal subportal;
388
389 Assert(!fstmt->ismove);
390 subportal = GetPortalByName(fstmt->portalname);
391 Assert(PortalIsValid(subportal));
392 return FetchPortalTargetList(subportal);
393 }
394 if (IsA(stmt, ExecuteStmt))
395 {
396 ExecuteStmt *estmt = (ExecuteStmt *) stmt;
397 PreparedStatement *entry;
398
399 entry = FetchPreparedStatement(estmt->name, true);
401 }
402 return NIL;
403}
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:322
char * name
Definition: parsenodes.h:4184
bool ismove
Definition: parsenodes.h:3458
char * portalname
Definition: parsenodes.h:3456
List * targetlist
Definition: plannodes.h:229
struct Plan * planTree
Definition: plannodes.h:101
List * targetList
Definition: parsenodes.h:198

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 ( PlannedStmt pstmt)

Definition at line 1710 of file pquery.c.

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

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

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

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

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

620{
621 int natts;
622 int i;
623
624 /* Do nothing if portal won't return tuples */
625 if (portal->tupDesc == NULL)
626 return;
627 natts = portal->tupDesc->natts;
628 portal->formats = (int16 *)
630 natts * sizeof(int16));
631 if (nFormats > 1)
632 {
633 /* format specified for each column */
634 if (nFormats != natts)
636 (errcode(ERRCODE_PROTOCOL_VIOLATION),
637 errmsg("bind message has %d result formats but query has %d columns",
638 nFormats, natts)));
639 memcpy(portal->formats, formats, natts * sizeof(int16));
640 }
641 else if (nFormats > 0)
642 {
643 /* single format specified, use for all columns */
644 int16 format1 = formats[0];
645
646 for (i = 0; i < natts; i++)
647 portal->formats[i] = format1;
648 }
649 else
650 {
651 /* use default format for all columns */
652 for (i = 0; i < natts; i++)
653 portal->formats[i] = 0;
654 }
655}
int16_t int16
Definition: c.h:537
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereport(elevel,...)
Definition: elog.h:150
int i
Definition: isn.c:77
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
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 429 of file pquery.c.

431{
432 Portal saveActivePortal;
433 ResourceOwner saveResourceOwner;
434 MemoryContext savePortalContext;
435 MemoryContext oldContext;
436 QueryDesc *queryDesc;
437 int myeflags;
438
439 Assert(PortalIsValid(portal));
440 Assert(portal->status == PORTAL_DEFINED);
441
442 /*
443 * Set up global portal context pointers.
444 */
445 saveActivePortal = ActivePortal;
446 saveResourceOwner = CurrentResourceOwner;
447 savePortalContext = PortalContext;
448 PG_TRY();
449 {
450 ActivePortal = portal;
451 if (portal->resowner)
454
456
457 /* Must remember portal param list, if any */
458 portal->portalParams = params;
459
460 /*
461 * Determine the portal execution strategy
462 */
463 portal->strategy = ChoosePortalStrategy(portal->stmts);
464
465 /*
466 * Fire her up according to the strategy
467 */
468 switch (portal->strategy)
469 {
471
472 /* Must set snapshot before starting executor. */
473 if (snapshot)
474 PushActiveSnapshot(snapshot);
475 else
477
478 /*
479 * We could remember the snapshot in portal->portalSnapshot,
480 * but presently there seems no need to, as this code path
481 * cannot be used for non-atomic execution. Hence there can't
482 * be any commit/abort that might destroy the snapshot. Since
483 * we don't do that, there's also no need to force a
484 * non-default nesting level for the snapshot.
485 */
486
487 /*
488 * Create QueryDesc in portal's context; for the moment, set
489 * the destination to DestNone.
490 */
491 queryDesc = CreateQueryDesc(linitial_node(PlannedStmt, portal->stmts),
492 portal->sourceText,
496 params,
497 portal->queryEnv,
498 0);
499
500 /*
501 * If it's a scrollable cursor, executor needs to support
502 * REWIND and backwards scan, as well as whatever the caller
503 * might've asked for.
504 */
505 if (portal->cursorOptions & CURSOR_OPT_SCROLL)
506 myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
507 else
508 myeflags = eflags;
509
510 /*
511 * Call ExecutorStart to prepare the plan for execution
512 */
513 ExecutorStart(queryDesc, myeflags);
514
515 /*
516 * This tells PortalCleanup to shut down the executor
517 */
518 portal->queryDesc = queryDesc;
519
520 /*
521 * Remember tuple descriptor (computed by ExecutorStart)
522 */
523 portal->tupDesc = queryDesc->tupDesc;
524
525 /*
526 * Reset cursor position data to "start of query"
527 */
528 portal->atStart = true;
529 portal->atEnd = false; /* allow fetches */
530 portal->portalPos = 0;
531
533 break;
534
537
538 /*
539 * We don't start the executor until we are told to run the
540 * portal. We do need to set up the result tupdesc.
541 */
542 {
543 PlannedStmt *pstmt;
544
545 pstmt = PortalGetPrimaryStmt(portal);
546 portal->tupDesc =
548 }
549
550 /*
551 * Reset cursor position data to "start of query"
552 */
553 portal->atStart = true;
554 portal->atEnd = false; /* allow fetches */
555 portal->portalPos = 0;
556 break;
557
559
560 /*
561 * We don't set snapshot here, because PortalRunUtility will
562 * take care of it if needed.
563 */
564 {
565 PlannedStmt *pstmt = PortalGetPrimaryStmt(portal);
566
567 Assert(pstmt->commandType == CMD_UTILITY);
569 }
570
571 /*
572 * Reset cursor position data to "start of query"
573 */
574 portal->atStart = true;
575 portal->atEnd = false; /* allow fetches */
576 portal->portalPos = 0;
577 break;
578
580 /* Need do nothing now */
581 portal->tupDesc = NULL;
582 break;
583 }
584 }
585 PG_CATCH();
586 {
587 /* Uncaught error while executing portal: mark it dead */
588 MarkPortalFailed(portal);
589
590 /* Restore global vars and propagate error */
591 ActivePortal = saveActivePortal;
592 CurrentResourceOwner = saveResourceOwner;
593 PortalContext = savePortalContext;
594
595 PG_RE_THROW();
596 }
597 PG_END_TRY();
598
599 MemoryContextSwitchTo(oldContext);
600
601 ActivePortal = saveActivePortal;
602 CurrentResourceOwner = saveResourceOwner;
603 PortalContext = savePortalContext;
604
605 portal->status = PORTAL_READY;
606}
DestReceiver * None_Receiver
Definition: dest.c:96
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:122
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:3387
#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:205
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:680
void PopActiveSnapshot(void)
Definition: snapmgr.c:773
#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:2076

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