]> granicus.if.org Git - postgresql/blobdiff - src/include/utils/portal.h
Fix oversight in initial implementation of PORTAL_ONE_RETURNING mode: we
[postgresql] / src / include / utils / portal.h
index 3faf3ec562fb9252b83fe61902e86650e263edf2..92cc55189ed67a556e4745e5386f12d61b7c4975 100644 (file)
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,9 +47,8 @@
 #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;
@@ -88,9 +110,16 @@ typedef struct PortalData
 {
        /* 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) */
@@ -100,11 +129,11 @@ typedef struct PortalData
        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 */
 
@@ -113,10 +142,7 @@ typedef struct PortalData
        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 */
@@ -127,26 +153,30 @@ typedef struct PortalData
        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;
 
 /*
@@ -160,24 +190,36 @@ typedef struct 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 */