Header And Logo

PostgreSQL
| The world's most advanced open source database.

portal.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * portal.h
00004  *    POSTGRES portal definitions.
00005  *
00006  * A portal is an abstraction which represents the execution state of
00007  * a running or runnable query.  Portals support both SQL-level CURSORs
00008  * and protocol-level portals.
00009  *
00010  * Scrolling (nonsequential access) and suspension of execution are allowed
00011  * only for portals that contain a single SELECT-type query.  We do not want
00012  * to let the client suspend an update-type query partway through!  Because
00013  * the query rewriter does not allow arbitrary ON SELECT rewrite rules,
00014  * only queries that were originally update-type could produce multiple
00015  * plan trees; so the restriction to a single query is not a problem
00016  * in practice.
00017  *
00018  * For SQL cursors, we support three kinds of scroll behavior:
00019  *
00020  * (1) Neither NO SCROLL nor SCROLL was specified: to remain backward
00021  *     compatible, we allow backward fetches here, unless it would
00022  *     impose additional runtime overhead to do so.
00023  *
00024  * (2) NO SCROLL was specified: don't allow any backward fetches.
00025  *
00026  * (3) SCROLL was specified: allow all kinds of backward fetches, even
00027  *     if we need to take a performance hit to do so.  (The planner sticks
00028  *     a Materialize node atop the query plan if needed.)
00029  *
00030  * Case #1 is converted to #2 or #3 by looking at the query itself and
00031  * determining if scrollability can be supported without additional
00032  * overhead.
00033  *
00034  * Protocol-level portals have no nonsequential-fetch API and so the
00035  * distinction doesn't matter for them.  They are always initialized
00036  * to look like NO SCROLL cursors.
00037  *
00038  *
00039  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00040  * Portions Copyright (c) 1994, Regents of the University of California
00041  *
00042  * src/include/utils/portal.h
00043  *
00044  *-------------------------------------------------------------------------
00045  */
00046 #ifndef PORTAL_H
00047 #define PORTAL_H
00048 
00049 #include "datatype/timestamp.h"
00050 #include "executor/execdesc.h"
00051 #include "utils/plancache.h"
00052 #include "utils/resowner.h"
00053 
00054 /*
00055  * We have several execution strategies for Portals, depending on what
00056  * query or queries are to be executed.  (Note: in all cases, a Portal
00057  * executes just a single source-SQL query, and thus produces just a
00058  * single result from the user's viewpoint.  However, the rule rewriter
00059  * may expand the single source query to zero or many actual queries.)
00060  *
00061  * PORTAL_ONE_SELECT: the portal contains one single SELECT query.  We run
00062  * the Executor incrementally as results are demanded.  This strategy also
00063  * supports holdable cursors (the Executor results can be dumped into a
00064  * tuplestore for access after transaction completion).
00065  *
00066  * PORTAL_ONE_RETURNING: the portal contains a single INSERT/UPDATE/DELETE
00067  * query with a RETURNING clause (plus possibly auxiliary queries added by
00068  * rule rewriting).  On first execution, we run the portal to completion
00069  * and dump the primary query's results into the portal tuplestore; the
00070  * results are then returned to the client as demanded.  (We can't support
00071  * suspension of the query partway through, because the AFTER TRIGGER code
00072  * can't cope, and also because we don't want to risk failing to execute
00073  * all the auxiliary queries.)
00074  *
00075  * PORTAL_ONE_MOD_WITH: the portal contains one single SELECT query, but
00076  * it has data-modifying CTEs.  This is currently treated the same as the
00077  * PORTAL_ONE_RETURNING case because of the possibility of needing to fire
00078  * triggers.  It may act more like PORTAL_ONE_SELECT in future.
00079  *
00080  * PORTAL_UTIL_SELECT: the portal contains a utility statement that returns
00081  * a SELECT-like result (for example, EXPLAIN or SHOW).  On first execution,
00082  * we run the statement and dump its results into the portal tuplestore;
00083  * the results are then returned to the client as demanded.
00084  *
00085  * PORTAL_MULTI_QUERY: all other cases.  Here, we do not support partial
00086  * execution: the portal's queries will be run to completion on first call.
00087  */
00088 typedef enum PortalStrategy
00089 {
00090     PORTAL_ONE_SELECT,
00091     PORTAL_ONE_RETURNING,
00092     PORTAL_ONE_MOD_WITH,
00093     PORTAL_UTIL_SELECT,
00094     PORTAL_MULTI_QUERY
00095 } PortalStrategy;
00096 
00097 /*
00098  * A portal is always in one of these states.  It is possible to transit
00099  * from ACTIVE back to READY if the query is not run to completion;
00100  * otherwise we never back up in status.
00101  */
00102 typedef enum PortalStatus
00103 {
00104     PORTAL_NEW,                 /* freshly created */
00105     PORTAL_DEFINED,             /* PortalDefineQuery done */
00106     PORTAL_READY,               /* PortalStart complete, can run it */
00107     PORTAL_ACTIVE,              /* portal is running (can't delete it) */
00108     PORTAL_DONE,                /* portal is finished (don't re-run it) */
00109     PORTAL_FAILED               /* portal got error (can't re-run it) */
00110 } PortalStatus;
00111 
00112 typedef struct PortalData *Portal;
00113 
00114 typedef struct PortalData
00115 {
00116     /* Bookkeeping data */
00117     const char *name;           /* portal's name */
00118     const char *prepStmtName;   /* source prepared statement (NULL if none) */
00119     MemoryContext heap;         /* subsidiary memory for portal */
00120     ResourceOwner resowner;     /* resources owned by portal */
00121     void        (*cleanup) (Portal portal);     /* cleanup hook */
00122     SubTransactionId createSubid;       /* the ID of the creating subxact */
00123 
00124     /*
00125      * if createSubid is InvalidSubTransactionId, the portal is held over from
00126      * a previous transaction
00127      */
00128 
00129     /* The query or queries the portal will execute */
00130     const char *sourceText;     /* text of query (as of 8.4, never NULL) */
00131     const char *commandTag;     /* command tag for original query */
00132     List       *stmts;          /* PlannedStmts and/or utility statements */
00133     CachedPlan *cplan;          /* CachedPlan, if stmts are from one */
00134 
00135     ParamListInfo portalParams; /* params to pass to query */
00136 
00137     /* Features/options */
00138     PortalStrategy strategy;    /* see above */
00139     int         cursorOptions;  /* DECLARE CURSOR option bits */
00140 
00141     /* Status data */
00142     PortalStatus status;        /* see above */
00143     bool        portalPinned;   /* a pinned portal can't be dropped */
00144 
00145     /* If not NULL, Executor is active; call ExecutorEnd eventually: */
00146     QueryDesc  *queryDesc;      /* info needed for executor invocation */
00147 
00148     /* If portal returns tuples, this is their tupdesc: */
00149     TupleDesc   tupDesc;        /* descriptor for result tuples */
00150     /* and these are the format codes to use for the columns: */
00151     int16      *formats;        /* a format code for each column */
00152 
00153     /*
00154      * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or
00155      * PORTAL_UTIL_SELECT query.  (A cursor held past the end of its
00156      * transaction no longer has any active executor state.)
00157      */
00158     Tuplestorestate *holdStore; /* store for holdable cursors */
00159     MemoryContext holdContext;  /* memory containing holdStore */
00160 
00161     /*
00162      * atStart, atEnd and portalPos indicate the current cursor position.
00163      * portalPos is zero before the first row, N after fetching N'th row of
00164      * query.  After we run off the end, portalPos = # of rows in query, and
00165      * atEnd is true.  If portalPos overflows, set posOverflow (this causes us
00166      * to stop relying on its value for navigation).  Note that atStart
00167      * implies portalPos == 0, but not the reverse (portalPos could have
00168      * overflowed).
00169      */
00170     bool        atStart;
00171     bool        atEnd;
00172     bool        posOverflow;
00173     long        portalPos;
00174 
00175     /* Presentation data, primarily used by the pg_cursors system view */
00176     TimestampTz creation_time;  /* time at which this portal was defined */
00177     bool        visible;        /* include this portal in pg_cursors? */
00178 }   PortalData;
00179 
00180 /*
00181  * PortalIsValid
00182  *      True iff portal is valid.
00183  */
00184 #define PortalIsValid(p) PointerIsValid(p)
00185 
00186 /*
00187  * Access macros for Portal ... use these in preference to field access.
00188  */
00189 #define PortalGetQueryDesc(portal)  ((portal)->queryDesc)
00190 #define PortalGetHeapMemory(portal) ((portal)->heap)
00191 #define PortalGetPrimaryStmt(portal) PortalListGetPrimaryStmt((portal)->stmts)
00192 
00193 
00194 /* Prototypes for functions in utils/mmgr/portalmem.c */
00195 extern void EnablePortalManager(void);
00196 extern bool PreCommit_Portals(bool isPrepare);
00197 extern void AtAbort_Portals(void);
00198 extern void AtCleanup_Portals(void);
00199 extern void AtSubCommit_Portals(SubTransactionId mySubid,
00200                     SubTransactionId parentSubid,
00201                     ResourceOwner parentXactOwner);
00202 extern void AtSubAbort_Portals(SubTransactionId mySubid,
00203                    SubTransactionId parentSubid,
00204                    ResourceOwner parentXactOwner);
00205 extern void AtSubCleanup_Portals(SubTransactionId mySubid);
00206 extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent);
00207 extern Portal CreateNewPortal(void);
00208 extern void PinPortal(Portal portal);
00209 extern void UnpinPortal(Portal portal);
00210 extern void MarkPortalDone(Portal portal);
00211 extern void MarkPortalFailed(Portal portal);
00212 extern void PortalDrop(Portal portal, bool isTopCommit);
00213 extern Portal GetPortalByName(const char *name);
00214 extern void PortalDefineQuery(Portal portal,
00215                   const char *prepStmtName,
00216                   const char *sourceText,
00217                   const char *commandTag,
00218                   List *stmts,
00219                   CachedPlan *cplan);
00220 extern Node *PortalListGetPrimaryStmt(List *stmts);
00221 extern void PortalCreateHoldStore(Portal portal);
00222 extern void PortalHashTableDeleteAll(void);
00223 extern bool ThereAreNoReadyPortals(void);
00224 
00225 #endif   /* PORTAL_H */