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

📄 recipe.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
					if (p->param_tlist)					{						/*						 * we have a parameter with an attribute like						 * $N.foo so replace it with a new var node						 */						/* param tlist can only have one entry in them! */						param_tle = (TargetEntry *) (lfirst(p->param_tlist));						oldVar = (Var *) param_tle->expr;						oldVar->varno = rt_ind;						oldVar->varnoold = rt_ind;						return (Node *) oldVar;					}					else					{						/* we have $N without the .foo */						bool		defined;						bool		isRel;						/*						 * TODO here, we need to check to see whether the						 * type of the tee is a complex type (relation) or						 * a simple type						 */						/*						 * if it is a simple type, then we need to get the						 * "result" attribute from the tee relation						 */						isRel = (typeidTypeRelid(p->paramtype) != 0);						if (isRel)						{							newVar = makeVar(rt_ind,											 0, /* the whole tuple */										   TypeGet(teeRelName, &defined),											 -1,											 0,											 rt_ind,											 0);							return (Node *) newVar;						}						else							newVar = makeVar(rt_ind,											 1, /* just the first field,												 * which is 'result' */										   TypeGet(teeRelName, &defined),											 -1,											 0,											 rt_ind,											 0);						return (Node *) newVar;					}				}				else					elog(NOTICE, "tg_replaceNumberedParam: unexpected paramkind value of %d", p->paramkind);			}			break;		case T_Expr:			{				/*				 * the node is an expression, we need to recursively call				 * ourselves until we find parameter nodes				 */				List	   *l;				Expr	   *expr = (Expr *) expression;				List	   *newArgs;				/*				 * we have to make a new args lists because Params can be				 * replaced by Var nodes in tg_replaceNumberedParam()				 */				newArgs = NIL;				/*				 * we only care about argument to expressions, it doesn't				 * matter when the opType is				 */				/* recursively rewrite the arguments of this expression */				foreach(l, expr->args)				{					newArgs = lappend(newArgs,									  tg_replaceNumberedParam(lfirst(l),															  pnum,															  rt_ind,															teeRelName));				}				/* change the arguments of the expression */				expr->args = newArgs;			}			break;		default:			{				/* ignore other expr types */			}	}	return expression;}/* tg_rewriteParamsInExpr:   rewrite the params in expressions by using the targetlist entries   from the input parsetrees   this procedure recursively calls itself   it returns a (possibly modified) Node*.*/static Node *tg_rewriteParamsInExpr(Node *expression, QueryTreeList * inputQlist){	List	   *tl;	TargetEntry *param_tle,			   *tle;	Param	   *p;	int			childno;	char	   *resname;	if (expression == NULL)		return NULL;	switch (nodeTag(expression))	{		case T_Param:			{				/*				 * the node is a parameter, substitute the entry from the				 * target list of the child that corresponds to the				 * parameter number				 */				p = (Param *) expression;				/* we only deal with the case of numbered parameters */				if (p->paramkind == PARAM_NUM)				{					/* paramid's start from 1 */					childno = p->paramid - 1;					if (p->param_tlist)					{						/*						 * we have a parameter with an attribute like						 * $N.foo so match the resname "foo" against the						 * target list of the (N-1)th inputQlist						 */						/* param tlist can only have one entry in them! */						param_tle = (TargetEntry *) (lfirst(p->param_tlist));						resname = param_tle->resdom->resname;						if (inputQlist->qtrees[childno])						{							foreach(tl, inputQlist->qtrees[childno]->targetList)							{								tle = lfirst(tl);								if (strcmp(resname, tle->resdom->resname) == 0)									return tle->expr;							}						}						else							elog(ERROR, "tg_rewriteParamsInExpr:can't substitute for parameter %d when that input is unconnected", p->paramid);					}					else					{						/* we have $N without the .foo */						/* use the first resdom in the targetlist of the */						/* appropriate child query */						tl = inputQlist->qtrees[childno]->targetList;						tle = lfirst(tl);						return tle->expr;					}				}				else					elog(NOTICE, "tg_rewriteParamsInExpr: unexpected paramkind value of %d", p->paramkind);			}			break;		case T_Expr:			{				/*				 * the node is an expression, we need to recursively call				 * ourselves until we find parameter nodes				 */				List	   *l;				Expr	   *expr = (Expr *) expression;				List	   *newArgs;				/*				 * we have to make a new args lists because Params can be				 * replaced by Var nodes in tg_rewriteParamsInExpr()				 */				newArgs = NIL;				/*				 * we only care about argument to expressions, it doesn't				 * matter when the opType is				 */				/* recursively rewrite the arguments of this expression */				foreach(l, expr->args)				{					newArgs = lappend(newArgs,						  tg_rewriteParamsInExpr(lfirst(l), inputQlist));				}				/* change the arguments of the expression */				expr->args = newArgs;			}			break;		default:			{				/* ignore other expr types */			}	}	return expression;}/*   getParamTypes:	  given an element, finds its parameter types.	  the typev array argument is set to the parameter types.	  the parameterCount is returned   this code is very similar to ProcedureDefine() in pg_proc.c*/static intgetParamTypes(TgElement * elem, Oid *typev){	/* this code is similar to ProcedureDefine() */	int16		parameterCount;	bool		defined;	Oid			toid;	char	   *t;	int			i,				j;	parameterCount = 0;	for (i = 0; i < 8; i++)		typev[i] = 0;	for (j = 0; j < elem->inTypes->num; j++)	{		if (parameterCount == 8)		{			elog(ERROR,				 "getParamTypes: Ingredients cannot take > 8 arguments");		}		t = elem->inTypes->val[j];		if (strcmp(t, "opaque") == 0)		{			elog(ERROR,				 "getParamTypes: Ingredient functions cannot take type 'opaque'");		}		else		{			toid = TypeGet(elem->inTypes->val[j], &defined);			if (!OidIsValid(toid))				elog(ERROR, "getParamTypes: arg type '%s' is not defined", t);			if (!defined)				elog(NOTICE, "getParamTypes: arg type '%s' is only a shell", t);		}		typev[parameterCount++] = toid;	}	return parameterCount;}/* * tg_parseTeeNode * *	 handles the parsing of the tee node * * */static QueryTreeList *tg_parseTeeNode(TgRecipe * r,				TgNode * n,		/* the tee node */				int i,			/* which input this node is to its parent */				QueryTreeList * qList,				TeeInfo * teeInfo){	QueryTreeList *q;	char	   *tt;	int			rt_ind;	Query	   *orig;	/*	 * the input Node is a tee node, so we need to do the following: we	 * need to parse the child of the tee node, we add that to our query	 * tree list we need the name of the tee node table the tee node table	 * is the table into which the tee node may materialize results.  Call	 * it TT we add a range table to our existing query with TT in it we	 * need to replace the parameter $i with TT (otherwise the optimizer	 * won't know to use the table on expression containining $i) After	 * that rewrite, the optimizer will generate sequential scans of TT	 *	 * Later, in the glue phase, we replace all instances of TT sequential	 * scans with the actual Tee node	 */	q = tg_parseSubQuery(r, n, teeInfo);	/* tt is the name of the tee node table */	tt = n->nodeName;	if (q)		appendTeeQuery(teeInfo, q, tt);	orig = qList->qtrees[0];	rt_ind = RangeTablePosn(orig->rtable, tt);	/*	 * check to see that this table is not part of the range table	 * already.  This usually only happens if multiple inputs are	 * connected to the same Tee.	 */	if (rt_ind == 0)	{		orig->rtable = lappend(orig->rtable,							   addRangeTableEntry(NULL,												  tt,												  tt,												  FALSE,												  FALSE));		rt_ind = length(orig->rtable);	}	orig->qual = tg_replaceNumberedParam(orig->qual,										 i + 1, /* params start at 1 */										 rt_ind,										 tt);	return qList;}/* * tg_parseSubQuery: *	  go backwards from a node and parse the query * *	 the result parse tree is passed back * * could return NULL if trying to parse a teeNode * that's already been processed by another parent * */static QueryTreeList *tg_parseSubQuery(TgRecipe * r, TgNode * n, TeeInfo * teeInfo){	TgElement  *elem;	char	   *funcName;	Oid			typev[8],		/* eight arguments maximum	*/				relid;	int			i,				parameterCount;	QueryTreeList *qList;		/* the parse tree of the nodeElement */	QueryTreeList *inputQlist;	/* the list of parse trees for the inputs								 * to this node */	QueryTreeList *q;	TgNode	   *child;	Relation	rel;	unsigned int len;	TupleDesc	tupdesc;	qList = NULL;	if (n->nodeType == TG_INGRED_NODE)	{		/* parse each ingredient node in turn */		elem = n->nodeElem;		switch (elem->srcLang)		{			case TG_SQL:				{					/*					 * for SQL ingredients, the SQL query is contained in					 * the 'src' field					 */#ifdef DEBUG_RECIPE					elog(NOTICE, "calling parser with %s", elem->src);#endif	 /* DEBUG_RECIPE */					parameterCount = getParamTypes(elem, typev);					qList = parser(elem->src, typev, parameterCount);					if (qList->len > 1)					{						elog(NOTICE,							 "tg_parseSubQuery: parser produced > 1 query tree");					}				}				break;			case TG_C:				{					/* C ingredients are registered functions in postgres */					/*					 * we create a new query string by using the function					 * name (found in the 'src' field) and adding					 * parameters to it so if the function was FOOBAR and					 * took in two arguments, we would create a string					 * select FOOBAR($1,$2)					 */					char		newquery[1000];					funcName = elem->src;					parameterCount = getParamTypes(elem, typev);					if (parameterCount > 0)					{						int			i;						snprintf(newquery, 1000, "select %s($1", funcName);						for (i = 1; i < parameterCount; i++)							snprintf(newquery, 1000, "%s,$%d", pstrdup(newquery), i);						snprintf(newquery, 1000, "%s)", pstrdup(newquery));					}					else						snprintf(newquery, 1000, "select %s()", funcName);#ifdef DEBUG_RECIPE					elog(NOTICE, "calling parser with %s", newquery);#endif	 /* DEBUG_RECIPE */

⌨️ 快捷键说明

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