aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/functions.c')
-rw-r--r--src/backend/executor/functions.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index cff75b2f647..53ff614d87b 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -871,13 +871,19 @@ prepare_next_query(SQLFunctionHashEntry *func)
/*
* Parse and/or rewrite the query, creating a CachedPlanSource that holds
- * a copy of the original parsetree.
+ * a copy of the original parsetree. Note fine point: we make a copy of
+ * each original parsetree to ensure that the source_list in pcontext
+ * remains unmodified during parse analysis and rewrite. This is normally
+ * unnecessary, but we have to do it in case an error is raised during
+ * parse analysis. Otherwise, a fresh attempt to execute the function
+ * will arrive back here and try to work from a corrupted source_list.
*/
if (!func->raw_source)
{
/* Source queries are already parse-analyzed */
Query *parsetree = list_nth_node(Query, func->source_list, qindex);
+ parsetree = copyObject(parsetree);
plansource = CreateCachedPlanForQuery(parsetree,
func->src,
CreateCommandTag((Node *) parsetree));
@@ -889,6 +895,7 @@ prepare_next_query(SQLFunctionHashEntry *func)
/* Source queries are raw parsetrees */
RawStmt *parsetree = list_nth_node(RawStmt, func->source_list, qindex);
+ parsetree = copyObject(parsetree);
plansource = CreateCachedPlan(parsetree,
func->src,
CreateCommandTag(parsetree->stmt));