aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execUtils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execUtils.c')
-rw-r--r--src/backend/executor/execUtils.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index d8290b3b5be..eef515a1de7 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,13 +8,14 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.140 2006/10/04 00:29:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.141 2006/12/26 21:37:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* CreateExecutorState Create/delete executor working state
+ * CreateSubExecutorState
* FreeExecutorState
* CreateExprContext
* CreateStandaloneExprContext
@@ -65,6 +66,8 @@ int NIndexTupleInserted;
int NIndexTupleProcessed;
+static EState *InternalCreateExecutorState(MemoryContext qcontext,
+ bool is_subquery);
static void ShutdownExprContext(ExprContext *econtext);
@@ -149,9 +152,7 @@ DisplayTupleCount(FILE *statfp)
EState *
CreateExecutorState(void)
{
- EState *estate;
MemoryContext qcontext;
- MemoryContext oldcontext;
/*
* Create the per-query context for this Executor run.
@@ -162,6 +163,37 @@ CreateExecutorState(void)
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
+ return InternalCreateExecutorState(qcontext, false);
+}
+
+/* ----------------
+ * CreateSubExecutorState
+ *
+ * Create and initialize an EState node for a sub-query.
+ *
+ * Ideally, sub-queries probably shouldn't have their own EState at all,
+ * but right now this is necessary because they have their own rangetables
+ * and we access the rangetable via the EState. It is critical that a
+ * sub-query share the parent's es_query_cxt, else structures allocated by
+ * the sub-query (especially its result tuple descriptor) may disappear
+ * too soon during executor shutdown.
+ * ----------------
+ */
+EState *
+CreateSubExecutorState(EState *parent_estate)
+{
+ return InternalCreateExecutorState(parent_estate->es_query_cxt, true);
+}
+
+/*
+ * Guts of CreateExecutorState/CreateSubExecutorState
+ */
+static EState *
+InternalCreateExecutorState(MemoryContext qcontext, bool is_subquery)
+{
+ EState *estate;
+ MemoryContext oldcontext;
+
/*
* Make the EState node within the per-query context. This way, we don't
* need a separate pfree() operation for it at shutdown.
@@ -200,6 +232,8 @@ CreateExecutorState(void)
estate->es_lastoid = InvalidOid;
estate->es_rowMarks = NIL;
+ estate->es_is_subquery = is_subquery;
+
estate->es_instrument = false;
estate->es_select_into = false;
estate->es_into_oids = false;
@@ -258,9 +292,12 @@ FreeExecutorState(EState *estate)
/*
* Free the per-query memory context, thereby releasing all working
- * memory, including the EState node itself.
+ * memory, including the EState node itself. In a subquery, we don't
+ * do this, leaving the memory cleanup to happen when the topmost query
+ * is closed down.
*/
- MemoryContextDelete(estate->es_query_cxt);
+ if (!estate->es_is_subquery)
+ MemoryContextDelete(estate->es_query_cxt);
}
/* ----------------