codekingpro/portable-devtools
114k
1/*-------------------------------------------------------------------------2 *3 * portal.h4 * POSTGRES portal definitions.5 *6 * A portal is an abstraction which represents the execution state of7 * a running or runnable query. Portals support both SQL-level CURSORs8 * and protocol-level portals.9 *10 * Scrolling (nonsequential access) and suspension of execution are allowed11 * only for portals that contain a single SELECT-type query. We do not want12 * to let the client suspend an update-type query partway through! Because13 * the query rewriter does not allow arbitrary ON SELECT rewrite rules,14 * only queries that were originally update-type could produce multiple15 * plan trees; so the restriction to a single query is not a problem16 * in practice.17 *18 * For SQL cursors, we support three kinds of scroll behavior:19 *20 * (1) Neither NO SCROLL nor SCROLL was specified: to remain backward21 * compatible, we allow backward fetches here, unless it would22 * impose additional runtime overhead to do so.23 *24 * (2) NO SCROLL was specified: don't allow any backward fetches.25 *26 * (3) SCROLL was specified: allow all kinds of backward fetches, even27 * if we need to take a performance hit to do so. (The planner sticks28 * a Materialize node atop the query plan if needed.)29 *30 * Case #1 is converted to #2 or #3 by looking at the query itself and31 * determining if scrollability can be supported without additional32 * overhead.33 *34 * Protocol-level portals have no nonsequential-fetch API and so the35 * distinction doesn't matter for them. They are always initialized36 * to look like NO SCROLL cursors.37 *38 *39 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group40 * Portions Copyright (c) 1994, Regents of the University of California41 *42 * src/include/utils/portal.h43 *44 *-------------------------------------------------------------------------45 */46#ifndef PORTAL_H47#define PORTAL_H48 49#include "datatype/timestamp.h"50#include "executor/execdesc.h"51#include "tcop/cmdtag.h"52#include "utils/plancache.h"53#include "utils/resowner.h"54 55/*56 * We have several execution strategies for Portals, depending on what57 * query or queries are to be executed. (Note: in all cases, a Portal58 * executes just a single source-SQL query, and thus produces just a59 * single result from the user's viewpoint. However, the rule rewriter60 * may expand the single source query to zero or many actual queries.)61 *62 * PORTAL_ONE_SELECT: the portal contains one single SELECT query. We run63 * the Executor incrementally as results are demanded. This strategy also64 * supports holdable cursors (the Executor results can be dumped into a65 * tuplestore for access after transaction completion).66 *67 * PORTAL_ONE_RETURNING: the portal contains a single INSERT/UPDATE/DELETE68 * query with a RETURNING clause (plus possibly auxiliary queries added by69 * rule rewriting). On first execution, we run the portal to completion70 * and dump the primary query's results into the portal tuplestore; the71 * results are then returned to the client as demanded. (We can't support72 * suspension of the query partway through, because the AFTER TRIGGER code73 * can't cope, and also because we don't want to risk failing to execute74 * all the auxiliary queries.)75 *76 * PORTAL_ONE_MOD_WITH: the portal contains one single SELECT query, but77 * it has data-modifying CTEs. This is currently treated the same as the78 * PORTAL_ONE_RETURNING case because of the possibility of needing to fire79 * triggers. It may act more like PORTAL_ONE_SELECT in future.80 *81 * PORTAL_UTIL_SELECT: the portal contains a utility statement that returns82 * a SELECT-like result (for example, EXPLAIN or SHOW). On first execution,83 * we run the statement and dump its results into the portal tuplestore;84 * the results are then returned to the client as demanded.85 *86 * PORTAL_MULTI_QUERY: all other cases. Here, we do not support partial87 * execution: the portal's queries will be run to completion on first call.88 */89typedef enum PortalStrategy90{91 PORTAL_ONE_SELECT,92 PORTAL_ONE_RETURNING,93 PORTAL_ONE_MOD_WITH,94 PORTAL_UTIL_SELECT,95 PORTAL_MULTI_QUERY96} PortalStrategy;97 98/*99 * A portal is always in one of these states. It is possible to transit100 * from ACTIVE back to READY if the query is not run to completion;101 * otherwise we never back up in status.102 */103typedef enum PortalStatus104{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) */111} PortalStatus;112 113typedef struct PortalData *Portal;114 115typedef struct PortalData116{117 /* Bookkeeping data */118 const char *name; /* portal's name */119 const char *prepStmtName; /* source prepared statement (NULL if none) */120 MemoryContext portalContext; /* subsidiary memory for portal */121 ResourceOwner resowner; /* resources owned by portal */122 void (*cleanup) (Portal portal); /* cleanup hook */123 124 /*125 * State data for remembering which subtransaction(s) the portal was126 * created or used in. If the portal is held over from a previous127 * transaction, both subxids are InvalidSubTransactionId. Otherwise,128 * createSubid is the creating subxact and activeSubid is the last subxact129 * in which we ran the portal.130 */131 SubTransactionId createSubid; /* the creating subxact */132 SubTransactionId activeSubid; /* the last subxact with activity */133 int createLevel; /* creating subxact's nesting level */134 135 /* The query or queries the portal will execute */136 const char *sourceText; /* text of query (as of 8.4, never NULL) */137 CommandTag commandTag; /* command tag for original query */138 QueryCompletion qc; /* command completion data for executed query */139 List *stmts; /* list of PlannedStmts */140 CachedPlan *cplan; /* CachedPlan, if stmts are from one */141 142 ParamListInfo portalParams; /* params to pass to query */143 QueryEnvironment *queryEnv; /* environment for query */144 145 /* Features/options */146 PortalStrategy strategy; /* see above */147 int cursorOptions; /* DECLARE CURSOR option bits */148 bool run_once; /* portal will only be run once */149 150 /* Status data */151 PortalStatus status; /* see above */152 bool portalPinned; /* a pinned portal can't be dropped */153 bool autoHeld; /* was automatically converted from pinned to154 * held (see HoldPinnedPortals()) */155 156 /* If not NULL, Executor is active; call ExecutorEnd eventually: */157 QueryDesc *queryDesc; /* info needed for executor invocation */158 159 /* If portal returns tuples, this is their tupdesc: */160 TupleDesc tupDesc; /* descriptor for result tuples */161 /* and these are the format codes to use for the columns: */162 int16 *formats; /* a format code for each column */163 164 /*165 * Outermost ActiveSnapshot for execution of the portal's queries. For166 * all but a few utility commands, we require such a snapshot to exist.167 * This ensures that TOAST references in query results can be detoasted,168 * and helps to reduce thrashing of the process's exposed xmin.169 */170 Snapshot portalSnapshot; /* active snapshot, or NULL if none */171 172 /*173 * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or174 * PORTAL_UTIL_SELECT query. (A cursor held past the end of its175 * transaction no longer has any active executor state.)176 */177 Tuplestorestate *holdStore; /* store for holdable cursors */178 MemoryContext holdContext; /* memory containing holdStore */179 180 /*181 * Snapshot under which tuples in the holdStore were read. We must keep a182 * reference to this snapshot if there is any possibility that the tuples183 * contain TOAST references, because releasing the snapshot could allow184 * recently-dead rows to be vacuumed away, along with any toast data185 * belonging to them. In the case of a held cursor, we avoid needing to186 * keep such a snapshot by forcibly detoasting the data.187 */188 Snapshot holdSnapshot; /* registered snapshot, or NULL if none */189 190 /*191 * atStart, atEnd and portalPos indicate the current cursor position.192 * portalPos is zero before the first row, N after fetching N'th row of193 * query. After we run off the end, portalPos = # of rows in query, and194 * atEnd is true. Note that atStart implies portalPos == 0, but not the195 * reverse: we might have backed up only as far as the first row, not to196 * the start. Also note that various code inspects atStart and atEnd, but197 * only the portal movement routines should touch portalPos.198 */199 bool atStart;200 bool atEnd;201 uint64 portalPos;202 203 /* Presentation data, primarily used by the pg_cursors system view */204 TimestampTz creation_time; /* time at which this portal was defined */205 bool visible; /* include this portal in pg_cursors? */206} PortalData;207 208/*209 * PortalIsValid210 * True iff portal is valid.211 */212#define PortalIsValid(p) PointerIsValid(p)213 214 215/* Prototypes for functions in utils/mmgr/portalmem.c */216extern void EnablePortalManager(void);217extern bool PreCommit_Portals(bool isPrepare);218extern void AtAbort_Portals(void);219extern void AtCleanup_Portals(void);220extern void PortalErrorCleanup(void);221extern void AtSubCommit_Portals(SubTransactionId mySubid,222 SubTransactionId parentSubid,223 int parentLevel,224 ResourceOwner parentXactOwner);225extern void AtSubAbort_Portals(SubTransactionId mySubid,226 SubTransactionId parentSubid,227 ResourceOwner myXactOwner,228 ResourceOwner parentXactOwner);229extern void AtSubCleanup_Portals(SubTransactionId mySubid);230extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent);231extern Portal CreateNewPortal(void);232extern void PinPortal(Portal portal);233extern void UnpinPortal(Portal portal);234extern void MarkPortalActive(Portal portal);235extern void MarkPortalDone(Portal portal);236extern void MarkPortalFailed(Portal portal);237extern void PortalDrop(Portal portal, bool isTopCommit);238extern Portal GetPortalByName(const char *name);239extern void PortalDefineQuery(Portal portal,240 const char *prepStmtName,241 const char *sourceText,242 CommandTag commandTag,243 List *stmts,244 CachedPlan *cplan);245extern PlannedStmt *PortalGetPrimaryStmt(Portal portal);246extern void PortalCreateHoldStore(Portal portal);247extern void PortalHashTableDeleteAll(void);248extern bool ThereAreNoReadyPortals(void);249extern void HoldPinnedPortals(void);250extern void ForgetPortalSnapshots(void);251 252#endif /* PORTAL_H */253 