diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 44a59e1d4f..0165f794b0 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -984,7 +984,8 @@ static void exec_simple_query(const char *query_string) { CommandDest dest = whereToSendOutput; - MemoryContext oldcontext; + MemoryContext oldcontext, + stmtcontext; List *parsetree_list; ListCell *parsetree_item; bool save_log_statement_stats = log_statement_stats; @@ -1132,10 +1133,14 @@ 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 querytrees. + * Memory allocated during this construction is released before + * the generated plan is executed. */ - oldcontext = MemoryContextSwitchTo(MessageContext); + stmtcontext = AllocSetContextCreate(MessageContext, + "statement parse/plan context", + ALLOCSET_DEFAULT_SIZES); + oldcontext = MemoryContextSwitchTo(stmtcontext); querytree_list = pg_analyze_and_rewrite(parsetree, query_string, NULL, 0, NULL); @@ -1143,6 +1148,14 @@ exec_simple_query(const char *query_string) plantree_list = pg_plan_queries(querytree_list, CURSOR_OPT_PARALLEL_OK, NULL); + /* + * Copy the plan trees into the longer-lived MessageContext and delete + * the temporary context used to generate them. + */ + MemoryContextSwitchTo(MessageContext); + plantree_list = copyObject(plantree_list); + MemoryContextDelete(stmtcontext); + /* Done with the snapshot used for parsing/planning */ if (snapshot_set) PopActiveSnapshot();