[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pgsql-hackers
Subject:    [HACKERS] explain refactoring v2
From:       Robert Haas <robertmhaas () gmail ! com>
Date:       2009-05-30 21:33:07
Message-ID: 603c8f070905301433i1804ab9aqecb272a5679405b () mail ! gmail ! com
[Download RAW message or body]

Here's an updated version of my patch from last night.

http://archives.postgresql.org/message-id/603c8f070905292048y804d505wf701214e7b81fde7@mail.gmail.com

In addition to the changes mentioned there, this removes a completely
unused argument from show_scan_qual() and two redundant ones from
show_sort_keys().

I realize this may not be the most glamorous patch that any of you
have read in the last year...

...Robert

["explain_refactor_v2.patch" (text/x-diff)]

*** a/src/backend/commands/explain.c
--- b/src/backend/commands/explain.c
***************
*** 63,78 **** static void explain_outNode(StringInfo str,
  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 *scan_plan, Plan *outer_plan,
  			   StringInfo str, int indent, ExplainState *es);
  static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
  				StringInfo str, int indent, ExplainState *es);
! static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
! 			   const char *qlabel,
  			   StringInfo str, int indent, ExplainState *es);
  static void show_sort_info(SortState *sortstate,
  			   StringInfo str, int indent, ExplainState *es);
  static const char *explain_get_index_name(Oid indexId);
  
  
  /*
--- 63,78 ----
  static void show_plan_tlist(Plan *plan,
  							StringInfo str, int indent, ExplainState *es);
  static void show_scan_qual(List *qual, const char *qlabel,
! 			   Plan *scan_plan, Plan *outer_plan,
  			   StringInfo str, int indent, ExplainState *es);
  static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
  				StringInfo str, int indent, ExplainState *es);
! static void show_sort_keys(Plan *sortplan, const char *qlabel,
  			   StringInfo str, int indent, ExplainState *es);
  static void show_sort_info(SortState *sortstate,
  			   StringInfo str, int indent, ExplainState *es);
  static const char *explain_get_index_name(Oid indexId);
+ static void ExplainScanTarget(StringInfo str, Scan *plan, ExplainState *es);
  
  
  /*
***************
*** 668,790 **** explain_outNode(StringInfo str,
  		case T_SeqScan:
  		case T_BitmapHeapScan:
  		case T_TidScan:
- 			if (((Scan *) plan)->scanrelid > 0)
- 			{
- 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
- 											  es->rtable);
- 				char	   *relname;
- 
- 				/* Assume it's on a real relation */
- 				Assert(rte->rtekind == RTE_RELATION);
- 
- 				/* We only show the rel name, not schema name */
- 				relname = get_rel_name(rte->relid);
- 
- 				appendStringInfo(str, " on %s",
- 								 quote_identifier(relname));
- 				if (strcmp(rte->eref->aliasname, relname) != 0)
- 					appendStringInfo(str, " %s",
- 									 quote_identifier(rte->eref->aliasname));
- 			}
- 			break;
- 		case T_BitmapIndexScan:
- 			appendStringInfo(str, " on %s",
- 				explain_get_index_name(((BitmapIndexScan *) plan)->indexid));
- 			break;
  		case T_SubqueryScan:
- 			if (((Scan *) plan)->scanrelid > 0)
- 			{
- 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
- 											  es->rtable);
- 
- 				appendStringInfo(str, " %s",
- 								 quote_identifier(rte->eref->aliasname));
- 			}
- 			break;
  		case T_FunctionScan:
- 			if (((Scan *) plan)->scanrelid > 0)
- 			{
- 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
- 											  es->rtable);
- 				Node	   *funcexpr;
- 				char	   *proname;
- 
- 				/* Assert it's on a RangeFunction */
- 				Assert(rte->rtekind == RTE_FUNCTION);
- 
- 				/*
- 				 * If the expression is still a function call, we can get the
- 				 * real name of the function.  Otherwise, punt (this can
- 				 * happen if the optimizer simplified away the function call,
- 				 * for example).
- 				 */
- 				funcexpr = ((FunctionScan *) plan)->funcexpr;
- 				if (funcexpr && IsA(funcexpr, FuncExpr))
- 				{
- 					Oid			funcid = ((FuncExpr *) funcexpr)->funcid;
- 
- 					/* We only show the func name, not schema name */
- 					proname = get_func_name(funcid);
- 				}
- 				else
- 					proname = rte->eref->aliasname;
- 
- 				appendStringInfo(str, " on %s",
- 								 quote_identifier(proname));
- 				if (strcmp(rte->eref->aliasname, proname) != 0)
- 					appendStringInfo(str, " %s",
- 									 quote_identifier(rte->eref->aliasname));
- 			}
- 			break;
  		case T_ValuesScan:
- 			if (((Scan *) plan)->scanrelid > 0)
- 			{
- 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
- 											  es->rtable);
- 				char	   *valsname;
- 
- 				/* Assert it's on a values rte */
- 				Assert(rte->rtekind == RTE_VALUES);
- 
- 				valsname = rte->eref->aliasname;
- 
- 				appendStringInfo(str, " on %s",
- 								 quote_identifier(valsname));
- 			}
- 			break;
  		case T_CteScan:
- 			if (((Scan *) plan)->scanrelid > 0)
- 			{
- 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
- 											  es->rtable);
- 
- 				/* Assert it's on a non-self-reference CTE */
- 				Assert(rte->rtekind == RTE_CTE);
- 				Assert(!rte->self_reference);
- 
- 				appendStringInfo(str, " on %s",
- 								 quote_identifier(rte->ctename));
- 				if (strcmp(rte->eref->aliasname, rte->ctename) != 0)
- 					appendStringInfo(str, " %s",
- 									 quote_identifier(rte->eref->aliasname));
- 			}
- 			break;
  		case T_WorkTableScan:
! 			if (((Scan *) plan)->scanrelid > 0)
! 			{
! 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
! 											  es->rtable);
! 
! 				/* Assert it's on a self-reference CTE */
! 				Assert(rte->rtekind == RTE_CTE);
! 				Assert(rte->self_reference);
! 
! 				appendStringInfo(str, " on %s",
! 								 quote_identifier(rte->ctename));
! 				if (strcmp(rte->eref->aliasname, rte->ctename) != 0)
! 					appendStringInfo(str, " %s",
! 									 quote_identifier(rte->eref->aliasname));
! 			}
  			break;
  		default:
  			break;
--- 668,683 ----
  		case T_SeqScan:
  		case T_BitmapHeapScan:
  		case T_TidScan:
  		case T_SubqueryScan:
  		case T_FunctionScan:
  		case T_ValuesScan:
  		case T_CteScan:
  		case T_WorkTableScan:
! 			ExplainScanTarget(str, (Scan *) plan, es);
! 			break;
! 		case T_BitmapIndexScan:
! 			appendStringInfo(str, " on %s",
! 				explain_get_index_name(((BitmapIndexScan *) plan)->indexid));
  			break;
  		default:
  			break;
***************
*** 825,843 **** explain_outNode(StringInfo str,
  		case T_IndexScan:
  			show_scan_qual(((IndexScan *) plan)->indexqualorig,
  						   "Index Cond",
- 						   ((Scan *) plan)->scanrelid,
  						   plan, outer_plan,
  						   str, indent, es);
  			show_scan_qual(plan->qual,
  						   "Filter",
- 						   ((Scan *) plan)->scanrelid,
  						   plan, outer_plan,
  						   str, indent, es);
  			break;
  		case T_BitmapIndexScan:
  			show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
  						   "Index Cond",
- 						   ((Scan *) plan)->scanrelid,
  						   plan, outer_plan,
  						   str, indent, es);
  			break;
--- 718,733 ----
***************
*** 845,851 **** explain_outNode(StringInfo str,
  			/* XXX do we want to show this in production? */
  			show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig,
  						   "Recheck Cond",
- 						   ((Scan *) plan)->scanrelid,
  						   plan, outer_plan,
  						   str, indent, es);
  			/* FALL THRU */
--- 735,740 ----
***************
*** 854,869 **** explain_outNode(StringInfo str,
  		case T_ValuesScan:
  		case T_CteScan:
  		case T_WorkTableScan:
- 			show_scan_qual(plan->qual,
- 						   "Filter",
- 						   ((Scan *) plan)->scanrelid,
- 						   plan, outer_plan,
- 						   str, indent, es);
- 			break;
  		case T_SubqueryScan:
  			show_scan_qual(plan->qual,
  						   "Filter",
- 						   ((Scan *) plan)->scanrelid,
  						   plan, outer_plan,
  						   str, indent, es);
  			break;
--- 743,751 ----
***************
*** 879,890 **** explain_outNode(StringInfo str,
  					tidquals = list_make1(make_orclause(tidquals));
  				show_scan_qual(tidquals,
  							   "TID Cond",
- 							   ((Scan *) plan)->scanrelid,
  							   plan, outer_plan,
  							   str, indent, es);
  				show_scan_qual(plan->qual,
  							   "Filter",
- 							   ((Scan *) plan)->scanrelid,
  							   plan, outer_plan,
  							   str, indent, es);
  			}
--- 761,770 ----
***************
*** 927,934 **** explain_outNode(StringInfo str,
  			break;
  		case T_Sort:
  			show_sort_keys(plan,
- 						   ((Sort *) plan)->numCols,
- 						   ((Sort *) plan)->sortColIdx,
  						   "Sort Key",
  						   str, indent, es);
  			show_sort_info((SortState *) planstate,
--- 807,812 ----
***************
*** 1179,1185 **** show_plan_tlist(Plan *plan,
   */
  static void
  show_scan_qual(List *qual, const char *qlabel,
! 			   int scanrelid, Plan *scan_plan, Plan *outer_plan,
  			   StringInfo str, int indent, ExplainState *es)
  {
  	List	   *context;
--- 1057,1063 ----
   */
  static void
  show_scan_qual(List *qual, const char *qlabel,
! 			   Plan *scan_plan, Plan *outer_plan,
  			   StringInfo str, int indent, ExplainState *es)
  {
  	List	   *context;
***************
*** 1249,1256 **** show_upper_qual(List *qual, const char *qlabel, Plan *plan,
   * Show the sort keys for a Sort node.
   */
  static void
! show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
! 			   const char *qlabel,
  			   StringInfo str, int indent, ExplainState *es)
  {
  	List	   *context;
--- 1127,1133 ----
   * Show the sort keys for a Sort node.
   */
  static void
! show_sort_keys(Plan *sortplan, const char *qlabel,
  			   StringInfo str, int indent, ExplainState *es)
  {
  	List	   *context;
***************
*** 1258,1263 **** show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
--- 1135,1142 ----
  	int			keyno;
  	char	   *exprstr;
  	int			i;
+ 	int			nkeys = ((Sort *) sortplan)->numCols;
+ 	AttrNumber *keycols = ((Sort *) sortplan)->sortColIdx;
  
  	if (nkeys <= 0)
  		return;
***************
*** 1340,1342 **** explain_get_index_name(Oid indexId)
--- 1219,1288 ----
  	}
  	return result;
  }
+ 
+ /*
+  * Explain details for Scan nodes.
+  */
+ static void
+ ExplainScanTarget(StringInfo str, Scan *plan, ExplainState *es)
+ {
+ 	char *objectname = NULL;
+ 	Node *funcexpr;
+ 	RangeTblEntry *rte;
+ 
+ 	if (plan->scanrelid <= 0)
+ 		return;
+ 	rte = rt_fetch(plan->scanrelid, es->rtable);
+ 
+ 	switch (nodeTag(plan))
+ 	{
+ 		case T_IndexScan:
+ 		case T_SeqScan:
+ 		case T_BitmapHeapScan:
+ 		case T_TidScan:
+ 			/* Assert it's on a real relation */
+ 			Assert(rte->rtekind == RTE_RELATION);
+ 			objectname = get_rel_name(rte->relid);
+ 			break;
+ 		case T_FunctionScan:
+ 			/* Assert it's on a RangeFunction */
+ 			Assert(rte->rtekind == RTE_FUNCTION);
+ 
+ 			/*
+ 			 * If the expression is still a function call, we can get the
+ 			 * real name of the function.  Otherwise, punt (this can
+ 			 * happen if the optimizer simplified away the function call,
+ 			 * for example).
+ 			 */
+ 			funcexpr = ((FunctionScan *) plan)->funcexpr;
+ 			if (funcexpr && IsA(funcexpr, FuncExpr))
+ 			{
+ 				Oid			funcid = ((FuncExpr *) funcexpr)->funcid;
+ 				objectname = get_func_name(funcid);
+ 			}
+ 			break;
+ 		case T_ValuesScan:
+ 			Assert(rte->rtekind == RTE_VALUES);
+ 			break;
+ 		case T_CteScan:
+ 			/* Assert it's on a non-self-reference CTE */
+ 			Assert(rte->rtekind == RTE_CTE);
+ 			Assert(!rte->self_reference);
+ 			objectname = rte->ctename;
+ 			break;
+ 		case T_WorkTableScan:
+ 			/* Assert it's on a self-reference CTE */
+ 			Assert(rte->rtekind == RTE_CTE);
+ 			Assert(rte->self_reference);
+ 			objectname = rte->ctename;
+ 			break;
+ 		default:
+ 			break;
+ 	}
+ 
+ 	appendStringInfoString(str, " on");
+ 	if (objectname != NULL)
+ 		appendStringInfo(str, " %s", quote_identifier(objectname));
+ 	if (objectname == NULL || strcmp(rte->eref->aliasname, objectname) != 0)
+ 		appendStringInfo(str, " %s", quote_identifier(rte->eref->aliasname));
+ }


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic