From 147fbf9c6eba1a494c7fcd34227c5809ab39d491 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 5 Mar 2003 18:38:14 +0000
Subject: [PATCH] Repair bug reported by Laurent Perez: bad plan generated when
 UPDATE or DELETE of an inheritance tree references another inherited
 relation. This bug has been latent since 7.1; I'm still not quite sure why
 7.1 and 7.2 don't manifest it (at least, they don't crash on a simple test
 case).

---
 src/backend/optimizer/plan/planner.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 76862c769cb..c597e44f1d4 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.148 2003/02/15 21:39:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.149 2003/03/05 18:38:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -443,6 +443,7 @@ inheritance_planner(Query *parse, List *inheritlist)
 {
 	int			parentRTindex = parse->resultRelation;
 	Oid			parentOID = getrelid(parentRTindex, parse->rtable);
+	int			mainrtlength = length(parse->rtable);
 	List	   *subplans = NIL;
 	List	   *tlist = NIL;
 	List	   *l;
@@ -451,6 +452,7 @@ inheritance_planner(Query *parse, List *inheritlist)
 	{
 		int			childRTindex = lfirsti(l);
 		Oid			childOID = getrelid(childRTindex, parse->rtable);
+		int			subrtlength;
 		Query	   *subquery;
 		Plan	   *subplan;
 
@@ -461,6 +463,24 @@ inheritance_planner(Query *parse, List *inheritlist)
 		/* Generate plan */
 		subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */ );
 		subplans = lappend(subplans, subplan);
+		/*
+		 * It's possible that additional RTEs got added to the rangetable
+		 * due to expansion of inherited source tables (see allpaths.c).
+		 * If so, we must copy 'em back to the main parse tree's rtable.
+		 *
+		 * XXX my goodness this is ugly.  Really need to think about ways
+		 * to rein in planner's habit of scribbling on its input.
+		 */
+		subrtlength = length(subquery->rtable);
+		if (subrtlength > mainrtlength)
+		{
+			List   *subrt = subquery->rtable;
+
+			while (mainrtlength-- > 0) /* wish we had nthcdr() */
+				subrt = lnext(subrt);
+			parse->rtable = nconc(parse->rtable, subrt);
+			mainrtlength = subrtlength;
+		}
 		/* Save preprocessed tlist from first rel for use in Append */
 		if (tlist == NIL)
 			tlist = subplan->targetlist;
-- 
GitLab