* to look like NO SCROLL cursors.
*
*
- * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: portal.h,v 1.47 2003/08/08 21:42:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/portal.h,v 1.66 2006/08/14 22:57:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#define PORTAL_H
#include "executor/execdesc.h"
-#include "nodes/memnodes.h"
-#include "utils/tuplestore.h"
-
+#include "utils/resowner.h"
+#include "utils/timestamp.h"
/*
* We have several execution strategies for Portals, depending on what
* supports holdable cursors (the Executor results can be dumped into a
* tuplestore for access after transaction completion).
*
+ * PORTAL_ONE_RETURNING: the portal contains a single INSERT/UPDATE/DELETE
+ * query with a RETURNING clause (plus possibly auxiliary queries added by
+ * rule rewriting). On first execution, we run the portal to completion
+ * and dump the primary query's results into the portal tuplestore; the
+ * results are then returned to the client as demanded. (We can't support
+ * suspension of the query partway through, because the AFTER TRIGGER code
+ * can't cope, and also because we don't want to risk failing to execute
+ * all the auxiliary queries.)
+ *
* PORTAL_UTIL_SELECT: the portal contains a utility statement that returns
* a SELECT-like result (for example, EXPLAIN or SHOW). On first execution,
* we run the statement and dump its results into the portal tuplestore;
* PORTAL_MULTI_QUERY: all other cases. Here, we do not support partial
* execution: the portal's queries will be run to completion on first call.
*/
-
typedef enum PortalStrategy
{
PORTAL_ONE_SELECT,
+ PORTAL_ONE_RETURNING,
PORTAL_UTIL_SELECT,
PORTAL_MULTI_QUERY
} PortalStrategy;
+/*
+ * A portal is always in one of these states. It is possible to transit
+ * from ACTIVE back to READY if the query is not run to completion;
+ * otherwise we never back up in status.
+ */
+typedef enum PortalStatus
+{
+ PORTAL_NEW, /* in process of creation */
+ PORTAL_READY, /* PortalStart complete, can run it */
+ PORTAL_ACTIVE, /* portal is running (can't delete it) */
+ PORTAL_DONE, /* portal is finished (don't re-run it) */
+ PORTAL_FAILED /* portal got error (can't re-run it) */
+} PortalStatus;
+
/*
* Note: typedef Portal is declared in tcop/dest.h as
* typedef struct PortalData *Portal;
{
/* Bookkeeping data */
const char *name; /* portal's name */
+ const char *prepStmtName; /* protocol prepare name */
MemoryContext heap; /* subsidiary memory for portal */
- void (*cleanup) (Portal portal, bool isError); /* cleanup hook */
- TransactionId createXact; /* the xid of the creating xact */
+ ResourceOwner resowner; /* resources owned by portal */
+ void (*cleanup) (Portal portal); /* cleanup hook */
+ SubTransactionId createSubid; /* the ID of the creating subxact */
+
+ /*
+ * if createSubid is InvalidSubTransactionId, the portal is held over from
+ * a previous transaction
+ */
/* The query or queries the portal will execute */
const char *sourceText; /* text of query, if known (may be NULL) */
MemoryContext queryContext; /* where the above trees live */
/*
- * Note: queryContext effectively identifies which prepared statement
- * the portal depends on, if any. The queryContext is *not* owned by
- * the portal and is not to be deleted by portal destruction. (But
- * for a cursor it is the same as "heap", and that context is deleted
- * by portal destruction.)
+ * Note: queryContext effectively identifies which prepared statement the
+ * portal depends on, if any. The queryContext is *not* owned by the
+ * portal and is not to be deleted by portal destruction. (But for a
+ * cursor it is the same as "heap", and that context is deleted by portal
+ * destruction.)
*/
ParamListInfo portalParams; /* params to pass to query */
int cursorOptions; /* DECLARE CURSOR option bits */
/* Status data */
- bool portalReady; /* PortalStart complete? */
- bool portalUtilReady; /* PortalRunUtility complete? */
- bool portalActive; /* portal is running (can't delete it) */
- bool portalDone; /* portal is finished (don't re-run it) */
+ PortalStatus status; /* see above */
/* If not NULL, Executor is active; call ExecutorEnd eventually: */
QueryDesc *queryDesc; /* info needed for executor invocation */
int16 *formats; /* a format code for each column */
/*
- * Where we store tuples for a held cursor or a PORTAL_UTIL_SELECT
- * query. (A cursor held past the end of its transaction no longer has
- * any active executor state.)
+ * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or
+ * PORTAL_UTIL_SELECT query. (A cursor held past the end of its
+ * transaction no longer has any active executor state.)
*/
Tuplestorestate *holdStore; /* store for holdable cursors */
MemoryContext holdContext; /* memory containing holdStore */
/*
* atStart, atEnd and portalPos indicate the current cursor position.
- * portalPos is zero before the first row, N after fetching N'th row
- * of query. After we run off the end, portalPos = # of rows in
- * query, and atEnd is true. If portalPos overflows, set posOverflow
- * (this causes us to stop relying on its value for navigation). Note
- * that atStart implies portalPos == 0, but not the reverse (portalPos
- * could have overflowed).
+ * portalPos is zero before the first row, N after fetching N'th row of
+ * query. After we run off the end, portalPos = # of rows in query, and
+ * atEnd is true. If portalPos overflows, set posOverflow (this causes us
+ * to stop relying on its value for navigation). Note that atStart
+ * implies portalPos == 0, but not the reverse (portalPos could have
+ * overflowed).
*/
bool atStart;
bool atEnd;
bool posOverflow;
long portalPos;
+
+ /* Presentation data, primarily used by the pg_cursors system view */
+ TimestampTz creation_time; /* time at which this portal was defined */
+ bool visible; /* include this portal in pg_cursors? */
} PortalData;
/*
*/
#define PortalGetQueryDesc(portal) ((portal)->queryDesc)
#define PortalGetHeapMemory(portal) ((portal)->heap)
+#define PortalGetPrimaryQuery(portal) PortalListGetPrimaryQuery((portal)->parseTrees)
/* Prototypes for functions in utils/mmgr/portalmem.c */
extern void EnablePortalManager(void);
+extern bool CommitHoldablePortals(void);
+extern bool PrepareHoldablePortals(void);
extern void AtCommit_Portals(void);
extern void AtAbort_Portals(void);
extern void AtCleanup_Portals(void);
+extern void AtSubCommit_Portals(SubTransactionId mySubid,
+ SubTransactionId parentSubid,
+ ResourceOwner parentXactOwner);
+extern void AtSubAbort_Portals(SubTransactionId mySubid,
+ SubTransactionId parentSubid,
+ ResourceOwner parentXactOwner);
+extern void AtSubCleanup_Portals(SubTransactionId mySubid);
extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent);
extern Portal CreateNewPortal(void);
-extern void PortalDrop(Portal portal, bool isError);
+extern void PortalDrop(Portal portal, bool isTopCommit);
extern void DropDependentPortals(MemoryContext queryContext);
extern Portal GetPortalByName(const char *name);
extern void PortalDefineQuery(Portal portal,
+ const char *prepStmtName,
const char *sourceText,
const char *commandTag,
List *parseTrees,
List *planTrees,
MemoryContext queryContext);
+extern Query *PortalListGetPrimaryQuery(List *parseTrees);
extern void PortalCreateHoldStore(Portal portal);
#endif /* PORTAL_H */