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

📄 recipe.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
					qList = parser(newquery, typev, parameterCount);					if (qList->len > 1)					{						elog(NOTICE,							 "tg_parseSubQuery: parser produced > 1 query tree");					}				}				break;			case TG_RECIPE_GRAPH:				elog(NOTICE, "tg_parseSubQuery: can't parse recipe graph ingredients yet!");				break;			case TG_COMPILED:				elog(NOTICE, "tg_parseSubQuery: can't parse compiled ingredients yet!");				break;			default:				elog(NOTICE, "tg_parseSubQuery: unknown srcLang: %d", elem->srcLang);		}		/* parse each of the subrecipes that are input to this node */		if (n->inNodes->num > 0)		{			inputQlist = malloc(sizeof(QueryTreeList));			inputQlist->len = n->inNodes->num + 1;			inputQlist->qtrees = (Query **) malloc(inputQlist->len * sizeof(Query *));			for (i = 0; i < n->inNodes->num; i++)			{				inputQlist->qtrees[i] = NULL;				if (n->inNodes->val[i])				{					if (n->inNodes->val[i]->nodeType == TG_TEE_NODE)					{						qList = tg_parseTeeNode(r, n->inNodes->val[i],												i, qList, teeInfo);					}					else					{			/* input node is not a Tee */						q = tg_parseSubQuery(r, n->inNodes->val[i],											 teeInfo);						Assert(q->len == 1);						inputQlist->qtrees[i] = q->qtrees[0];					}				}			}			/* now, we have all the query trees from our input nodes */			/* transform the original parse tree appropriately */			tg_rewriteQuery(r, n, qList, inputQlist);		}	}	else if (n->nodeType == TG_EYE_NODE)	{		/*		 * if we hit an eye, we need to stop and make what we have into a		 * subrecipe query block		 */		elog(NOTICE, "tg_parseSubQuery: can't handle eye nodes yet");	}	else if (n->nodeType == TG_TEE_NODE)	{		/*		 * if we hit a tee, check to see if the parsing has been done for		 * this tee already by the other parent		 */		rel = RelationNameGetRelation(n->nodeName);		if (RelationIsValid(rel))		{			/*			 * this tee has already been visited, no need to do any			 * further processing			 */			return NULL;		}		else		{			/* we need to process the child of the tee first, */			child = n->inNodes->val[0];			if (child->nodeType == TG_TEE_NODE)			{				/* nested Tee nodes */				qList = tg_parseTeeNode(r, child, 0, qList, teeInfo);				return qList;			}			Assert(child != NULL);			/* parse the input node */			q = tg_parseSubQuery(r, child, teeInfo);			Assert(q->len == 1);			/* add the parsed query to the main list of queries */			qList = appendQlist(qList, q);			/* need to create the tee table here */			/*			 * the tee table created is used both for materializing the			 * values at the tee node, and for parsing and optimization.			 * The optimization needs to have a real table before it will			 * consider scans on it			 */			/*			 * first, find the type of the tuples being produced by the			 * tee.  The type is the same as the output type of the child			 * node.			 *			 * NOTE: we are assuming that the child node only has a single			 * output here!			 */			getParamTypes(child->nodeElem, typev);			/*			 * the output type is either a complex type, (and is thus a			 * relation) or is a simple type			 */			rel = RelationNameGetRelation(child->nodeElem->outTypes->val[0]);			if (RelationIsValid(rel))			{				/*				 * for complex types, create new relation with the same				 * tuple descriptor as the output table type				 */				len = length(q->qtrees[0]->targetList);				tupdesc = rel->rd_att;				relid = heap_create_with_catalog(									   child->nodeElem->outTypes->val[0],									   tupdesc, RELKIND_RELATION, false);			}			else			{				/*				 * we have to create a relation with one attribute of the				 * simple base type.  That attribute will have an attr				 * name of "result"				 */				/* NOTE: ignore array types for the time being */				len = 1;				tupdesc = CreateTemplateTupleDesc(len);				if (!TupleDescInitEntry(tupdesc, 1,										"result",										InvalidOid,										-1, 0, false))					elog(NOTICE, "tg_parseSubQuery: unexpected result from TupleDescInitEntry");				else				{					relid = heap_create_with_catalog(									   child->nodeElem->outTypes->val[0],									   tupdesc, RELKIND_RELATION, false);				}			}		}	}	else if (n->nodeType == TG_RECIPE_NODE)		elog(NOTICE, "tg_parseSubQuery: can't handle embedded recipes yet!");	else		elog(NOTICE, "unknown nodeType: %d", n->nodeType);	return qList;}/* * OffsetVarAttno - *	  recursively find all the var nodes with the specified varno * and offset their varattno with the offset * *	code is similar to OffsetVarNodes in rewriteManip.c */voidOffsetVarAttno(Node *node, int varno, int offset){	if (node == NULL)		return;	switch (nodeTag(node))	{		case T_TargetEntry:			{				TargetEntry *tle = (TargetEntry *) node;				OffsetVarAttno(tle->expr, varno, offset);			}			break;		case T_Expr:			{				Expr	   *expr = (Expr *) node;				OffsetVarAttno((Node *) expr->args, varno, offset);			}			break;		case T_Var:			{				Var		   *var = (Var *) node;				if (var->varno == varno)					var->varattno += offset;			}			break;		case T_List:			{				List	   *l;				foreach(l, (List *) node)					OffsetVarAttno(lfirst(l), varno, offset);			}			break;		default:			/* ignore the others */			break;	}}/* * appendQlist *	  add the contents of a QueryTreeList q2 to the end of the QueryTreeList *	 q1 * *	returns a new querytree list */QueryTreeList *appendQlist(QueryTreeList * q1, QueryTreeList * q2){	QueryTreeList *newq;	int			i,				j;	int			newlen;	if (q1 == NULL)		return q2;	if (q2 == NULL)		return q1;	newlen = q1->len + q2->len;	newq = (QueryTreeList *) malloc(sizeof(QueryTreeList));	newq->len = newlen;	newq->qtrees = (Query **) malloc(newlen * sizeof(Query *));	for (i = 0; i < q1->len; i++)		newq->qtrees[i] = q1->qtrees[i];	for (j = 0; j < q2->len; j++)		newq->qtrees[i + j] = q2->qtrees[j];	return newq;}/* * appendTeeQuery * *	modify the query field of the teeInfo list of the particular tee node */static voidappendTeeQuery(TeeInfo * teeInfo, QueryTreeList * q, char *teeNodeName){	int			i;	Assert(teeInfo);	for (i = 0; i < teeInfo->num; i++)	{		if (strcmp(teeInfo->val[i].tpi_relName, teeNodeName) == 0)		{			Assert(q->len == 1);			teeInfo->val[i].tpi_parsetree = q->qtrees[0];			return;		}	}	elog(NOTICE, "appendTeeQuery: teeNodeName '%s' not found in teeInfo");}/* * replaceSeqScan *	  replaces sequential scans of a specified relation with the tee plan *	the relation is specified by its index in the range table,	 rt_ind * * returns the modified plan * the offset_attno is the offset that needs to be added to the parent's * qual or targetlist because the child plan has been replaced with a tee node */static voidreplaceSeqScan(Plan *plan, Plan *parent,			   int rt_ind, Plan *tplan){	Scan	   *snode;	Tee		   *teePlan;	Result	   *newPlan;	if (plan == NULL)		return;	if (plan->type == T_SeqScan)	{		snode = (Scan *) plan;		if (snode->scanrelid == rt_ind)		{			/*			 * found the sequential scan that should be replaced with the			 * tplan.			 */			/* we replace the plan, but we also need to modify its parent */			/*			 * replace the sequential scan with a Result node the reason			 * we use a result node is so that we get the proper			 * projection behavior.  The Result node is simply (ab)used as			 * a projection node			 */			newPlan = makeNode(Result);			newPlan->plan.cost = 0.0;			newPlan->plan.state = (EState *) NULL;			newPlan->plan.targetlist = plan->targetlist;			newPlan->plan.lefttree = tplan;			newPlan->plan.righttree = NULL;			newPlan->resconstantqual = NULL;			newPlan->resstate = NULL;			/* change all the varno's to 1 */			ChangeVarNodes((Node *) newPlan->plan.targetlist,						   snode->scanrelid, 1);			if (parent)			{				teePlan = (Tee *) tplan;				if (parent->lefttree == plan)					parent->lefttree = (Plan *) newPlan;				else					parent->righttree = (Plan *) newPlan;				if (teePlan->leftParent == NULL)					teePlan->leftParent = (Plan *) newPlan;				else					teePlan->rightParent = (Plan *) newPlan;/* comment for now to test out executor-stuff				if (parent->state) {					ExecInitNode((Plan*)newPlan, parent->state, (Plan*)newPlan);				}*/			}		}	}	else	{		if (plan->lefttree)			replaceSeqScan(plan->lefttree, plan, rt_ind, tplan);		if (plan->righttree)			replaceSeqScan(plan->righttree, plan, rt_ind, tplan);	}}/* * replaceTeeScans *	  places the sequential scans of the Tee table with * a connection to the actual tee plan node */static Plan *replaceTeeScans(Plan *plan, Query *parsetree, TeeInfo * teeInfo){	int			i;	List	   *rtable;	RangeTblEntry *rte;	char		prefix[5];	int			rt_ind;	Plan	   *tplan;	rtable = parsetree->rtable;	if (rtable == NULL)		return plan;	/*	 * look through the range table for the tee relation entry, that will	 * give use the varno we need to detect which sequential scans need to	 * be replaced with tee nodes	 */	rt_ind = 0;	while (rtable != NIL)	{		rte = lfirst(rtable);		rtable = lnext(rtable);		rt_ind++;				/* range table references in varno fields								 * start w/ 1 */		/*		 * look for the "tee_" prefix in the refname, also check to see		 * that the relname and the refname are the same this should		 * eliminate any user-specified table and leave us with the tee		 * table entries only		 */		if ((strlen(rte->refname) < 4) ||			(strcmp(rte->relname, rte->refname) != 0))			continue;		StrNCpy(prefix, rte->refname, 5);		if (strcmp(prefix, "tee_") == 0)		{			/* okay, we found a tee node entry in the range table */			/* find the appropriate plan in the teeInfo list */			tplan = NULL;			for (i = 0; i < teeInfo->num; i++)			{				if (strcmp(teeInfo->val[i].tpi_relName,						   rte->refname) == 0)					tplan = teeInfo->val[i].tpi_plan;			}			if (tplan == NULL)				elog(NOTICE, "replaceTeeScans didn't find the corresponding tee plan");			/*			 * replace the sequential scan node with that var number with			 * the tee plan node			 */			replaceSeqScan(plan, NULL, rt_ind, tplan);		}	}	return plan;}#endif	 /* TIOGA */

⌨️ 快捷键说明

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