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-2016, 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; /* PlannedStmts and/or utility statements */ 137 CachedPlan *cplan; /* CachedPlan, if stmts are from one */ 138 139 ParamListInfo portalParams; /* params to pass to query */ 140 141 /* Features/options */ 142 PortalStrategy strategy; /* see above */ 143 int cursorOptions; /* DECLARE CURSOR option bits */ 144 145 /* Status data */ 146 PortalStatus status; /* see above */ 147 bool portalPinned; /* a pinned portal can't be dropped */ 148 149 /* If not NULL, Executor is active; call ExecutorEnd eventually: */ 150 QueryDesc *queryDesc; /* info needed for executor invocation */ 151 152 /* If portal returns tuples, this is their tupdesc: */ 153 TupleDesc tupDesc; /* descriptor for result tuples */ 154 /* and these are the format codes to use for the columns: */ 155 int16 *formats; /* a format code for each column */ 156 157 /* 158 * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or 159 * PORTAL_UTIL_SELECT query. (A cursor held past the end of its 160 * transaction no longer has any active executor state.) 161 */ 162 Tuplestorestate *holdStore; /* store for holdable cursors */ 163 MemoryContext holdContext; /* memory containing holdStore */ 164 165 /* 166 * Snapshot under which tuples in the holdStore were read. We must keep a 167 * reference to this snapshot if there is any possibility that the tuples 168 * contain TOAST references, because releasing the snapshot could allow 169 * recently-dead rows to be vacuumed away, along with any toast data 170 * belonging to them. In the case of a held cursor, we avoid needing to 171 * keep such a snapshot by forcibly detoasting the data. 172 */ 173 Snapshot holdSnapshot; /* registered snapshot, or NULL if none */ 174 175 /* 176 * atStart, atEnd and portalPos indicate the current cursor position. 177 * portalPos is zero before the first row, N after fetching N'th row of 178 * query. After we run off the end, portalPos = # of rows in query, and 179 * atEnd is true. Note that atStart implies portalPos == 0, but not the 180 * reverse: we might have backed up only as far as the first row, not to 181 * the start. Also note that various code inspects atStart and atEnd, but 182 * only the portal movement routines should touch portalPos. 183 */ 184 bool atStart; 185 bool atEnd; 186 uint64 portalPos; 187 188 /* Presentation data, primarily used by the pg_cursors system view */ 189 TimestampTz creation_time; /* time at which this portal was defined */ 190 bool visible; /* include this portal in pg_cursors? */ 191 } PortalData; 192 193 /* 194 * PortalIsValid 195 * True iff portal is valid. 196 */ 197 #define PortalIsValid(p) PointerIsValid(p) 198 199 /* 200 * Access macros for Portal ... use these in preference to field access. 201 */ 202 #define PortalGetQueryDesc(portal) ((portal)->queryDesc) 203 #define PortalGetHeapMemory(portal) ((portal)->heap) 204 #define PortalGetPrimaryStmt(portal) PortalListGetPrimaryStmt((portal)->stmts) 205 206 207 /* Prototypes for functions in utils/mmgr/portalmem.c */ 208 extern void EnablePortalManager(void); 209 extern bool PreCommit_Portals(bool isPrepare); 210 extern void AtAbort_Portals(void); 211 extern void AtCleanup_Portals(void); 212 extern void AtSubCommit_Portals(SubTransactionId mySubid, 213 SubTransactionId parentSubid, 214 ResourceOwner parentXactOwner); 215 extern void AtSubAbort_Portals(SubTransactionId mySubid, 216 SubTransactionId parentSubid, 217 ResourceOwner myXactOwner, 218 ResourceOwner parentXactOwner); 219 extern void AtSubCleanup_Portals(SubTransactionId mySubid); 220 extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent); 221 extern Portal CreateNewPortal(void); 222 extern void PinPortal(Portal portal); 223 extern void UnpinPortal(Portal portal); 224 extern void MarkPortalActive(Portal portal); 225 extern void MarkPortalDone(Portal portal); 226 extern void MarkPortalFailed(Portal portal); 227 extern void PortalDrop(Portal portal, bool isTopCommit); 228 extern Portal GetPortalByName(const char *name); 229 extern void PortalDefineQuery(Portal portal, 230 const char *prepStmtName, 231 const char *sourceText, 232 const char *commandTag, 233 List *stmts, 234 CachedPlan *cplan); 235 extern Node *PortalListGetPrimaryStmt(List *stmts); 236 extern void PortalCreateHoldStore(Portal portal); 237 extern void PortalHashTableDeleteAll(void); 238 extern bool ThereAreNoReadyPortals(void); 239 240 #endif /* PORTAL_H */ 241