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

📄 parse_relation.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	rte->rtekind = RTE_JOIN;	rte->relid = InvalidOid;	rte->subquery = NULL;	rte->jointype = jointype;	rte->joinaliasvars = aliasvars;	rte->alias = alias;	eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL);	numaliases = list_length(eref->colnames);	/* fill in any unspecified alias columns */	if (numaliases < list_length(colnames))		eref->colnames = list_concat(eref->colnames,									 list_copy_tail(colnames, numaliases));	rte->eref = eref;	/*----------	 * Flags:	 * - this RTE should be expanded to include descendant tables,	 * - this RTE is in the FROM clause,	 * - this RTE should be checked for appropriate access rights.	 *	 * Joins are never checked for access rights.	 *----------	 */	rte->inh = false;			/* never true for joins */	rte->inFromCl = inFromCl;	rte->requiredPerms = 0;	rte->checkAsUser = InvalidOid;	/*	 * Add completed RTE to pstate's range table list, but not to join list	 * nor namespace --- caller must do that if appropriate.	 */	if (pstate != NULL)		pstate->p_rtable = lappend(pstate->p_rtable, rte);	return rte;}/* * Has the specified refname been selected FOR UPDATE/FOR SHARE? */static boolisLockedRel(ParseState *pstate, char *refname){	/* Outer loop to check parent query levels as well as this one */	while (pstate != NULL)	{		if (pstate->p_locking_clause)		{			if (pstate->p_locking_clause->lockedRels == NIL)			{				/* all tables used in query */				return true;			}			else			{				/* just the named tables */				ListCell   *l;				foreach(l, pstate->p_locking_clause->lockedRels)				{					char	   *rname = strVal(lfirst(l));					if (strcmp(refname, rname) == 0)						return true;				}			}		}		pstate = pstate->parentParseState;	}	return false;}/* * Add the given RTE as a top-level entry in the pstate's join list * and/or name space lists.  (We assume caller has checked for any * namespace conflicts.) */voidaddRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,			  bool addToJoinList,			  bool addToRelNameSpace, bool addToVarNameSpace){	if (addToJoinList)	{		int			rtindex = RTERangeTablePosn(pstate, rte, NULL);		RangeTblRef *rtr = makeNode(RangeTblRef);		rtr->rtindex = rtindex;		pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);	}	if (addToRelNameSpace)		pstate->p_relnamespace = lappend(pstate->p_relnamespace, rte);	if (addToVarNameSpace)		pstate->p_varnamespace = lappend(pstate->p_varnamespace, rte);}/* * Add a POSTQUEL-style implicit RTE. * * We assume caller has already checked that there is no RTE or join with * a conflicting name. */RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation){	RangeTblEntry *rte;	/* issue warning or error as needed */	warnAutoRange(pstate, relation);	/*	 * Note that we set inFromCl true, so that the RTE will be listed	 * explicitly if the parsetree is ever decompiled by ruleutils.c. This	 * provides a migration path for views/rules that were originally written	 * with implicit-RTE syntax.	 */	rte = addRangeTableEntry(pstate, relation, NULL, false, true);	/* Add to joinlist and relnamespace, but not varnamespace */	addRTEtoQuery(pstate, rte, true, true, false);	return rte;}/* * expandRTE -- expand the columns of a rangetable entry * * This creates lists of an RTE's column names (aliases if provided, else * real names) and Vars for each column.  Only user columns are considered. * If include_dropped is FALSE then dropped columns are omitted from the * results.  If include_dropped is TRUE then empty strings and NULL constants * (not Vars!) are returned for dropped columns. * * rtindex and sublevels_up are the varno and varlevelsup values to use * in the created Vars.  Ordinarily rtindex should match the actual position * of the RTE in its rangetable. * * The output lists go into *colnames and *colvars. * If only one of the two kinds of output list is needed, pass NULL for the * output pointer for the unwanted one. */voidexpandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,		  bool include_dropped,		  List **colnames, List **colvars){	int			varattno;	if (colnames)		*colnames = NIL;	if (colvars)		*colvars = NIL;	switch (rte->rtekind)	{		case RTE_RELATION:			/* Ordinary relation RTE */			expandRelation(rte->relid, rte->eref, rtindex, sublevels_up,						   include_dropped, colnames, colvars);			break;		case RTE_SUBQUERY:			{				/* Subquery RTE */				ListCell   *aliasp_item = list_head(rte->eref->colnames);				ListCell   *tlistitem;				varattno = 0;				foreach(tlistitem, rte->subquery->targetList)				{					TargetEntry *te = (TargetEntry *) lfirst(tlistitem);					if (te->resjunk)						continue;					varattno++;					Assert(varattno == te->resno);					if (colnames)					{						/* Assume there is one alias per target item */						char	   *label = strVal(lfirst(aliasp_item));						*colnames = lappend(*colnames, makeString(pstrdup(label)));						aliasp_item = lnext(aliasp_item);					}					if (colvars)					{						Var		   *varnode;						varnode = makeVar(rtindex, varattno,										  exprType((Node *) te->expr),										  exprTypmod((Node *) te->expr),										  sublevels_up);						*colvars = lappend(*colvars, varnode);					}				}			}			break;		case RTE_FUNCTION:			{				/* Function RTE */				TypeFuncClass functypclass;				Oid			funcrettype;				TupleDesc	tupdesc;				functypclass = get_expr_result_type(rte->funcexpr,													&funcrettype,													&tupdesc);				if (functypclass == TYPEFUNC_COMPOSITE)				{					/* Composite data type, e.g. a table's row type */					Assert(tupdesc);					expandTupleDesc(tupdesc, rte->eref, rtindex, sublevels_up,									include_dropped, colnames, colvars);				}				else if (functypclass == TYPEFUNC_SCALAR)				{					/* Base data type, i.e. scalar */					if (colnames)						*colnames = lappend(*colnames,											linitial(rte->eref->colnames));					if (colvars)					{						Var		   *varnode;						varnode = makeVar(rtindex, 1,										  funcrettype, -1,										  sublevels_up);						*colvars = lappend(*colvars, varnode);					}				}				else if (functypclass == TYPEFUNC_RECORD)				{					List	   *coldeflist = rte->coldeflist;					ListCell   *col;					int			attnum = 0;					foreach(col, coldeflist)					{						ColumnDef  *colDef = lfirst(col);						attnum++;						if (colnames)						{							char	   *attrname;							attrname = pstrdup(colDef->colname);							*colnames = lappend(*colnames, makeString(attrname));						}						if (colvars)						{							Var		   *varnode;							Oid			atttypid;							atttypid = typenameTypeId(colDef->typename);							varnode = makeVar(rtindex,											  attnum,											  atttypid,											  colDef->typename->typmod,											  sublevels_up);							*colvars = lappend(*colvars, varnode);						}					}				}				else				{					/* addRangeTableEntryForFunction should've caught this */					elog(ERROR, "function in FROM has unsupported return type");				}			}			break;		case RTE_JOIN:			{				/* Join RTE */				ListCell   *colname;				ListCell   *aliasvar;				Assert(list_length(rte->eref->colnames) == list_length(rte->joinaliasvars));				varattno = 0;				forboth(colname, rte->eref->colnames, aliasvar, rte->joinaliasvars)				{					Node	   *avar = (Node *) lfirst(aliasvar);					varattno++;					/*					 * During ordinary parsing, there will never be any					 * deleted columns in the join; but we have to check since					 * this routine is also used by the rewriter, and joins					 * found in stored rules might have join columns for					 * since-deleted columns.  This will be signaled by a NULL					 * Const in the alias-vars list.					 */					if (IsA(avar, Const))					{						if (include_dropped)						{							if (colnames)								*colnames = lappend(*colnames,													makeString(pstrdup("")));							if (colvars)								*colvars = lappend(*colvars,												   copyObject(avar));						}						continue;					}					if (colnames)					{						char	   *label = strVal(lfirst(colname));						*colnames = lappend(*colnames,											makeString(pstrdup(label)));					}					if (colvars)					{						Var		   *varnode;						varnode = makeVar(rtindex, varattno,										  exprType(avar),										  exprTypmod(avar),										  sublevels_up);						*colvars = lappend(*colvars, varnode);					}				}			}			break;		default:			elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);	}}/* * expandRelation -- expandRTE subroutine */static voidexpandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up,			   bool include_dropped,			   List **colnames, List **colvars){	Relation	rel;	/* Get the tupledesc and turn it over to expandTupleDesc */	rel = relation_open(relid, AccessShareLock);	expandTupleDesc(rel->rd_att, eref, rtindex, sublevels_up, include_dropped,					colnames, colvars);	relation_close(rel, AccessShareLock);}/* * expandTupleDesc -- expandRTE subroutine */static voidexpandTupleDesc(TupleDesc tupdesc, Alias *eref,				int rtindex, int sublevels_up,				bool include_dropped,				List **colnames, List **colvars){	int			maxattrs = tupdesc->natts;	int			numaliases = list_length(eref->colnames);	int			varattno;	for (varattno = 0; varattno < maxattrs; varattno++)	{		Form_pg_attribute attr = tupdesc->attrs[varattno];		if (attr->attisdropped)		{			if (include_dropped)			{				if (colnames)					*colnames = lappend(*colnames, makeString(pstrdup("")));				if (colvars)				{					/*					 * can't use atttypid here, but it doesn't really matter					 * what type the Const claims to be.					 */					*colvars = lappend(*colvars, makeNullConst(INT4OID));				}			}			continue;		}		if (colnames)		{			char	   *label;			if (varattno < numaliases)				label = strVal(list_nth(eref->colnames, varattno));			else				label = NameStr(attr->attname);			*colnames = lappend(*colnames, makeString(pstrdup(label)));		}		if (colvars)		{			Var		   *varnode;			varnode = makeVar(rtindex, attr->attnum,							  attr->atttypid, attr->atttypmod,							  sublevels_up);			*colvars = lappend(*colvars, varnode);		}	}}/* * expandRelAttrs - *	  Workhorse for "*" expansion: produce a list of targetentries *	  for the attributes of the rte * * As with expandRTE, rtindex/sublevels_up determine the varno/varlevelsup * fields of the Vars produced.  pstate->p_next_resno determines the resnos * assigned to the TLEs. */List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,			   int rtindex, int sublevels_up){	List	   *names,			   *vars;	ListCell   *name,			   *var;	List	   *te_list = NIL;	expandRTE(rte, rtindex, sublevels_up, false,			  &names, &vars);	forboth(name, names, var, vars)	{		char	   *label = strVal(lfirst(name));		Node	   *varnode = (Node *) lfirst(var);		TargetEntry *te;		te = makeTargetEntry((Expr *) varnode,							 (AttrNumber) pstate->p_next_resno++,							 label,							 false);		te_list = lappend(te_list, te);	}	Assert(name == NULL && var == NULL);		/* lists not the same length? */	return te_list;}/* * get_rte_attribute_name *		Get an attribute name from a RangeTblEntry * * This is unlike get_attname() because we use aliases if available. * In particular, it will work on an RTE for a subselect or join, whereas * get_attname() only works on real relations.

⌨️ 快捷键说明

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