1 /*------------------------------------------------------------------------- 2 * 3 * portal.h 4 * POSTGRES portal definitions. 5 * 6 * A portal is an abstraction which represents the execution state of 7 * a running or runnable query. Portals support both SQL-level CURSORs 8 * and protocol-level portals. 9 * 10 * Scrolling (nonsequential access) and suspension of execution are allowed 11 * only for portals that contain a single SELECT-type query. We do not want 12 * to let the client suspend an update-type query partway through! Because 13 * the query rewriter does not allow arbitrary ON SELECT rewrite rules, 14 * only queries that were originally update-type could produce multiple 15 * plan trees; so the restriction to a single query is not a problem 16 * 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 backward 21 * compatible, we allow backward fetches here, unless it would 22 * 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, even 27 * if we need to take a performance hit to do so. (The planner sticks 28 * 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 and 31 * determining if scrollability can be supported without additional 32 * overhead. 33 * 34 * Protocol-level portals have no nonsequential-fetch API and so the 35 * distinction doesn't matter for them. They are always initialized 36 * to look like NO SCROLL cursors. 37 * 38 * 39 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group 40 * Portions Copyright (c) 1994, Regents of the University of California 41 * 42 * src/include/utils/portal.h 43 * 44 *------------------------------------------------------------------------- 45 */ 46 #ifndef PORTAL_H 47 #define PORTAL_H 48 49 #include "datatype/timestamp.h" 50 #include "executor/execdesc.h" 51 #include "utils/plancache.h" 52 #include "utils/resowner.h" 53 54 /* 55 * We have several execution strategies for Portals, depending on what 56 * query or queries are to be executed. (Note: in all cases, a Portal 57 * executes just a single source-SQL query, and thus produces just a 58 * single result from the user's viewpoint. However, the rule rewriter 59 * may expand the single source query to zero or many actual queries.) 60 * 61 * PORTAL_ONE_SELECT: the portal contains one single SELECT query. We run 62 * the Executor incrementally as results are demanded. This strategy also 63 * supports holdable cursors (the Executor results can be dumped into a 64 * tuplestore for access after transaction completion). 65 * 66 * PORTAL_ONE_RETURNING: the portal contains a single INSERT/UPDATE/DELETE 67 * query with a RETURNING clause (plus possibly auxiliary queries added by 68 * rule rewriting). On first execution, we run the portal to completion 69 * and dump the primary query's results into the portal tuplestore; the 70 * results are then returned to the client as demanded. (We can't support 71 * suspension of the query partway through, because the AFTER TRIGGER code 72 * can't cope, and also because we don't want to risk failing to execute 73 * all the auxiliary queries.) 74 * 75 * PORTAL_ONE_MOD_WITH: the portal contains one single SELECT query, but 76 * it has data-modifying CTEs. This is currently treated the same as the 77 * PORTAL_ONE_RETURNING case because of the possibility of needing to fire 78 * triggers. It may act more like PORTAL_ONE_SELECT in future. 79 * 80 * PORTAL_UTIL_SELECT: the portal contains a utility statement that returns 81 * a SELECT-like result (for example, EXPLAIN or SHOW). On first execution, 82 * we run the statement and dump its results into the portal tuplestore; 83 * the results are then returned to the client as demanded. 84 * 85 * PORTAL_MULTI_QUERY: all other cases. Here, we do not support partial 86 * execution: the portal's queries will be run to completion on first call. 87 */ 88 typedef enum PortalStrategy 89 { 90 PORTAL_ONE_SELECT, 91 PORTAL_ONE_RETURNING, 92 PORTAL_ONE_MOD_WITH, 93 PORTAL_UTIL_SELECT, 94 PORTAL_MULTI_QUERY 95 } PortalStrategy; 96 97 /* 98 * A portal is always in one of these states. It is possible to transit 99 * from ACTIVE back to READY if the query is not run to completion; 100 * otherwise we never back up in status. 101 */ 102 typedef enum PortalStatus 103 { 104 PORTAL_NEW, /* freshly created */ 105 PORTAL_DEFINED, /* PortalDefineQuery done */ 106 PORTAL_READY, /* PortalStart complete, can run it */ 107 PORTAL_ACTIVE, /* portal is running (can't delete it) */ 108 PORTAL_DONE, /* portal is finished (don't re-run it) */ 109 PORTAL_FAILED /* portal got error (can't re-run it) */ 110 } PortalStatus; 111 112 typedef struct PortalData *Portal; 113 114 typedef struct PortalData 115 { 116 /* Bookkeeping data */ 117 const char *name; /* portal's name */ 118 const char *prepStmtName; /* source prepared statement (NULL if none) */ 119 MemoryContext heap; /* subsidiary memory for portal */ 120 ResourceOwner resowner; /* resources owned by portal */ 121 void (*cleanup) (Portal portal); /* cleanup hook */ 122 123 /* 124 * State data for remembering which subtransaction(s) the portal was 125 * created or used in. If the portal is held over from a previous 126 * transaction, both subxids are InvalidSubTransactionId. Otherwise, 127 * createSubid is the creating subxact and activeSubid is the last subxact 128 * in which we ran the portal. 129 */ 130 SubTransactionId createSubid; /* the creating subxact */ 131 SubTransactionId activeSubid; /* the last subxact with activity */ 132 133 /* The query or queries the portal will execute */ 134 const char *sourceText; /* text of query (as of 8.4, never NULL) */ 135 const char *commandTag; /* command tag for original query */ 136 List *stmts; /* list of PlannedStmts */ 137 CachedPlan *cplan; /* CachedPlan, if stmts are from one */ 138 139 ParamListInfo portalParams; /* params to pass to query */ 140 QueryEnvironment *queryEnv; /* environment for query */ 141 142 /* Features/options */ 143 PortalStrategy strategy; /* see above */ 144 int cursorOptions; /* DECLARE CURSOR option bits */ 145 bool run_once; /* portal will only be run once */ 146 147 /* Status data */ 148 PortalStatus status; /* see above */ 149 bool portalPinned; /* a pinned portal can't be dropped */ 150 151 /* If not NULL, Executor is active; call ExecutorEnd eventually: */ 152 QueryDesc *queryDesc; /* info needed for executor invocation */ 153 154 /* If portal returns tuples, this is their tupdesc: */ 155 TupleDesc tupDesc; /* descriptor for result tuples */ 156 /* and these are the format codes to use for the columns: */ 157 int16 *formats; /* a format code for each column */ 158 159 /* 160 * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or 161 * PORTAL_UTIL_SELECT query. (A cursor held past the end of its 162 * transaction no longer has any active executor state.) 163 */ 164 Tuplestorestate *holdStore; /* store for holdable cursors */ 165 MemoryContext holdContext; /* memory containing holdStore */ 166 167 /* 168 * Snapshot under which tuples in the holdStore were read. We must keep a 169 * reference to this snapshot if there is any possibility that the tuples 170 * contain TOAST references, because releasing the snapshot could allow 171 * recently-dead rows to be vacuumed away, along with any toast data 172 * belonging to them. In the case of a held cursor, we avoid needing to 173 * keep such a snapshot by forcibly detoasting the data. 174 */ 175 Snapshot holdSnapshot; /* registered snapshot, or NULL if none */ 176 177 /* 178 * atStart, atEnd and portalPos indicate the current cursor position. 179 * portalPos is zero before the first row, N after fetching N'th row of 180 * query. After we run off the end, portalPos = # of rows in query, and 181 * atEnd is true. Note that atStart implies portalPos == 0, but not the 182 * reverse: we might have backed up only as far as the first row, not to 183 * the start. Also note that various code inspects atStart and atEnd, but 184 * only the portal movement routines should touch portalPos. 185 */ 186 bool atStart; 187 bool atEnd; 188 uint64 portalPos; 189 190 /* Presentation data, primarily used by the pg_cursors system view */ 191 TimestampTz creation_time; /* time at which this portal was defined */ 192 bool visible; /* include this portal in pg_cursors? */ 193 } PortalData; 194 195 /* 196 * PortalIsValid 197 * True iff portal is valid. 198 */ 199 #define PortalIsValid(p) PointerIsValid(p) 200 201 /* 202 * Access macros for Portal ... use these in preference to field access. 203 */ 204 #define PortalGetQueryDesc(portal) ((portal)->queryDesc) 205 #define PortalGetHeapMemory(portal) ((portal)->heap) 206 207 208 /* Prototypes for functions in utils/mmgr/portalmem.c */ 209 extern void EnablePortalManager(void); 210 extern bool PreCommit_Portals(bool isPrepare); 211 extern void AtAbort_Portals(void); 212 extern void AtCleanup_Portals(void); 213 extern void AtSubCommit_Portals(SubTransactionId mySubid, 214 SubTransactionId parentSubid, 215 ResourceOwner parentXactOwner); 216 extern void AtSubAbort_Portals(SubTransactionId mySubid, 217 SubTransactionId parentSubid, 218 ResourceOwner myXactOwner, 219 ResourceOwner parentXactOwner); 220 extern void AtSubCleanup_Portals(SubTransactionId mySubid); 221 extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent); 222 extern Portal CreateNewPortal(void); 223 extern void PinPortal(Portal portal); 224 extern void UnpinPortal(Portal portal); 225 extern void MarkPortalActive(Portal portal); 226 extern void MarkPortalDone(Portal portal); 227 extern void MarkPortalFailed(Portal portal); 228 extern void PortalDrop(Portal portal, bool isTopCommit); 229 extern Portal GetPortalByName(const char *name); 230 extern void PortalDefineQuery(Portal portal, 231 const char *prepStmtName, 232 const char *sourceText, 233 const char *commandTag, 234 List *stmts, 235 CachedPlan *cplan); 236 extern PlannedStmt *PortalGetPrimaryStmt(Portal portal); 237 extern void PortalCreateHoldStore(Portal portal); 238 extern void PortalHashTableDeleteAll(void); 239 extern bool ThereAreNoReadyPortals(void); 240 241 #endif /* PORTAL_H */ 242