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

📄 parse_target.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
			while (ilist != NIL)			{				A_Indices  *ind = lfirst(ilist);				ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);				ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);				ilist = lnext(ilist);			}		}		res->name = colname;		return MakeTargetEntryExpr(pstate, res->name, expr,								   res->indirection, false);	}}/* *	MakeTargetEntryAttr() *	Make a TargetEntry from a complex node. */static TargetEntry *MakeTargetEntryAttr(ParseState *pstate,					ResTarget *res){	Oid			type_id;	int32		type_mod;	Attr	   *att = (Attr *) res->val;	Node	   *result;	char	   *attrname;	char	   *resname;	Resdom	   *resnode;	int			resdomno;	List	   *attrs = att->attrs;	TargetEntry *tent;	attrname = strVal(lfirst(att->attrs));	/*	 * Target item is fully specified: ie. relation.attribute	 */	result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST);	handleTargetColname(pstate, &res->name, att->relname, attrname);	if (att->indirection != NIL)	{		List	   *ilist = att->indirection;		while (ilist != NIL)		{			A_Indices  *ind = lfirst(ilist);			ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);			ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);			ilist = lnext(ilist);		}		result = (Node *) make_array_ref(result, att->indirection);	}	type_id = exprType(result);	if (nodeTag(result) == T_Var)		type_mod = ((Var *) result)->vartypmod;	else		type_mod = -1;	/* move to last entry */	while (lnext(attrs) != NIL)		attrs = lnext(attrs);	resname = (res->name) ? res->name : strVal(lfirst(attrs));	if (pstate->p_is_insert || pstate->p_is_update)	{		Relation	rd;		/*		 * insert or update query -- insert, update work only on one		 * relation, so multiple occurence of same resdomno is bogus		 */		rd = pstate->p_target_relation;		Assert(rd != NULL);		resdomno = attnameAttNum(rd, res->name);	}	else		resdomno = pstate->p_last_resno++;	resnode = makeResdom((AttrNumber) resdomno,						 (Oid) type_id,						 type_mod,						 resname,						 (Index) 0,						 (Oid) 0,						 false);	tent = makeNode(TargetEntry);	tent->resdom = resnode;	tent->expr = result;	return tent;}/* transformTargetList() * Turns a list of ResTarget's into a list of TargetEntry's. */List *transformTargetList(ParseState *pstate, List *targetlist){	List	   *p_target = NIL;	List	   *tail_p_target = NIL;	while (targetlist != NIL)	{		ResTarget  *res = (ResTarget *) lfirst(targetlist);		TargetEntry *tent = NULL;		switch (nodeTag(res->val))		{			case T_Ident:				{					char	   *identname;					identname = ((Ident *) res->val)->name;					tent = MakeTargetEntryIdent(pstate,												(Node *) res->val, &res->name, NULL, identname, false);					break;				}			case T_ParamNo:			case T_FuncCall:			case T_A_Const:			case T_A_Expr:				{					tent = MakeTargetEntryComplex(pstate, res);					break;				}			case T_CaseExpr:				{					tent = MakeTargetEntryCase(pstate, res);					break;				}			case T_Attr:				{					bool		expand_star = false;					char	   *attrname;					Attr	   *att = (Attr *) res->val;					/*					 * Target item is a single '*', expand all tables (eg.					 * SELECT * FROM emp)					 */					if (att->relname != NULL && !strcmp(att->relname, "*"))					{						if (tail_p_target == NIL)							p_target = tail_p_target = ExpandAllTables(pstate);						else							lnext(tail_p_target) = ExpandAllTables(pstate);						expand_star = true;					}					else					{						/*						 * Target item is relation.*, expand the table						 * (eg. SELECT emp.*, dname FROM emp, dept)						 */						attrname = strVal(lfirst(att->attrs));						if (att->attrs != NIL && !strcmp(attrname, "*"))						{							/*							 * tail_p_target is the target list we're							 * building in the while loop. Make sure we							 * fix it after appending more nodes.							 */							if (tail_p_target == NIL)								p_target = tail_p_target = expandAll(pstate, att->relname,									att->relname, &pstate->p_last_resno);							else								lnext(tail_p_target) = expandAll(pstate, att->relname, att->relname,												  &pstate->p_last_resno);							expand_star = true;						}					}					if (expand_star)					{						while (lnext(tail_p_target) != NIL)							/* make sure we point to the last target entry */							tail_p_target = lnext(tail_p_target);						/*						 * skip rest of while loop						 */						targetlist = lnext(targetlist);						continue;					}					else					{						tent = MakeTargetEntryAttr(pstate, res);						break;					}				}			default:				/* internal error */				elog(ERROR, "Unable to transform targetlist (internal error)");				break;		}		if (p_target == NIL)			p_target = tail_p_target = lcons(tent, NIL);		else		{			lnext(tail_p_target) = lcons(tent, NIL);			tail_p_target = lnext(tail_p_target);		}		targetlist = lnext(targetlist);	}	return p_target;}	/* transformTargetList() */Node *CoerceTargetExpr(ParseState *pstate,				 Node *expr,				 Oid type_id,				 Oid attrtype){	if (can_coerce_type(1, &type_id, &attrtype))		expr = coerce_type(pstate, expr, type_id, attrtype, -1);#ifndef DISABLE_STRING_HACKS	/*	 * string hacks to get transparent conversions w/o explicit	 * conversions	 */	else if ((attrtype == BPCHAROID) || (attrtype == VARCHAROID))	{		Oid			text_id = TEXTOID;		if (type_id == TEXTOID)		{		}		else if (can_coerce_type(1, &type_id, &text_id))			expr = coerce_type(pstate, expr, type_id, text_id, -1);		else			expr = NULL;	}#endif	else		expr = NULL;	return expr;}	/* CoerceTargetExpr() *//* SizeTargetExpr() * Apparently going to a fixed-length string? * Then explicitly size for storage... */static Node *SizeTargetExpr(ParseState *pstate,			   Node *expr,			   Oid attrtype,			   int32 attrtypmod){	int			i;	HeapTuple	ftup;	char	   *funcname;	Oid			oid_array[MAXFARGS];	FuncCall   *func;	A_Const    *cons;	funcname = typeidTypeName(attrtype);	oid_array[0] = attrtype;	oid_array[1] = INT4OID;	for (i = 2; i < MAXFARGS; i++)		oid_array[i] = InvalidOid;	/* attempt to find with arguments exactly as specified... */	ftup = SearchSysCacheTuple(PRONAME,							   PointerGetDatum(funcname),							   Int32GetDatum(2),							   PointerGetDatum(oid_array),							   0);	if (HeapTupleIsValid(ftup))	{		func = makeNode(FuncCall);		func->funcname = funcname;		cons = makeNode(A_Const);		cons->val.type = T_Integer;		cons->val.val.ival = attrtypmod;		func->args = lappend(lcons(expr, NIL), cons);		expr = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST);	}	return expr;}	/* SizeTargetExpr() *//* * makeTargetNames - *	  generate a list of column names if not supplied or *	  test supplied column names to make sure they are in target table *	  (used exclusively for inserts) */List *makeTargetNames(ParseState *pstate, List *cols){	List	   *tl = NULL;	/* Generate ResTarget if not supplied */	if (cols == NIL)	{		int			numcol;		int			i;		Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;		numcol = pstate->p_target_relation->rd_rel->relnatts;		for (i = 0; i < numcol; i++)		{			Ident	   *id = makeNode(Ident);			id->name = palloc(NAMEDATALEN);			StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);			id->indirection = NIL;			id->isRel = false;			if (tl == NIL)				cols = tl = lcons(id, NIL);			else			{				lnext(tl) = lcons(id, NIL);				tl = lnext(tl);			}		}	}	else	{		foreach(tl, cols)		{			List	   *nxt;			char	   *name = ((Ident *) lfirst(tl))->name;			/* elog on failure */			attnameAttNum(pstate->p_target_relation, name);			foreach(nxt, lnext(tl))				if (!strcmp(name, ((Ident *) lfirst(nxt))->name))				elog(ERROR, "Attribute '%s' should be specified only once", name);		}	}	return cols;}/* * ExpandAllTables - *	  turns '*' (in the target list) into a list of attributes *	   (of all relations in the range table) */static List *ExpandAllTables(ParseState *pstate){	List	   *target = NIL;	List	   *legit_rtable = NIL;	List	   *rt,			   *rtable;	rtable = pstate->p_rtable;	if (pstate->p_is_rule)	{		/*		 * skip first two entries, "*new*" and "*current*"		 */		rtable = lnext(lnext(pstate->p_rtable));	}	/* SELECT *; */	if (rtable == NULL)		elog(ERROR, "Wildcard with no tables specified.");	/*	 * go through the range table and make a list of range table entries	 * which we will expand.	 */	foreach(rt, rtable)	{		RangeTblEntry *rte = lfirst(rt);		/*		 * we only expand those specify in the from clause. (This will		 * also prevent us from using the wrong table in inserts: eg.		 * tenk2 in "insert into tenk2 select * from tenk1;")		 */		if (!rte->inFromCl)			continue;		legit_rtable = lappend(legit_rtable, rte);	}	foreach(rt, legit_rtable)	{		RangeTblEntry *rte = lfirst(rt);		List	   *temp = target;		if (temp == NIL)			target = expandAll(pstate, rte->relname, rte->refname,							   &pstate->p_last_resno);		else		{			while (temp != NIL && lnext(temp) != NIL)				temp = lnext(temp);			lnext(temp) = expandAll(pstate, rte->relname, rte->refname,									&pstate->p_last_resno);		}	}	return target;}/* * FigureColname - *	  if the name of the resulting column is not specified in the target *	  list, we have to guess. * */static char *FigureColname(Node *expr, Node *resval){	switch (nodeTag(expr))	{			case T_Aggref:			return (char *) ((Aggref *) expr)->aggname;		case T_Expr:			if (((Expr *) expr)->opType == FUNC_EXPR)			{				if (nodeTag(resval) == T_FuncCall)					return ((FuncCall *) resval)->funcname;			}			break;		case T_CaseExpr:			{				char	   *name;				name = FigureColname(((CaseExpr *) expr)->defresult, resval);				if (!strcmp(name, "?column?"))					name = "case";				return name;			}			break;		default:			break;	}	return "?column?";}

⌨️ 快捷键说明

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