From c5e4e91a96aa27f7dee05a763122ad66c5c69282 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 17 Apr 2008 18:30:18 +0000
Subject: [PATCH] Add some code to EXPLAIN to show the targetlist (ie, output
 columns) of each plan node.  For the moment this is debug support only and is
 not enabled unless EXPLAIN_PRINT_TLISTS is defined at build time. Later I'll
 see about the idea of letting EXPLAIN VERBOSE do it.

---
 src/backend/commands/explain.c | 59 ++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index d1511b2fe8c..768ae7797ef 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.171 2008/03/26 18:48:59 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.172 2008/04/17 18:30:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,6 +61,8 @@ static void explain_outNode(StringInfo str,
 				Plan *plan, PlanState *planstate,
 				Plan *outer_plan,
 				int indent, ExplainState *es);
+static void show_plan_tlist(Plan *plan,
+							StringInfo str, int indent, ExplainState *es);
 static void show_scan_qual(List *qual, const char *qlabel,
 			   int scanrelid, Plan *outer_plan, Plan *inner_plan,
 			   StringInfo str, int indent, ExplainState *es);
@@ -443,7 +445,7 @@ explain_outNode(StringInfo str,
 				Plan *outer_plan,
 				int indent, ExplainState *es)
 {
-	char	   *pname;
+	const char *pname;
 	int			i;
 
 	if (plan == NULL)
@@ -744,6 +746,9 @@ explain_outNode(StringInfo str,
 		appendStringInfo(str, " (never executed)");
 	appendStringInfoChar(str, '\n');
 
+	/* target list */
+	show_plan_tlist(plan, str, indent, es);
+
 	/* quals, sort keys, etc */
 	switch (nodeTag(plan))
 	{
@@ -1043,6 +1048,56 @@ explain_outNode(StringInfo str,
 	}
 }
 
+/*
+ * Show the targetlist of a plan node
+ */
+static void
+show_plan_tlist(Plan *plan,
+				StringInfo str, int indent, ExplainState *es)
+{
+#ifdef EXPLAIN_PRINT_TLISTS
+	List	   *context;
+	bool		useprefix;
+	ListCell   *lc;
+	int			i;
+
+	/* No work if empty tlist (this occurs eg in bitmap indexscans) */
+	if (plan->targetlist == NIL)
+		return;
+	/* The tlist of an Append isn't real helpful, so suppress it */
+	if (IsA(plan, Append))
+		return;
+
+	/* Set up deparsing context */
+	context = deparse_context_for_plan((Node *) outerPlan(plan),
+									   (Node *) innerPlan(plan),
+									   es->rtable);
+	useprefix = list_length(es->rtable) > 1;
+
+	/* Emit line prefix */
+	for (i = 0; i < indent; i++)
+		appendStringInfo(str, "  ");
+	appendStringInfo(str, "  Output: ");
+
+	/* Deparse each non-junk result column */
+	i = 0;
+	foreach(lc, plan->targetlist)
+	{
+		TargetEntry *tle = (TargetEntry *) lfirst(lc);
+
+		if (tle->resjunk)
+			continue;
+		if (i++ > 0)
+			appendStringInfo(str, ", ");
+		appendStringInfoString(str,
+							   deparse_expression((Node *) tle->expr, context,
+												  useprefix, false));
+	}
+
+	appendStringInfoChar(str, '\n');
+#endif /* EXPLAIN_PRINT_TLISTS */
+}
+
 /*
  * Show a qualifier expression for a scan plan node
  *
-- 
GitLab