PostgreSQL Source Code git master
Loading...
Searching...
No Matches
portal.h File Reference
#include "datatype/timestamp.h"
#include "executor/execdesc.h"
#include "tcop/cmdtag.h"
#include "utils/plancache.h"
#include "utils/resowner.h"
Include dependency graph for portal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PortalData
 

Macros

#define PortalIsValid(p)   ((p) != NULL)
 

Typedefs

typedef enum PortalStrategy PortalStrategy
 
typedef enum PortalStatus PortalStatus
 
typedef struct PortalDataPortal
 
typedef struct PortalData PortalData
 

Enumerations

enum  PortalStrategy {
  PORTAL_ONE_SELECT , PORTAL_ONE_RETURNING , PORTAL_ONE_MOD_WITH , PORTAL_UTIL_SELECT ,
  PORTAL_MULTI_QUERY
}
 
enum  PortalStatus {
  PORTAL_NEW , PORTAL_DEFINED , PORTAL_READY , PORTAL_ACTIVE ,
  PORTAL_DONE , PORTAL_FAILED
}
 

Functions

void EnablePortalManager (void)
 
bool PreCommit_Portals (bool isPrepare)
 
void AtAbort_Portals (void)
 
void AtCleanup_Portals (void)
 
void PortalErrorCleanup (void)
 
void AtSubCommit_Portals (SubTransactionId mySubid, SubTransactionId parentSubid, int parentLevel, ResourceOwner parentXactOwner)
 
void AtSubAbort_Portals (SubTransactionId mySubid, SubTransactionId parentSubid, ResourceOwner myXactOwner, ResourceOwner parentXactOwner)
 
void AtSubCleanup_Portals (SubTransactionId mySubid)
 
Portal CreatePortal (const char *name, bool allowDup, bool dupSilent)
 
Portal CreateNewPortal (void)
 
void PinPortal (Portal portal)
 
void UnpinPortal (Portal portal)
 
void MarkPortalActive (Portal portal)
 
void MarkPortalDone (Portal portal)
 
void MarkPortalFailed (Portal portal)
 
void PortalDrop (Portal portal, bool isTopCommit)
 
Portal GetPortalByName (const char *name)
 
void PortalDefineQuery (Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)
 
PlannedStmtPortalGetPrimaryStmt (Portal portal)
 
void PortalCreateHoldStore (Portal portal)
 
void PortalHashTableDeleteAll (void)
 
bool ThereAreNoReadyPortals (void)
 
void HoldPinnedPortals (void)
 
void ForgetPortalSnapshots (void)
 

Macro Definition Documentation

◆ PortalIsValid

#define PortalIsValid (   p)    ((p) != NULL)

Definition at line 211 of file portal.h.

Typedef Documentation

◆ Portal

Definition at line 113 of file portal.h.

◆ PortalData

◆ PortalStatus

◆ PortalStrategy

Enumeration Type Documentation

◆ PortalStatus

Enumerator
PORTAL_NEW 
PORTAL_DEFINED 
PORTAL_READY 
PORTAL_ACTIVE 
PORTAL_DONE 
PORTAL_FAILED 

Definition at line 103 of file portal.h.

104{
105 PORTAL_NEW, /* freshly created */
106 PORTAL_DEFINED, /* PortalDefineQuery done */
107 PORTAL_READY, /* PortalStart complete, can run it */
108 PORTAL_ACTIVE, /* portal is running (can't delete it) */
109 PORTAL_DONE, /* portal is finished (don't re-run it) */
110 PORTAL_FAILED, /* portal got error (can't re-run it) */
PortalStatus
Definition portal.h:104
@ PORTAL_FAILED
Definition portal.h:110
@ PORTAL_NEW
Definition portal.h:105
@ PORTAL_ACTIVE
Definition portal.h:108
@ PORTAL_DONE
Definition portal.h:109
@ PORTAL_READY
Definition portal.h:107
@ PORTAL_DEFINED
Definition portal.h:106

◆ PortalStrategy

Enumerator
PORTAL_ONE_SELECT 
PORTAL_ONE_RETURNING 
PORTAL_ONE_MOD_WITH 
PORTAL_UTIL_SELECT 
PORTAL_MULTI_QUERY 

Definition at line 89 of file portal.h.

90{
PortalStrategy
Definition portal.h:90
@ 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

Function Documentation

◆ AtAbort_Portals()

void AtAbort_Portals ( void  )
extern

Definition at line 780 of file portalmem.c.

781{
782 HASH_SEQ_STATUS status;
784
786
787 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
788 {
789 Portal portal = hentry->portal;
790
791 /*
792 * When elog(FATAL) is progress, we need to set the active portal to
793 * failed, so that PortalCleanup() doesn't run the executor shutdown.
794 */
796 MarkPortalFailed(portal);
797
798 /*
799 * Do nothing else to cursors held over from a previous transaction.
800 */
802 continue;
803
804 /*
805 * Do nothing to auto-held cursors. This is similar to the case of a
806 * cursor from a previous transaction, but it could also be that the
807 * cursor was auto-held in this transaction, so it wants to live on.
808 */
809 if (portal->autoHeld)
810 continue;
811
812 /*
813 * If it was created in the current transaction, we can't do normal
814 * shutdown on a READY portal either; it might refer to objects
815 * created in the failed transaction. See comments in
816 * AtSubAbort_Portals.
817 */
818 if (portal->status == PORTAL_READY)
819 MarkPortalFailed(portal);
820
821 /*
822 * Allow portalcmds.c to clean up the state it knows about, if we
823 * haven't already.
824 */
825 if (portal->cleanup)
826 {
827 portal->cleanup(portal);
828 portal->cleanup = NULL;
829 }
830
831 /* drop cached plan reference, if any */
833
834 /*
835 * Any resources belonging to the portal will be released in the
836 * upcoming transaction-wide cleanup; they will be gone before we run
837 * PortalDrop.
838 */
839 portal->resowner = NULL;
840
841 /*
842 * Although we can't delete the portal data structure proper, we can
843 * release any memory in subsidiary contexts, such as executor state.
844 * The cleanup hook was the last thing that might have needed data
845 * there. But leave active portals alone.
846 */
847 if (portal->status != PORTAL_ACTIVE)
849 }
850}
#define InvalidSubTransactionId
Definition c.h:672
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
bool shmem_exit_inprogress
Definition ipc.c:46
void MemoryContextDeleteChildren(MemoryContext context)
Definition mcxt.c:555
static HTAB * PortalHashTable
Definition portalmem.c:54
void MarkPortalFailed(Portal portal)
Definition portalmem.c:441
static void PortalReleaseCachedPlan(Portal portal)
Definition portalmem.c:309
static int fb(int x)
SubTransactionId createSubid
Definition portal.h:131
ResourceOwner resowner
Definition portal.h:121
bool autoHeld
Definition portal.h:152
MemoryContext portalContext
Definition portal.h:120
void(* cleanup)(Portal portal)
Definition portal.h:122
PortalStatus status
Definition portal.h:150

References PortalData::autoHeld, PortalData::cleanup, PortalData::createSubid, fb(), hash_seq_init(), hash_seq_search(), InvalidSubTransactionId, MarkPortalFailed(), MemoryContextDeleteChildren(), PORTAL_ACTIVE, PORTAL_READY, PortalData::portalContext, PortalHashTable, PortalReleaseCachedPlan(), PortalData::resowner, shmem_exit_inprogress, and PortalData::status.

Referenced by AbortOutOfAnyTransaction(), and AbortTransaction().

◆ AtCleanup_Portals()

void AtCleanup_Portals ( void  )
extern

Definition at line 858 of file portalmem.c.

859{
860 HASH_SEQ_STATUS status;
862
864
865 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
866 {
867 Portal portal = hentry->portal;
868
869 /*
870 * Do not touch active portals --- this can only happen in the case of
871 * a multi-transaction command.
872 */
873 if (portal->status == PORTAL_ACTIVE)
874 continue;
875
876 /*
877 * Do nothing to cursors held over from a previous transaction or
878 * auto-held ones.
879 */
880 if (portal->createSubid == InvalidSubTransactionId || portal->autoHeld)
881 {
882 Assert(portal->status != PORTAL_ACTIVE);
883 Assert(portal->resowner == NULL);
884 continue;
885 }
886
887 /*
888 * If a portal is still pinned, forcibly unpin it. PortalDrop will not
889 * let us drop the portal otherwise. Whoever pinned the portal was
890 * interrupted by the abort too and won't try to use it anymore.
891 */
892 if (portal->portalPinned)
893 portal->portalPinned = false;
894
895 /*
896 * We had better not call any user-defined code during cleanup, so if
897 * the cleanup hook hasn't been run yet, too bad; we'll just skip it.
898 */
899 if (portal->cleanup)
900 {
901 elog(WARNING, "skipping cleanup for portal \"%s\"", portal->name);
902 portal->cleanup = NULL;
903 }
904
905 /* Zap it. */
906 PortalDrop(portal, false);
907 }
908}
#define Assert(condition)
Definition c.h:873
#define WARNING
Definition elog.h:36
#define elog(elevel,...)
Definition elog.h:226
void PortalDrop(Portal portal, bool isTopCommit)
Definition portalmem.c:467
bool portalPinned
Definition portal.h:151
const char * name
Definition portal.h:118

References Assert, PortalData::autoHeld, PortalData::cleanup, PortalData::createSubid, elog, fb(), hash_seq_init(), hash_seq_search(), InvalidSubTransactionId, PortalData::name, PORTAL_ACTIVE, PortalDrop(), PortalHashTable, PortalData::portalPinned, PortalData::resowner, PortalData::status, and WARNING.

Referenced by CleanupTransaction().

◆ AtSubAbort_Portals()

void AtSubAbort_Portals ( SubTransactionId  mySubid,
SubTransactionId  parentSubid,
ResourceOwner  myXactOwner,
ResourceOwner  parentXactOwner 
)
extern

Definition at line 979 of file portalmem.c.

983{
984 HASH_SEQ_STATUS status;
986
988
989 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
990 {
991 Portal portal = hentry->portal;
992
993 /* Was it created in this subtransaction? */
994 if (portal->createSubid != mySubid)
995 {
996 /* No, but maybe it was used in this subtransaction? */
997 if (portal->activeSubid == mySubid)
998 {
999 /* Maintain activeSubid until the portal is removed */
1000 portal->activeSubid = parentSubid;
1001
1002 /*
1003 * A MarkPortalActive() caller ran an upper-level portal in
1004 * this subtransaction and left the portal ACTIVE. This can't
1005 * happen, but force the portal into FAILED state for the same
1006 * reasons discussed below.
1007 *
1008 * We assume we can get away without forcing upper-level READY
1009 * portals to fail, even if they were run and then suspended.
1010 * In theory a suspended upper-level portal could have
1011 * acquired some references to objects that are about to be
1012 * destroyed, but there should be sufficient defenses against
1013 * such cases: the portal's original query cannot contain such
1014 * references, and any references within, say, cached plans of
1015 * PL/pgSQL functions are not from active queries and should
1016 * be protected by revalidation logic.
1017 */
1018 if (portal->status == PORTAL_ACTIVE)
1019 MarkPortalFailed(portal);
1020
1021 /*
1022 * Also, if we failed it during the current subtransaction
1023 * (either just above, or earlier), reattach its resource
1024 * owner to the current subtransaction's resource owner, so
1025 * that any resources it still holds will be released while
1026 * cleaning up this subtransaction. This prevents some corner
1027 * cases wherein we might get Asserts or worse while cleaning
1028 * up objects created during the current subtransaction
1029 * (because they're still referenced within this portal).
1030 */
1031 if (portal->status == PORTAL_FAILED && portal->resowner)
1032 {
1034 portal->resowner = NULL;
1035 }
1036 }
1037 /* Done if it wasn't created in this subtransaction */
1038 continue;
1039 }
1040
1041 /*
1042 * Force any live portals of my own subtransaction into FAILED state.
1043 * We have to do this because they might refer to objects created or
1044 * changed in the failed subtransaction, leading to crashes within
1045 * ExecutorEnd when portalcmds.c tries to close down the portal.
1046 * Currently, every MarkPortalActive() caller ensures it updates the
1047 * portal status again before relinquishing control, so ACTIVE can't
1048 * happen here. If it does happen, dispose the portal like existing
1049 * MarkPortalActive() callers would.
1050 */
1051 if (portal->status == PORTAL_READY ||
1052 portal->status == PORTAL_ACTIVE)
1053 MarkPortalFailed(portal);
1054
1055 /*
1056 * Allow portalcmds.c to clean up the state it knows about, if we
1057 * haven't already.
1058 */
1059 if (portal->cleanup)
1060 {
1061 portal->cleanup(portal);
1062 portal->cleanup = NULL;
1063 }
1064
1065 /* drop cached plan reference, if any */
1067
1068 /*
1069 * Any resources belonging to the portal will be released in the
1070 * upcoming transaction-wide cleanup; they will be gone before we run
1071 * PortalDrop.
1072 */
1073 portal->resowner = NULL;
1074
1075 /*
1076 * Although we can't delete the portal data structure proper, we can
1077 * release any memory in subsidiary contexts, such as executor state.
1078 * The cleanup hook was the last thing that might have needed data
1079 * there.
1080 */
1082 }
1083}
void ResourceOwnerNewParent(ResourceOwner owner, ResourceOwner newparent)
Definition resowner.c:911
SubTransactionId activeSubid
Definition portal.h:132

References PortalData::activeSubid, PortalData::cleanup, PortalData::createSubid, fb(), hash_seq_init(), hash_seq_search(), MarkPortalFailed(), MemoryContextDeleteChildren(), PORTAL_ACTIVE, PORTAL_FAILED, PORTAL_READY, PortalData::portalContext, PortalHashTable, PortalReleaseCachedPlan(), ResourceOwnerNewParent(), PortalData::resowner, and PortalData::status.

Referenced by AbortOutOfAnyTransaction(), and AbortSubTransaction().

◆ AtSubCleanup_Portals()

void AtSubCleanup_Portals ( SubTransactionId  mySubid)
extern

Definition at line 1092 of file portalmem.c.

1093{
1094 HASH_SEQ_STATUS status;
1096
1098
1099 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
1100 {
1101 Portal portal = hentry->portal;
1102
1103 if (portal->createSubid != mySubid)
1104 continue;
1105
1106 /*
1107 * If a portal is still pinned, forcibly unpin it. PortalDrop will not
1108 * let us drop the portal otherwise. Whoever pinned the portal was
1109 * interrupted by the abort too and won't try to use it anymore.
1110 */
1111 if (portal->portalPinned)
1112 portal->portalPinned = false;
1113
1114 /*
1115 * We had better not call any user-defined code during cleanup, so if
1116 * the cleanup hook hasn't been run yet, too bad; we'll just skip it.
1117 */
1118 if (portal->cleanup)
1119 {
1120 elog(WARNING, "skipping cleanup for portal \"%s\"", portal->name);
1121 portal->cleanup = NULL;
1122 }
1123
1124 /* Zap it. */
1125 PortalDrop(portal, false);
1126 }
1127}

References PortalData::cleanup, PortalData::createSubid, elog, fb(), hash_seq_init(), hash_seq_search(), PortalData::name, PortalDrop(), PortalHashTable, PortalData::portalPinned, and WARNING.

Referenced by CleanupSubTransaction().

◆ AtSubCommit_Portals()

void AtSubCommit_Portals ( SubTransactionId  mySubid,
SubTransactionId  parentSubid,
int  parentLevel,
ResourceOwner  parentXactOwner 
)
extern

Definition at line 943 of file portalmem.c.

947{
948 HASH_SEQ_STATUS status;
950
952
953 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
954 {
955 Portal portal = hentry->portal;
956
957 if (portal->createSubid == mySubid)
958 {
959 portal->createSubid = parentSubid;
960 portal->createLevel = parentLevel;
961 if (portal->resowner)
963 }
964 if (portal->activeSubid == mySubid)
965 portal->activeSubid = parentSubid;
966 }
967}
int createLevel
Definition portal.h:133

References PortalData::activeSubid, PortalData::createLevel, PortalData::createSubid, fb(), hash_seq_init(), hash_seq_search(), PortalHashTable, ResourceOwnerNewParent(), and PortalData::resowner.

Referenced by CommitSubTransaction().

◆ CreateNewPortal()

Portal CreateNewPortal ( void  )
extern

Definition at line 235 of file portalmem.c.

236{
237 static unsigned int unnamed_portal_count = 0;
238
239 char portalname[MAX_PORTALNAME_LEN];
240
241 /* Select a nonconflicting name */
242 for (;;)
243 {
245 sprintf(portalname, "<unnamed portal %u>", unnamed_portal_count);
246 if (GetPortalByName(portalname) == NULL)
247 break;
248 }
249
250 return CreatePortal(portalname, false, false);
251}
#define sprintf
Definition port.h:262
#define MAX_PORTALNAME_LEN
Definition portalmem.c:46
Portal GetPortalByName(const char *name)
Definition portalmem.c:130
Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)
Definition portalmem.c:175

References CreatePortal(), fb(), GetPortalByName(), MAX_PORTALNAME_LEN, and sprintf.

Referenced by ExecuteQuery(), and SPI_cursor_open_internal().

◆ CreatePortal()

Portal CreatePortal ( const char name,
bool  allowDup,
bool  dupSilent 
)
extern

Definition at line 175 of file portalmem.c.

176{
177 Portal portal;
178
179 Assert(name);
180
181 portal = GetPortalByName(name);
182 if (PortalIsValid(portal))
183 {
184 if (!allowDup)
187 errmsg("cursor \"%s\" already exists", name)));
188 if (!dupSilent)
191 errmsg("closing existing cursor \"%s\"",
192 name)));
193 PortalDrop(portal, false);
194 }
195
196 /* make new portal structure */
197 portal = (Portal) MemoryContextAllocZero(TopPortalContext, sizeof *portal);
198
199 /* initialize portal context; typically it won't store much */
201 "PortalContext",
203
204 /* create a resource owner for the portal */
206 "Portal");
207
208 /* initialize portal fields that don't start off zero */
209 portal->status = PORTAL_NEW;
210 portal->cleanup = PortalCleanup;
212 portal->activeSubid = portal->createSubid;
216 portal->atStart = true;
217 portal->atEnd = true; /* disallow fetches until query is set */
218 portal->visible = true;
220
221 /* put portal in table (sets portal->name) */
223
224 /* for named portals reuse portal->name copy */
225 MemoryContextSetIdentifier(portal->portalContext, portal->name[0] ? portal->name : "<unnamed>");
226
227 return portal;
228}
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1266
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition mcxt.c:661
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
#define CURSOR_OPT_NO_SCROLL
struct PortalData * Portal
Definition portal.h:113
#define PortalIsValid(p)
Definition portal.h:211
void PortalCleanup(Portal portal)
Definition portalcmds.c:274
#define PortalHashTableInsert(PORTAL, NAME)
Definition portalmem.c:68
static MemoryContext TopPortalContext
Definition portalmem.c:91
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
Definition resowner.c:418
ResourceOwner CurTransactionResourceOwner
Definition resowner.c:174
bool atEnd
Definition portal.h:199
bool atStart
Definition portal.h:198
TimestampTz creation_time
Definition portal.h:203
bool visible
Definition portal.h:204
int cursorOptions
Definition portal.h:147
PortalStrategy strategy
Definition portal.h:146
const char * name
SubTransactionId GetCurrentSubTransactionId(void)
Definition xact.c:792
int GetCurrentTransactionNestLevel(void)
Definition xact.c:930
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition xact.c:880

References PortalData::activeSubid, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, PortalData::atEnd, PortalData::atStart, PortalData::cleanup, PortalData::createLevel, PortalData::createSubid, PortalData::creation_time, CURSOR_OPT_NO_SCROLL, PortalData::cursorOptions, CurTransactionResourceOwner, ereport, errcode(), errmsg(), ERROR, fb(), GetCurrentStatementStartTimestamp(), GetCurrentSubTransactionId(), GetCurrentTransactionNestLevel(), GetPortalByName(), MemoryContextAllocZero(), MemoryContextSetIdentifier(), name, PortalData::name, PORTAL_MULTI_QUERY, PORTAL_NEW, PortalCleanup(), PortalData::portalContext, PortalDrop(), PortalHashTableInsert, PortalIsValid, ResourceOwnerCreate(), PortalData::resowner, PortalData::status, PortalData::strategy, TopPortalContext, PortalData::visible, and WARNING.

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

◆ EnablePortalManager()

void EnablePortalManager ( void  )
extern

Definition at line 104 of file portalmem.c.

105{
106 HASHCTL ctl;
107
109
111 "TopPortalContext",
113
114 ctl.keysize = MAX_PORTALNAME_LEN;
115 ctl.entrysize = sizeof(PortalHashEnt);
116
117 /*
118 * use PORTALS_PER_USER as a guess of how many hash table entries to
119 * create, initially
120 */
123}
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
#define HASH_STRINGS
Definition hsearch.h:96
#define HASH_ELEM
Definition hsearch.h:95
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
struct portalhashent PortalHashEnt
#define PORTALS_PER_USER
Definition portalmem.c:38
tree ctl
Definition radixtree.h:1838

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, ctl, fb(), hash_create(), HASH_ELEM, HASH_STRINGS, MAX_PORTALNAME_LEN, PortalHashTable, PORTALS_PER_USER, TopMemoryContext, and TopPortalContext.

Referenced by InitPostgres().

◆ ForgetPortalSnapshots()

void ForgetPortalSnapshots ( void  )
extern

Definition at line 1256 of file portalmem.c.

1257{
1258 HASH_SEQ_STATUS status;
1260 int numPortalSnaps = 0;
1261 int numActiveSnaps = 0;
1262
1263 /* First, scan PortalHashTable and clear portalSnapshot fields */
1265
1266 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
1267 {
1268 Portal portal = hentry->portal;
1269
1270 if (portal->portalSnapshot != NULL)
1271 {
1272 portal->portalSnapshot = NULL;
1274 }
1275 /* portal->holdSnapshot will be cleaned up in PreCommit_Portals */
1276 }
1277
1278 /*
1279 * Now, pop all the active snapshots, which should be just those that were
1280 * portal snapshots. Ideally we'd drive this directly off the portal
1281 * scan, but there's no good way to visit the portals in the correct
1282 * order. So just cross-check after the fact.
1283 */
1284 while (ActiveSnapshotSet())
1285 {
1288 }
1289
1291 elog(ERROR, "portal snapshots (%d) did not account for all active snapshots (%d)",
1293}
bool ActiveSnapshotSet(void)
Definition snapmgr.c:812
void PopActiveSnapshot(void)
Definition snapmgr.c:775
Snapshot portalSnapshot
Definition portal.h:169

References ActiveSnapshotSet(), elog, ERROR, fb(), hash_seq_init(), hash_seq_search(), PopActiveSnapshot(), PortalHashTable, and PortalData::portalSnapshot.

Referenced by _SPI_commit(), and _SPI_rollback().

◆ GetPortalByName()

◆ HoldPinnedPortals()

void HoldPinnedPortals ( void  )
extern

Definition at line 1207 of file portalmem.c.

1208{
1209 HASH_SEQ_STATUS status;
1211
1213
1214 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
1215 {
1216 Portal portal = hentry->portal;
1217
1218 if (portal->portalPinned && !portal->autoHeld)
1219 {
1220 /*
1221 * Doing transaction control, especially abort, inside a cursor
1222 * loop that is not read-only, for example using UPDATE ...
1223 * RETURNING, has weird semantics issues. Also, this
1224 * implementation wouldn't work, because such portals cannot be
1225 * held. (The core grammar enforces that only SELECT statements
1226 * can drive a cursor, but for example PL/pgSQL does not restrict
1227 * it.)
1228 */
1229 if (portal->strategy != PORTAL_ONE_SELECT)
1230 ereport(ERROR,
1232 errmsg("cannot perform transaction commands inside a cursor loop that is not read-only")));
1233
1234 /* Verify it's in a suitable state to be held */
1235 if (portal->status != PORTAL_READY)
1236 elog(ERROR, "pinned portal is not ready to be auto-held");
1237
1238 HoldPortal(portal);
1239 portal->autoHeld = true;
1240 }
1241 }
1242}
static void HoldPortal(Portal portal)
Definition portalmem.c:635

References PortalData::autoHeld, elog, ereport, errcode(), errmsg(), ERROR, fb(), hash_seq_init(), hash_seq_search(), HoldPortal(), PORTAL_ONE_SELECT, PORTAL_READY, PortalHashTable, PortalData::portalPinned, PortalData::status, and PortalData::strategy.

Referenced by _SPI_commit(), and _SPI_rollback().

◆ MarkPortalActive()

void MarkPortalActive ( Portal  portal)
extern

Definition at line 394 of file portalmem.c.

395{
396 /* For safety, this is a runtime test not just an Assert */
397 if (portal->status != PORTAL_READY)
400 errmsg("portal \"%s\" cannot be run", portal->name)));
401 /* Perform the state transition */
402 portal->status = PORTAL_ACTIVE;
404}

References PortalData::activeSubid, ereport, errcode(), errmsg(), ERROR, fb(), GetCurrentSubTransactionId(), PortalData::name, PORTAL_ACTIVE, PORTAL_READY, and PortalData::status.

Referenced by PersistHoldablePortal(), PortalRun(), and PortalRunFetch().

◆ MarkPortalDone()

void MarkPortalDone ( Portal  portal)
extern

Definition at line 413 of file portalmem.c.

414{
415 /* Perform the state transition */
416 Assert(portal->status == PORTAL_ACTIVE);
417 portal->status = PORTAL_DONE;
418
419 /*
420 * Allow portalcmds.c to clean up the state it knows about. We might as
421 * well do that now, since the portal can't be executed any more.
422 *
423 * In some cases involving execution of a ROLLBACK command in an already
424 * aborted transaction, this is necessary, or we'd reach AtCleanup_Portals
425 * with the cleanup hook still unexecuted.
426 */
427 if (portal->cleanup)
428 {
429 portal->cleanup(portal);
430 portal->cleanup = NULL;
431 }
432}

References Assert, PortalData::cleanup, fb(), PORTAL_ACTIVE, PORTAL_DONE, and PortalData::status.

Referenced by PortalRun().

◆ MarkPortalFailed()

void MarkPortalFailed ( Portal  portal)
extern

Definition at line 441 of file portalmem.c.

442{
443 /* Perform the state transition */
444 Assert(portal->status != PORTAL_DONE);
445 portal->status = PORTAL_FAILED;
446
447 /*
448 * Allow portalcmds.c to clean up the state it knows about. We might as
449 * well do that now, since the portal can't be executed any more.
450 *
451 * In some cases involving cleanup of an already aborted transaction, this
452 * is necessary, or we'd reach AtCleanup_Portals with the cleanup hook
453 * still unexecuted.
454 */
455 if (portal->cleanup)
456 {
457 portal->cleanup(portal);
458 portal->cleanup = NULL;
459 }
460}

References Assert, PortalData::cleanup, fb(), PORTAL_DONE, PORTAL_FAILED, and PortalData::status.

Referenced by AtAbort_Portals(), AtSubAbort_Portals(), PersistHoldablePortal(), PortalRun(), PortalRunFetch(), and PortalStart().

◆ PinPortal()

void PinPortal ( Portal  portal)
extern

Definition at line 370 of file portalmem.c.

371{
372 if (portal->portalPinned)
373 elog(ERROR, "portal already pinned");
374
375 portal->portalPinned = true;
376}

References elog, ERROR, and PortalData::portalPinned.

Referenced by exec_for_query(), plperl_spi_query(), plperl_spi_query_prepared(), PLy_cursor_plan(), and PLy_cursor_query().

◆ PortalCreateHoldStore()

void PortalCreateHoldStore ( Portal  portal)
extern

Definition at line 330 of file portalmem.c.

331{
333
334 Assert(portal->holdContext == NULL);
335 Assert(portal->holdStore == NULL);
336 Assert(portal->holdSnapshot == NULL);
337
338 /*
339 * Create the memory context that is used for storage of the tuple set.
340 * Note this is NOT a child of the portal's portalContext.
341 */
342 portal->holdContext =
344 "PortalHoldContext",
346
347 /*
348 * Create the tuple store, selecting cross-transaction temp files, and
349 * enabling random access only if cursor requires scrolling.
350 *
351 * XXX: Should maintenance_work_mem be used for the portal size?
352 */
354
355 portal->holdStore =
357 true, work_mem);
358
360}
int work_mem
Definition globals.c:131
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define CURSOR_OPT_SCROLL
MemoryContext holdContext
Definition portal.h:177
Snapshot holdSnapshot
Definition portal.h:187
Tuplestorestate * holdStore
Definition portal.h:176
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition tuplestore.c:330

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CURSOR_OPT_SCROLL, PortalData::cursorOptions, fb(), PortalData::holdContext, PortalData::holdSnapshot, PortalData::holdStore, MemoryContextSwitchTo(), TopPortalContext, tuplestore_begin_heap(), and work_mem.

Referenced by FillPortalStore(), and HoldPortal().

◆ PortalDefineQuery()

void PortalDefineQuery ( Portal  portal,
const char prepStmtName,
const char sourceText,
CommandTag  commandTag,
List stmts,
CachedPlan cplan 
)
extern

Definition at line 282 of file portalmem.c.

288{
289 Assert(PortalIsValid(portal));
290 Assert(portal->status == PORTAL_NEW);
291
292 Assert(sourceText != NULL);
293 Assert(commandTag != CMDTAG_UNKNOWN || stmts == NIL);
294
295 portal->prepStmtName = prepStmtName;
296 portal->sourceText = sourceText;
297 portal->commandTag = commandTag;
298 SetQueryCompletion(&portal->qc, commandTag, 0);
299 portal->stmts = stmts;
300 portal->cplan = cplan;
301 portal->status = PORTAL_DEFINED;
302}
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
Definition cmdtag.h:37
#define NIL
Definition pg_list.h:68
CommandTag commandTag
Definition portal.h:137
const char * sourceText
Definition portal.h:136
List * stmts
Definition portal.h:139
QueryCompletion qc
Definition portal.h:138
const char * prepStmtName
Definition portal.h:119
CachedPlan * cplan
Definition portal.h:140

References Assert, PortalData::commandTag, PortalData::cplan, fb(), NIL, PORTAL_DEFINED, PORTAL_NEW, PortalIsValid, PortalData::prepStmtName, PortalData::qc, SetQueryCompletion(), PortalData::sourceText, PortalData::status, and PortalData::stmts.

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

◆ PortalDrop()

void PortalDrop ( Portal  portal,
bool  isTopCommit 
)
extern

Definition at line 467 of file portalmem.c.

468{
469 Assert(PortalIsValid(portal));
470
471 /*
472 * Don't allow dropping a pinned portal, it's still needed by whoever
473 * pinned it.
474 */
475 if (portal->portalPinned)
478 errmsg("cannot drop pinned portal \"%s\"", portal->name)));
479
480 /*
481 * Not sure if the PORTAL_ACTIVE case can validly happen or not...
482 */
483 if (portal->status == PORTAL_ACTIVE)
486 errmsg("cannot drop active portal \"%s\"", portal->name)));
487
488 /*
489 * Allow portalcmds.c to clean up the state it knows about, in particular
490 * shutting down the executor if still active. This step potentially runs
491 * user-defined code so failure has to be expected. It's the cleanup
492 * hook's responsibility to not try to do that more than once, in the case
493 * that failure occurs and then we come back to drop the portal again
494 * during transaction abort.
495 *
496 * Note: in most paths of control, this will have been done already in
497 * MarkPortalDone or MarkPortalFailed. We're just making sure.
498 */
499 if (portal->cleanup)
500 {
501 portal->cleanup(portal);
502 portal->cleanup = NULL;
503 }
504
505 /* There shouldn't be an active snapshot anymore, except after error */
506 Assert(portal->portalSnapshot == NULL || !isTopCommit);
507
508 /*
509 * Remove portal from hash table. Because we do this here, we will not
510 * come back to try to remove the portal again if there's any error in the
511 * subsequent steps. Better to leak a little memory than to get into an
512 * infinite error-recovery loop.
513 */
514 PortalHashTableDelete(portal);
515
516 /* drop cached plan reference, if any */
518
519 /*
520 * If portal has a snapshot protecting its data, release that. This needs
521 * a little care since the registration will be attached to the portal's
522 * resowner; if the portal failed, we will already have released the
523 * resowner (and the snapshot) during transaction abort.
524 */
525 if (portal->holdSnapshot)
526 {
527 if (portal->resowner)
529 portal->resowner);
530 portal->holdSnapshot = NULL;
531 }
532
533 /*
534 * Release any resources still attached to the portal. There are several
535 * cases being covered here:
536 *
537 * Top transaction commit (indicated by isTopCommit): normally we should
538 * do nothing here and let the regular end-of-transaction resource
539 * releasing mechanism handle these resources too. However, if we have a
540 * FAILED portal (eg, a cursor that got an error), we'd better clean up
541 * its resources to avoid resource-leakage warning messages.
542 *
543 * Sub transaction commit: never comes here at all, since we don't kill
544 * any portals in AtSubCommit_Portals().
545 *
546 * Main or sub transaction abort: we will do nothing here because
547 * portal->resowner was already set NULL; the resources were already
548 * cleaned up in transaction abort.
549 *
550 * Ordinary portal drop: must release resources. However, if the portal
551 * is not FAILED then we do not release its locks. The locks become the
552 * responsibility of the transaction's ResourceOwner (since it is the
553 * parent of the portal's owner) and will be released when the transaction
554 * eventually ends.
555 */
556 if (portal->resowner &&
557 (!isTopCommit || portal->status == PORTAL_FAILED))
558 {
559 bool isCommit = (portal->status != PORTAL_FAILED);
560
563 isCommit, false);
566 isCommit, false);
569 isCommit, false);
571 }
572 portal->resowner = NULL;
573
574 /*
575 * Delete tuplestore if present. We should do this even under error
576 * conditions; since the tuplestore would have been using cross-
577 * transaction storage, its temp files need to be explicitly deleted.
578 */
579 if (portal->holdStore)
580 {
581 MemoryContext oldcontext;
582
583 oldcontext = MemoryContextSwitchTo(portal->holdContext);
584 tuplestore_end(portal->holdStore);
585 MemoryContextSwitchTo(oldcontext);
586 portal->holdStore = NULL;
587 }
588
589 /* delete tuplestore storage, if any */
590 if (portal->holdContext)
592
593 /* release subsidiary storage */
595
596 /* release portal struct (it's in TopPortalContext) */
597 pfree(portal);
598}
void pfree(void *pointer)
Definition mcxt.c:1616
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define PortalHashTableDelete(PORTAL)
Definition portalmem.c:81
void ResourceOwnerRelease(ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
Definition resowner.c:655
void ResourceOwnerDelete(ResourceOwner owner)
Definition resowner.c:868
@ RESOURCE_RELEASE_LOCKS
Definition resowner.h:55
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition resowner.h:54
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition resowner.h:56
void UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner)
Definition snapmgr.c:879
void tuplestore_end(Tuplestorestate *state)
Definition tuplestore.c:492

References Assert, PortalData::cleanup, ereport, errcode(), errmsg(), ERROR, fb(), PortalData::holdContext, PortalData::holdSnapshot, PortalData::holdStore, MemoryContextDelete(), MemoryContextSwitchTo(), PortalData::name, pfree(), PORTAL_ACTIVE, PORTAL_FAILED, PortalData::portalContext, PortalHashTableDelete, PortalIsValid, PortalData::portalPinned, PortalReleaseCachedPlan(), PortalData::portalSnapshot, RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerDelete(), ResourceOwnerRelease(), PortalData::resowner, PortalData::status, tuplestore_end(), and UnregisterSnapshotFromOwner().

Referenced by AtCleanup_Portals(), AtSubCleanup_Portals(), CreatePortal(), exec_simple_query(), ExecuteQuery(), PerformPortalClose(), PortalErrorCleanup(), PortalHashTableDeleteAll(), PostgresMain(), PreCommit_Portals(), and SPI_cursor_close().

◆ PortalErrorCleanup()

void PortalErrorCleanup ( void  )
extern

Definition at line 917 of file portalmem.c.

918{
919 HASH_SEQ_STATUS status;
921
923
924 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
925 {
926 Portal portal = hentry->portal;
927
928 if (portal->autoHeld)
929 {
930 portal->portalPinned = false;
931 PortalDrop(portal, false);
932 }
933 }
934}

References PortalData::autoHeld, fb(), hash_seq_init(), hash_seq_search(), PortalDrop(), PortalHashTable, and PortalData::portalPinned.

Referenced by PostgresMain().

◆ PortalGetPrimaryStmt()

PlannedStmt * PortalGetPrimaryStmt ( Portal  portal)
extern

Definition at line 151 of file portalmem.c.

152{
153 ListCell *lc;
154
155 foreach(lc, portal->stmts)
156 {
158
159 if (stmt->canSetTag)
160 return stmt;
161 }
162 return NULL;
163}
#define stmt
#define lfirst_node(type, lc)
Definition pg_list.h:176

References fb(), lfirst_node, stmt, and PortalData::stmts.

Referenced by FetchPortalTargetList(), and PortalStart().

◆ PortalHashTableDeleteAll()

void PortalHashTableDeleteAll ( void  )
extern

Definition at line 606 of file portalmem.c.

607{
608 HASH_SEQ_STATUS status;
610
611 if (PortalHashTable == NULL)
612 return;
613
615 while ((hentry = hash_seq_search(&status)) != NULL)
616 {
617 Portal portal = hentry->portal;
618
619 /* Can't close the active portal (the one running the command) */
620 if (portal->status == PORTAL_ACTIVE)
621 continue;
622
623 PortalDrop(portal, false);
624
625 /* Restart the iteration in case that led to other drops */
626 hash_seq_term(&status);
628 }
629}
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition dynahash.c:1509

References fb(), hash_seq_init(), hash_seq_search(), hash_seq_term(), PORTAL_ACTIVE, PortalDrop(), PortalHashTable, and PortalData::status.

Referenced by DiscardAll(), and PerformPortalClose().

◆ PreCommit_Portals()

bool PreCommit_Portals ( bool  isPrepare)
extern

Definition at line 676 of file portalmem.c.

677{
678 bool result = false;
679 HASH_SEQ_STATUS status;
681
683
684 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
685 {
686 Portal portal = hentry->portal;
687
688 /*
689 * There should be no pinned portals anymore. Complain if someone
690 * leaked one. Auto-held portals are allowed; we assume that whoever
691 * pinned them is managing them.
692 */
693 if (portal->portalPinned && !portal->autoHeld)
694 elog(ERROR, "cannot commit while a portal is pinned");
695
696 /*
697 * Do not touch active portals --- this can only happen in the case of
698 * a multi-transaction utility command, such as VACUUM, or a commit in
699 * a procedure.
700 *
701 * Note however that any resource owner attached to such a portal is
702 * still going to go away, so don't leave a dangling pointer. Also
703 * unregister any snapshots held by the portal, mainly to avoid
704 * snapshot leak warnings from ResourceOwnerRelease().
705 */
706 if (portal->status == PORTAL_ACTIVE)
707 {
708 if (portal->holdSnapshot)
709 {
710 if (portal->resowner)
712 portal->resowner);
713 portal->holdSnapshot = NULL;
714 }
715 portal->resowner = NULL;
716 /* Clear portalSnapshot too, for cleanliness */
717 portal->portalSnapshot = NULL;
718 continue;
719 }
720
721 /* Is it a holdable portal created in the current xact? */
722 if ((portal->cursorOptions & CURSOR_OPT_HOLD) &&
724 portal->status == PORTAL_READY)
725 {
726 /*
727 * We are exiting the transaction that created a holdable cursor.
728 * Instead of dropping the portal, prepare it for access by later
729 * transactions.
730 *
731 * However, if this is PREPARE TRANSACTION rather than COMMIT,
732 * refuse PREPARE, because the semantics seem pretty unclear.
733 */
734 if (isPrepare)
737 errmsg("cannot PREPARE a transaction that has created a cursor WITH HOLD")));
738
739 HoldPortal(portal);
740
741 /* Report we changed state */
742 result = true;
743 }
744 else if (portal->createSubid == InvalidSubTransactionId)
745 {
746 /*
747 * Do nothing to cursors held over from a previous transaction
748 * (including ones we just froze in a previous cycle of this loop)
749 */
750 continue;
751 }
752 else
753 {
754 /* Zap all non-holdable portals */
755 PortalDrop(portal, true);
756
757 /* Report we changed state */
758 result = true;
759 }
760
761 /*
762 * After either freezing or dropping a portal, we have to restart the
763 * iteration, because we could have invoked user-defined code that
764 * caused a drop of the next portal in the hash chain.
765 */
766 hash_seq_term(&status);
768 }
769
770 return result;
771}
#define CURSOR_OPT_HOLD

References PortalData::autoHeld, PortalData::createSubid, CURSOR_OPT_HOLD, PortalData::cursorOptions, elog, ereport, errcode(), errmsg(), ERROR, fb(), hash_seq_init(), hash_seq_search(), hash_seq_term(), HoldPortal(), PortalData::holdSnapshot, InvalidSubTransactionId, PORTAL_ACTIVE, PORTAL_READY, PortalDrop(), PortalHashTable, PortalData::portalPinned, PortalData::portalSnapshot, PortalData::resowner, PortalData::status, and UnregisterSnapshotFromOwner().

Referenced by CommitTransaction(), and PrepareTransaction().

◆ ThereAreNoReadyPortals()

bool ThereAreNoReadyPortals ( void  )
extern

Definition at line 1171 of file portalmem.c.

1172{
1173 HASH_SEQ_STATUS status;
1175
1177
1178 while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
1179 {
1180 Portal portal = hentry->portal;
1181
1182 if (portal->status == PORTAL_READY)
1183 return false;
1184 }
1185
1186 return true;
1187}

References fb(), hash_seq_init(), hash_seq_search(), PORTAL_READY, PortalHashTable, and PortalData::status.

Referenced by CopyFrom().

◆ UnpinPortal()

void UnpinPortal ( Portal  portal)
extern

Definition at line 379 of file portalmem.c.

380{
381 if (!portal->portalPinned)
382 elog(ERROR, "portal not pinned");
383
384 portal->portalPinned = false;
385}

References elog, ERROR, and PortalData::portalPinned.

Referenced by exec_for_query(), plperl_spi_cursor_close(), plperl_spi_fetchrow(), PLy_cursor_close(), and PLy_cursor_dealloc().