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

📄 parse_relation.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	return scanRTEForColumn(pstate, rte, colname);}/* * buildRelationAliases *		Construct the eref column name list for a relation RTE. *		This code is also used for the case of a function RTE returning *		a named composite type. * * tupdesc: the physical column information * alias: the user-supplied alias, or NULL if none * eref: the eref Alias to store column names in * * eref->colnames is filled in.  Also, alias->colnames is rebuilt to insert * empty strings for any dropped columns, so that it will be one-to-one with * physical column numbers. */static voidbuildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref){	int			maxattrs = tupdesc->natts;	ListCell   *aliaslc;	int			numaliases;	int			varattno;	int			numdropped = 0;	Assert(eref->colnames == NIL);	if (alias)	{		aliaslc = list_head(alias->colnames);		numaliases = list_length(alias->colnames);		/* We'll rebuild the alias colname list */		alias->colnames = NIL;	}	else	{		aliaslc = NULL;		numaliases = 0;	}	for (varattno = 0; varattno < maxattrs; varattno++)	{		Form_pg_attribute attr = tupdesc->attrs[varattno];		Value	   *attrname;		if (attr->attisdropped)		{			/* Always insert an empty string for a dropped column */			attrname = makeString(pstrdup(""));			if (aliaslc)				alias->colnames = lappend(alias->colnames, attrname);			numdropped++;		}		else if (aliaslc)		{			/* Use the next user-supplied alias */			attrname = (Value *) lfirst(aliaslc);			aliaslc = lnext(aliaslc);			alias->colnames = lappend(alias->colnames, attrname);		}		else		{			attrname = makeString(pstrdup(NameStr(attr->attname)));			/* we're done with the alias if any */		}		eref->colnames = lappend(eref->colnames, attrname);	}	/* Too many user-supplied aliases? */	if (aliaslc)		ereport(ERROR,				(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),				 errmsg("table \"%s\" has %d columns available but %d columns specified",						eref->aliasname, maxattrs - numdropped, numaliases)));}/* * buildScalarFunctionAlias *		Construct the eref column name list for a function RTE, *		when the function returns a scalar type (not composite or RECORD). * * funcexpr: transformed expression tree for the function call * funcname: function name (used only for error message) * alias: the user-supplied alias, or NULL if none * eref: the eref Alias to store column names in * * eref->colnames is filled in. */static voidbuildScalarFunctionAlias(Node *funcexpr, char *funcname,						 Alias *alias, Alias *eref){	char	   *pname;	Assert(eref->colnames == NIL);	/* Use user-specified column alias if there is one. */	if (alias && alias->colnames != NIL)	{		if (list_length(alias->colnames) != 1)			ereport(ERROR,					(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),				  errmsg("too many column aliases specified for function %s",						 funcname)));		eref->colnames = copyObject(alias->colnames);		return;	}	/*	 * If the expression is a simple function call, and the function has a	 * single OUT parameter that is named, use the parameter's name.	 */	if (funcexpr && IsA(funcexpr, FuncExpr))	{		pname = get_func_result_name(((FuncExpr *) funcexpr)->funcid);		if (pname)		{			eref->colnames = list_make1(makeString(pname));			return;		}	}	/*	 * Otherwise use the previously-determined alias (not necessarily the	 * function name!)	 */	eref->colnames = list_make1(makeString(eref->aliasname));}/* * Add an entry for a relation to the pstate's range table (p_rtable). * * If pstate is NULL, we just build an RTE and return it without adding it * to an rtable list. * * Note: formerly this checked for refname conflicts, but that's wrong. * Caller is responsible for checking for conflicts in the appropriate scope. */RangeTblEntry *addRangeTableEntry(ParseState *pstate,				   RangeVar *relation,				   Alias *alias,				   bool inh,				   bool inFromCl){	RangeTblEntry *rte = makeNode(RangeTblEntry);	char	   *refname = alias ? alias->aliasname : relation->relname;	LOCKMODE	lockmode;	Relation	rel;	rte->rtekind = RTE_RELATION;	rte->alias = alias;	/*	 * Get the rel's OID.  This access also ensures that we have an up-to-date	 * relcache entry for the rel.	Since this is typically the first access	 * to a rel in a statement, be careful to get the right access level	 * depending on whether we're doing SELECT FOR UPDATE/SHARE.	 */	lockmode = isLockedRel(pstate, refname) ? RowShareLock : AccessShareLock;	rel = heap_openrv(relation, lockmode);	rte->relid = RelationGetRelid(rel);	/*	 * Build the list of effective column names using user-supplied aliases	 * and/or actual column names.	 */	rte->eref = makeAlias(refname, NIL);	buildRelationAliases(rel->rd_att, alias, rte->eref);	/*	 * Drop the rel refcount, but keep the access lock till end of transaction	 * so that the table can't be deleted or have its schema modified	 * underneath us.	 */	heap_close(rel, NoLock);	/*----------	 * 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.	 *	 * The initial default on access checks is always check-for-READ-access,	 * which is the right thing for all except target tables.	 *----------	 */	rte->inh = inh;	rte->inFromCl = inFromCl;	rte->requiredPerms = ACL_SELECT;	rte->checkAsUser = InvalidOid;		/* not set-uid by default, either */	/*	 * 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;}/* * Add an entry for a relation to the pstate's range table (p_rtable). * * This is just like addRangeTableEntry() except that it makes an RTE * given an already-open relation instead of a RangeVar reference. */RangeTblEntry *addRangeTableEntryForRelation(ParseState *pstate,							  Relation rel,							  Alias *alias,							  bool inh,							  bool inFromCl){	RangeTblEntry *rte = makeNode(RangeTblEntry);	char	   *refname = alias ? alias->aliasname : RelationGetRelationName(rel);	rte->rtekind = RTE_RELATION;	rte->alias = alias;	rte->relid = RelationGetRelid(rel);	/*	 * Build the list of effective column names using user-supplied aliases	 * and/or actual column names.	 */	rte->eref = makeAlias(refname, NIL);	buildRelationAliases(rel->rd_att, alias, rte->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.	 *	 * The initial default on access checks is always check-for-READ-access,	 * which is the right thing for all except target tables.	 *----------	 */	rte->inh = inh;	rte->inFromCl = inFromCl;	rte->requiredPerms = ACL_SELECT;	rte->checkAsUser = InvalidOid;		/* not set-uid by default, either */	/*	 * 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;}/* * Add an entry for a subquery to the pstate's range table (p_rtable). * * This is just like addRangeTableEntry() except that it makes a subquery RTE. * Note that an alias clause *must* be supplied. */RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate,							  Query *subquery,							  Alias *alias,							  bool inFromCl){	RangeTblEntry *rte = makeNode(RangeTblEntry);	char	   *refname = alias->aliasname;	Alias	   *eref;	int			numaliases;	int			varattno;	ListCell   *tlistitem;	rte->rtekind = RTE_SUBQUERY;	rte->relid = InvalidOid;	rte->subquery = subquery;	rte->alias = alias;	eref = copyObject(alias);	numaliases = list_length(eref->colnames);	/* fill in any unspecified alias columns */	varattno = 0;	foreach(tlistitem, subquery->targetList)	{		TargetEntry *te = (TargetEntry *) lfirst(tlistitem);		if (te->resjunk)			continue;		varattno++;		Assert(varattno == te->resno);		if (varattno > numaliases)		{			char	   *attrname;			attrname = pstrdup(te->resname);			eref->colnames = lappend(eref->colnames, makeString(attrname));		}	}	if (varattno < numaliases)		ereport(ERROR,				(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),				 errmsg("table \"%s\" has %d columns available but %d columns specified",						refname, varattno, 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.	 *	 * Subqueries are never checked for access rights.	 *----------	 */	rte->inh = false;			/* never true for subqueries */	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;}/* * Add an entry for a function to the pstate's range table (p_rtable). * * This is just like addRangeTableEntry() except that it makes a function RTE. */RangeTblEntry *addRangeTableEntryForFunction(ParseState *pstate,							  char *funcname,							  Node *funcexpr,							  RangeFunction *rangefunc,							  bool inFromCl){	RangeTblEntry *rte = makeNode(RangeTblEntry);	TypeFuncClass functypclass;	Oid			funcrettype;	TupleDesc	tupdesc;	Alias	   *alias = rangefunc->alias;	List	   *coldeflist = rangefunc->coldeflist;	Alias	   *eref;	rte->rtekind = RTE_FUNCTION;	rte->relid = InvalidOid;	rte->subquery = NULL;	rte->funcexpr = funcexpr;	rte->coldeflist = coldeflist;	rte->alias = alias;	eref = makeAlias(alias ? alias->aliasname : funcname, NIL);	rte->eref = eref;	/*	 * Now determine if the function returns a simple or composite type.	 */	functypclass = get_expr_result_type(funcexpr,										&funcrettype,										&tupdesc);	/*	 * A coldeflist is required if the function returns RECORD and hasn't got	 * a predetermined record type, and is prohibited otherwise.	 */	if (coldeflist != NIL)	{		if (functypclass != TYPEFUNC_RECORD)			ereport(ERROR,					(errcode(ERRCODE_SYNTAX_ERROR),					 errmsg("a column definition list is only allowed for functions returning \"record\"")));	}	else	{		if (functypclass == TYPEFUNC_RECORD)			ereport(ERROR,					(errcode(ERRCODE_SYNTAX_ERROR),					 errmsg("a column definition list is required for functions returning \"record\"")));	}	if (functypclass == TYPEFUNC_COMPOSITE)	{		/* Composite data type, e.g. a table's row type */		Assert(tupdesc);		/* Build the column alias list */		buildRelationAliases(tupdesc, alias, eref);	}	else if (functypclass == TYPEFUNC_SCALAR)	{		/* Base data type, i.e. scalar */		buildScalarFunctionAlias(funcexpr, funcname, alias, eref);	}	else if (functypclass == TYPEFUNC_RECORD)	{		ListCell   *col;		/* Use the column definition list to form the alias list */		foreach(col, coldeflist)		{			ColumnDef  *n = lfirst(col);			char	   *attrname;			attrname = pstrdup(n->colname);			eref->colnames = lappend(eref->colnames, makeString(attrname));		}	}	else		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),			 errmsg("function \"%s\" in FROM has unsupported return type %s",					funcname, format_type_be(funcrettype))));	/*----------	 * 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.	 *	 * Functions are never checked for access rights (at least, not by	 * the RTE permissions mechanism).	 *----------	 */	rte->inh = false;			/* never true for functions */	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;}/* * Add an entry for a join to the pstate's range table (p_rtable). * * This is much like addRangeTableEntry() except that it makes a join RTE. */RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,						  List *colnames,						  JoinType jointype,						  List *aliasvars,						  Alias *alias,						  bool inFromCl){	RangeTblEntry *rte = makeNode(RangeTblEntry);	Alias	   *eref;	int			numaliases;

⌨️ 快捷键说明

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