aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 44a59e1d4fb..ffd84d877c1 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -1070,6 +1070,7 @@ exec_simple_query(const char *query_string)
bool snapshot_set = false;
const char *commandTag;
char completionTag[COMPLETION_TAG_BUFSIZE];
+ MemoryContext per_parsetree_context = NULL;
List *querytree_list,
*plantree_list;
Portal portal;
@@ -1132,10 +1133,25 @@ exec_simple_query(const char *query_string)
/*
* OK to analyze, rewrite, and plan this query.
*
- * Switch to appropriate context for constructing querytrees (again,
- * these must outlive the execution context).
+ * Switch to appropriate context for constructing query and plan trees
+ * (these can't be in the transaction context, as that will get reset
+ * when the command is COMMIT/ROLLBACK). If we have multiple
+ * parsetrees, we use a separate context for each one, so that we can
+ * free that memory before moving on to the next one. But for the
+ * last (or only) parsetree, just use MessageContext, which will be
+ * reset shortly after completion anyway. In event of an error, the
+ * per_parsetree_context will be deleted when MessageContext is reset.
*/
- oldcontext = MemoryContextSwitchTo(MessageContext);
+ if (lnext(parsetree_item) != NULL)
+ {
+ per_parsetree_context =
+ AllocSetContextCreate(MessageContext,
+ "per-parsetree message context",
+ ALLOCSET_DEFAULT_SIZES);
+ oldcontext = MemoryContextSwitchTo(per_parsetree_context);
+ }
+ else
+ oldcontext = MemoryContextSwitchTo(MessageContext);
querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
NULL, 0, NULL);
@@ -1160,8 +1176,8 @@ exec_simple_query(const char *query_string)
/*
* We don't have to copy anything into the portal, because everything
- * we are passing here is in MessageContext, which will outlive the
- * portal anyway.
+ * we are passing here is in MessageContext or the
+ * per_parsetree_context, and so will outlive the portal anyway.
*/
PortalDefineQuery(portal,
NULL,
@@ -1263,6 +1279,10 @@ exec_simple_query(const char *query_string)
* aborted by error will not send an EndCommand report at all.)
*/
EndCommand(completionTag, dest);
+
+ /* Now we may drop the per-parsetree context, if one was created. */
+ if (per_parsetree_context)
+ MemoryContextDelete(per_parsetree_context);
} /* end loop over parsetrees */
/*