On 2019/05/24 23:28, Tom Lane wrote:
> So my thought, if we want to do something about this, is not "find
> some things we can pfree at the end of planning" but "find a way
> to use a separate context for each statement in the query string".
> Maybe multi-query strings could be handled by setting up a child
> context of MessageContext (after we've done the raw parsing there
> and determined that indeed there are multiple queries), running
> parse analysis and planning in that context, and resetting that
> context after each query.

Maybe like the attached?  I'm not sure if we need to likewise be concerned
about exec_sql_string() being handed multi-query strings.

Thanks,
Amit
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();

Reply via email to