⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 explain.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
					appendStringInfo(str, " %s",								 quote_identifier(rte->eref->aliasname));			}			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);				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).				 */				if (rte->funcexpr && IsA(rte->funcexpr, FuncExpr))				{					FuncExpr   *funcexpr = (FuncExpr *) rte->funcexpr;					Oid			funcid = 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;		default:			break;	}	if (es->printCost)	{		appendStringInfo(str, "  (cost=%.2f..%.2f rows=%.0f width=%d)",						 plan->startup_cost, plan->total_cost,						 plan->plan_rows, plan->plan_width);		/*		 * We have to forcibly clean up the instrumentation state because		 * we haven't done ExecutorEnd yet.  This is pretty grotty ...		 */		InstrEndLoop(planstate->instrument);		if (planstate->instrument && planstate->instrument->nloops > 0)		{			double		nloops = planstate->instrument->nloops;			appendStringInfo(str, " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",						1000.0 * planstate->instrument->startup / nloops,						  1000.0 * planstate->instrument->total / nloops,							 planstate->instrument->ntuples / nloops,							 planstate->instrument->nloops);		}		else if (es->printAnalyze)			appendStringInfo(str, " (never executed)");	}	appendStringInfoChar(str, '\n');	/* quals, sort keys, etc */	switch (nodeTag(plan))	{		case T_IndexScan:			show_scan_qual(((IndexScan *) plan)->indxqualorig, true,						   "Index Cond",						   ((Scan *) plan)->scanrelid,						   outer_plan,						   str, indent, es);			show_scan_qual(plan->qual, false,						   "Filter",						   ((Scan *) plan)->scanrelid,						   outer_plan,						   str, indent, es);			break;		case T_SeqScan:		case T_TidScan:		case T_SubqueryScan:		case T_FunctionScan:			show_scan_qual(plan->qual, false,						   "Filter",						   ((Scan *) plan)->scanrelid,						   outer_plan,						   str, indent, es);			break;		case T_NestLoop:			show_upper_qual(((NestLoop *) plan)->join.joinqual,							"Join Filter",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			show_upper_qual(plan->qual,							"Filter",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			break;		case T_MergeJoin:			show_upper_qual(((MergeJoin *) plan)->mergeclauses,							"Merge Cond",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			show_upper_qual(((MergeJoin *) plan)->join.joinqual,							"Join Filter",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			show_upper_qual(plan->qual,							"Filter",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			break;		case T_HashJoin:			show_upper_qual(((HashJoin *) plan)->hashclauses,							"Hash Cond",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			show_upper_qual(((HashJoin *) plan)->join.joinqual,							"Join Filter",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			show_upper_qual(plan->qual,							"Filter",							"outer", OUTER, outerPlan(plan),							"inner", INNER, innerPlan(plan),							str, indent, es);			break;		case T_Agg:		case T_Group:			show_upper_qual(plan->qual,							"Filter",							"subplan", 0, outerPlan(plan),							"", 0, NULL,							str, indent, es);			break;		case T_Sort:			show_sort_keys(plan->targetlist,						   ((Sort *) plan)->numCols,						   ((Sort *) plan)->sortColIdx,						   "Sort Key",						   str, indent, es);			break;		case T_Result:			show_upper_qual((List *) ((Result *) plan)->resconstantqual,							"One-Time Filter",							"subplan", OUTER, outerPlan(plan),							"", 0, NULL,							str, indent, es);			show_upper_qual(plan->qual,							"Filter",							"subplan", OUTER, outerPlan(plan),							"", 0, NULL,							str, indent, es);			break;		default:			break;	}	/* initPlan-s */	if (plan->initPlan)	{		List	   *saved_rtable = es->rtable;		List	   *lst;		for (i = 0; i < indent; i++)			appendStringInfo(str, "  ");		appendStringInfo(str, "  InitPlan\n");		foreach(lst, planstate->initPlan)		{			SubPlanState *sps = (SubPlanState *) lfirst(lst);			SubPlan    *sp = (SubPlan *) sps->xprstate.expr;			es->rtable = sp->rtable;			for (i = 0; i < indent; i++)				appendStringInfo(str, "  ");			appendStringInfo(str, "    ->  ");			explain_outNode(str, sp->plan,							sps->planstate,							NULL,							indent + 4, es);		}		es->rtable = saved_rtable;	}	/* lefttree */	if (outerPlan(plan))	{		for (i = 0; i < indent; i++)			appendStringInfo(str, "  ");		appendStringInfo(str, "  ->  ");		explain_outNode(str, outerPlan(plan),						outerPlanState(planstate),						NULL,						indent + 3, es);	}	/* righttree */	if (innerPlan(plan))	{		for (i = 0; i < indent; i++)			appendStringInfo(str, "  ");		appendStringInfo(str, "  ->  ");		explain_outNode(str, innerPlan(plan),						innerPlanState(planstate),						outerPlan(plan),						indent + 3, es);	}	if (IsA(plan, Append))	{		Append	   *appendplan = (Append *) plan;		AppendState *appendstate = (AppendState *) planstate;		List	   *lst;		int			j;		j = 0;		foreach(lst, appendplan->appendplans)		{			Plan	   *subnode = (Plan *) lfirst(lst);			for (i = 0; i < indent; i++)				appendStringInfo(str, "  ");			appendStringInfo(str, "  ->  ");			explain_outNode(str, subnode,							appendstate->appendplans[j],							NULL,							indent + 3, es);			j++;		}	}	if (IsA(plan, SubqueryScan))	{		SubqueryScan *subqueryscan = (SubqueryScan *) plan;		SubqueryScanState *subquerystate = (SubqueryScanState *) planstate;		Plan	   *subnode = subqueryscan->subplan;		RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid,									  es->rtable);		List	   *saved_rtable = es->rtable;		Assert(rte->rtekind == RTE_SUBQUERY);		es->rtable = rte->subquery->rtable;		for (i = 0; i < indent; i++)			appendStringInfo(str, "  ");		appendStringInfo(str, "  ->  ");		explain_outNode(str, subnode,						subquerystate->subplan,						NULL,						indent + 3, es);		es->rtable = saved_rtable;	}	/* subPlan-s */	if (planstate->subPlan)	{		List	   *saved_rtable = es->rtable;		List	   *lst;		for (i = 0; i < indent; i++)			appendStringInfo(str, "  ");		appendStringInfo(str, "  SubPlan\n");		foreach(lst, planstate->subPlan)		{			SubPlanState *sps = (SubPlanState *) lfirst(lst);			SubPlan    *sp = (SubPlan *) sps->xprstate.expr;			es->rtable = sp->rtable;			for (i = 0; i < indent; i++)				appendStringInfo(str, "  ");			appendStringInfo(str, "    ->  ");			explain_outNode(str, sp->plan,							sps->planstate,							NULL,							indent + 4, es);		}		es->rtable = saved_rtable;	}}/* * Show a qualifier expression for a scan plan node */static voidshow_scan_qual(List *qual, bool is_or_qual, const char *qlabel,			   int scanrelid, Plan *outer_plan,			   StringInfo str, int indent, ExplainState *es){	RangeTblEntry *rte;	Node	   *scancontext;	Node	   *outercontext;	List	   *context;	Node	   *node;	char	   *exprstr;	int			i;	/* No work if empty qual */	if (qual == NIL)		return;	if (is_or_qual)	{		if (lfirst(qual) == NIL && lnext(qual) == NIL)			return;	}	/* Fix qual --- indexqual requires different processing */	if (is_or_qual)		node = make_ors_ands_explicit(qual);	else		node = (Node *) make_ands_explicit(qual);	/* Generate deparse context */	Assert(scanrelid > 0 && scanrelid <= length(es->rtable));	rte = rt_fetch(scanrelid, es->rtable);	scancontext = deparse_context_for_rte(rte);	/*	 * If we have an outer plan that is referenced by the qual, add it to	 * the deparse context.  If not, don't (so that we don't force	 * prefixes unnecessarily).	 */	if (outer_plan)	{		Relids		varnos = pull_varnos(node);		if (bms_is_member(OUTER, varnos))			outercontext = deparse_context_for_subplan("outer",												  outer_plan->targetlist,													   es->rtable);		else			outercontext = NULL;		bms_free(varnos);	}	else		outercontext = NULL;	context = deparse_context_for_plan(scanrelid, scancontext,									   OUTER, outercontext,									   NIL);	/* Deparse the expression */	exprstr = deparse_expression(node, context, (outercontext != NULL), false);	/* And add to str */	for (i = 0; i < indent; i++)		appendStringInfo(str, "  ");	appendStringInfo(str, "  %s: %s\n", qlabel, exprstr);}/* * Show a qualifier expression for an upper-level plan node */static voidshow_upper_qual(List *qual, const char *qlabel,				const char *outer_name, int outer_varno, Plan *outer_plan,				const char *inner_name, int inner_varno, Plan *inner_plan,				StringInfo str, int indent, ExplainState *es){	List	   *context;	Node	   *outercontext;	Node	   *innercontext;	Node	   *node;	char	   *exprstr;	int			i;	/* No work if empty qual */	if (qual == NIL)		return;	/* Generate deparse context */	if (outer_plan)		outercontext = deparse_context_for_subplan(outer_name,												   outer_plan->targetlist,												   es->rtable);	else		outercontext = NULL;	if (inner_plan)		innercontext = deparse_context_for_subplan(inner_name,												   inner_plan->targetlist,												   es->rtable);	else		innercontext = NULL;	context = deparse_context_for_plan(outer_varno, outercontext,									   inner_varno, innercontext,									   NIL);	/* Deparse the expression */	node = (Node *) make_ands_explicit(qual);	exprstr = deparse_expression(node, context, (inner_plan != NULL), false);	/* And add to str */	for (i = 0; i < indent; i++)		appendStringInfo(str, "  ");	appendStringInfo(str, "  %s: %s\n", qlabel, exprstr);}/* * Show the sort keys for a Sort node. */static voidshow_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,			   const char *qlabel,			   StringInfo str, int indent, ExplainState *es){	List	   *context;	bool		useprefix;	int			keyno;	char	   *exprstr;	Relids		varnos;	int			i;	if (nkeys <= 0)		return;	for (i = 0; i < indent; i++)		appendStringInfo(str, "  ");	appendStringInfo(str, "  %s: ", qlabel);	/*	 * In this routine we expect that the plan node's tlist has not been	 * processed by set_plan_references().	Normally, any Vars will	 * contain valid varnos referencing the actual rtable.	But we might	 * instead be looking at a dummy tlist generated by prepunion.c; if	 * there are Vars with zero varno, use the tlist itself to determine	 * their names.	 */	varnos = pull_varnos((Node *) tlist);	if (bms_is_member(0, varnos))	{		Node	   *outercontext;		outercontext = deparse_context_for_subplan("sort",												   tlist,												   es->rtable);		context = deparse_context_for_plan(0, outercontext,										   0, NULL,										   NIL);		useprefix = false;	}	else	{		context = deparse_context_for_plan(0, NULL,										   0, NULL,										   es->rtable);		useprefix = length(es->rtable) > 1;	}	bms_free(varnos);	for (keyno = 0; keyno < nkeys; keyno++)	{		/* find key expression in tlist */		AttrNumber	keyresno = keycols[keyno];		TargetEntry *target = get_tle_by_resno(tlist, keyresno);		if (!target)			elog(ERROR, "no tlist entry for key %d", keyresno);		/* Deparse the expression, showing any top-level cast */		exprstr = deparse_expression((Node *) target->expr, context,									 useprefix, true);		/* And add to str */		if (keyno > 0)			appendStringInfo(str, ", ");		appendStringInfo(str, "%s", exprstr);	}	appendStringInfo(str, "\n");}/* * Indexscan qual lists have an implicit OR-of-ANDs structure.	Make it * explicit so deparsing works properly. */static Node *make_ors_ands_explicit(List *orclauses){	if (orclauses == NIL)		return NULL;			/* probably can't happen */	else if (lnext(orclauses) == NIL)		return (Node *) make_ands_explicit(lfirst(orclauses));	else	{		FastList	args;		List	   *orptr;		FastListInit(&args);		foreach(orptr, orclauses)			FastAppend(&args, make_ands_explicit(lfirst(orptr)));		return (Node *) make_orclause(FastListValue(&args));	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -