]> granicus.if.org Git - postgresql/commitdiff
Repair EXPLAIN failure when trying to display a plan condition that involves
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 Dec 2005 18:34:22 +0000 (18:34 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 Dec 2005 18:34:22 +0000 (18:34 +0000)
selection of a field from the result of a function returning RECORD.
I believe this case is new in 8.1; it's due to the addition of OUT parameters.
Per example from Michael Fuhr.

src/backend/utils/adt/ruleutils.c

index eaf4f195077130c2f6759869579b6be118b6fc22..7c47054633f1f2eebc8cd26df3bcd71dde9620d6 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.211 2005/12/28 01:30:00 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.212 2005/12/30 18:34:22 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1525,8 +1525,15 @@ deparse_context_for_subplan(const char *name, List *tlist,
                attrs = lappend(attrs, makeString(pstrdup(buf)));
        }
 
-       rte->rtekind = RTE_SPECIAL; /* XXX */
+       /*
+        * We create an RTE_SPECIAL RangeTblEntry, and store the given tlist
+        * in its coldeflist field.  This is a hack to make the tlist available
+        * to get_name_for_var_field().  RTE_SPECIAL nodes shouldn't appear in
+        * deparse contexts otherwise.
+        */
+       rte->rtekind = RTE_SPECIAL;
        rte->relid = InvalidOid;
+       rte->coldeflist = tlist;
        rte->eref = makeAlias(name, attrs);
        rte->inh = false;
        rte->inFromCl = true;
@@ -2571,7 +2578,8 @@ get_names_for_var(Var *var, int levelsup, deparse_context *context,
  * Note: this has essentially the same logic as the parser's
  * expandRecordVariable() function, but we are dealing with a different
  * representation of the input context, and we only need one field name not
- * a TupleDesc.
+ * a TupleDesc.  Also, we have a special case for RTE_SPECIAL so that we can
+ * deal with displaying RECORD-returning functions in subplan targetlists.
  */
 static const char *
 get_name_for_var_field(Var *var, int fieldno,
@@ -2602,7 +2610,6 @@ get_name_for_var_field(Var *var, int fieldno,
        switch (rte->rtekind)
        {
                case RTE_RELATION:
-               case RTE_SPECIAL:
 
                        /*
                         * This case should not occur: a column of a table shouldn't have
@@ -2663,6 +2670,21 @@ get_name_for_var_field(Var *var, int fieldno,
                         * its result columns as RECORD, which is not allowed.
                         */
                        break;
+               case RTE_SPECIAL:
+                       /*
+                        * This case occurs during EXPLAIN when we are looking at a
+                        * deparse context node set up by deparse_context_for_subplan().
+                        * Look into the subplan's target list to get the referenced
+                        * expression, and then pass it to get_expr_result_type().
+                        */
+                       if (rte->coldeflist)
+                       {
+                               TargetEntry *ste = get_tle_by_resno(rte->coldeflist, attnum);
+
+                               if (ste != NULL)
+                                       expr = (Node *) ste->expr;
+                       }
+                       break;
        }
 
        /*