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

📄 parse_func.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
{	bool		result = false;	Oid			relid;	Relation	inhrel;	List	   *visited,			   *queue;	ListCell   *queue_item;	if (!ISCOMPLEX(subclassTypeId) || !ISCOMPLEX(superclassTypeId))		return false;	relid = typeidTypeRelid(subclassTypeId);	if (relid == InvalidOid)		return false;	/*	 * Begin the search at the relation itself, so add relid to the queue.	 */	queue = list_make1_oid(relid);	visited = NIL;	inhrel = heap_open(InheritsRelationId, AccessShareLock);	/*	 * Use queue to do a breadth-first traversal of the inheritance graph from	 * the relid supplied up to the root.  Notice that we append to the queue	 * inside the loop --- this is okay because the foreach() macro doesn't	 * advance queue_item until the next loop iteration begins.	 */	foreach(queue_item, queue)	{		Oid			this_relid = lfirst_oid(queue_item);		ScanKeyData skey;		HeapScanDesc inhscan;		HeapTuple	inhtup;		/* If we've seen this relid already, skip it */		if (list_member_oid(visited, this_relid))			continue;		/*		 * Okay, this is a not-yet-seen relid. Add it to the list of		 * already-visited OIDs, then find all the types this relid inherits		 * from and add them to the queue. The one exception is we don't add		 * the original relation to 'visited'.		 */		if (queue_item != list_head(queue))			visited = lappend_oid(visited, this_relid);		ScanKeyInit(&skey,					Anum_pg_inherits_inhrelid,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(this_relid));		inhscan = heap_beginscan(inhrel, SnapshotNow, 1, &skey);		while ((inhtup = heap_getnext(inhscan, ForwardScanDirection)) != NULL)		{			Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup);			Oid			inhparent = inh->inhparent;			/* If this is the target superclass, we're done */			if (get_rel_type_id(inhparent) == superclassTypeId)			{				result = true;				break;			}			/* Else add to queue */			queue = lappend_oid(queue, inhparent);		}		heap_endscan(inhscan);		if (result)			break;	}	heap_close(inhrel, AccessShareLock);	list_free(visited);	list_free(queue);	return result;}/* * make_fn_arguments() * * Given the actual argument expressions for a function, and the desired * input types for the function, add any necessary typecasting to the * expression tree.  Caller should already have verified that casting is * allowed. * * Caution: given argument list is modified in-place. * * As with coerce_type, pstate may be NULL if no special unknown-Param * processing is wanted. */voidmake_fn_arguments(ParseState *pstate,				  List *fargs,				  Oid *actual_arg_types,				  Oid *declared_arg_types){	ListCell   *current_fargs;	int			i = 0;	foreach(current_fargs, fargs)	{		/* types don't match? then force coercion using a function call... */		if (actual_arg_types[i] != declared_arg_types[i])		{			lfirst(current_fargs) = coerce_type(pstate,												lfirst(current_fargs),												actual_arg_types[i],												declared_arg_types[i], -1,												COERCION_IMPLICIT,												COERCE_IMPLICIT_CAST);		}		i++;	}}/* * ParseComplexProjection - *	  handles function calls with a single argument that is of complex type. *	  If the function call is actually a column projection, return a suitably *	  transformed expression tree.	If not, return NULL. */static Node *ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg){	TupleDesc	tupdesc;	int			i;	/*	 * Special case for whole-row Vars so that we can resolve (foo.*).bar even	 * when foo is a reference to a subselect, join, or RECORD function. A	 * bonus is that we avoid generating an unnecessary FieldSelect; our	 * result can omit the whole-row Var and just be a Var for the selected	 * field.	 *	 * This case could be handled by expandRecordVariable, but it's more	 * efficient to do it this way when possible.	 */	if (IsA(first_arg, Var) &&		((Var *) first_arg)->varattno == InvalidAttrNumber)	{		RangeTblEntry *rte;		rte = GetRTEByRangeTablePosn(pstate,									 ((Var *) first_arg)->varno,									 ((Var *) first_arg)->varlevelsup);		/* Return a Var if funcname matches a column, else NULL */		return scanRTEForColumn(pstate, rte, funcname);	}	/*	 * Else do it the hard way with get_expr_result_type().	 *	 * If it's a Var of type RECORD, we have to work even harder: we have to	 * find what the Var refers to, and pass that to get_expr_result_type.	 * That task is handled by expandRecordVariable().	 */	if (IsA(first_arg, Var) &&		((Var *) first_arg)->vartype == RECORDOID)		tupdesc = expandRecordVariable(pstate, (Var *) first_arg, 0);	else if (get_expr_result_type(first_arg, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)		return NULL;			/* unresolvable RECORD type */	Assert(tupdesc);	for (i = 0; i < tupdesc->natts; i++)	{		Form_pg_attribute att = tupdesc->attrs[i];		if (strcmp(funcname, NameStr(att->attname)) == 0 &&			!att->attisdropped)		{			/* Success, so generate a FieldSelect expression */			FieldSelect *fselect = makeNode(FieldSelect);			fselect->arg = (Expr *) first_arg;			fselect->fieldnum = i + 1;			fselect->resulttype = att->atttypid;			fselect->resulttypmod = att->atttypmod;			return (Node *) fselect;		}	}	return NULL;				/* funcname does not match any column */}/* * helper routine for delivering "column does not exist" error message */static voidunknown_attribute(ParseState *pstate, Node *relref, char *attname){	RangeTblEntry *rte;	if (IsA(relref, Var) &&		((Var *) relref)->varattno == InvalidAttrNumber)	{		/* Reference the RTE by alias not by actual table name */		rte = GetRTEByRangeTablePosn(pstate,									 ((Var *) relref)->varno,									 ((Var *) relref)->varlevelsup);		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_COLUMN),				 errmsg("column %s.%s does not exist",						rte->eref->aliasname, attname)));	}	else	{		/* Have to do it by reference to the type of the expression */		Oid			relTypeId = exprType(relref);		if (ISCOMPLEX(relTypeId))			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_COLUMN),					 errmsg("column \"%s\" not found in data type %s",							attname, format_type_be(relTypeId))));		else if (relTypeId == RECORDOID)			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_COLUMN),			   errmsg("could not identify column \"%s\" in record data type",					  attname)));		else			ereport(ERROR,					(errcode(ERRCODE_WRONG_OBJECT_TYPE),					 errmsg("column notation .%s applied to type %s, "							"which is not a composite type",							attname, format_type_be(relTypeId))));	}}/* * funcname_signature_string *		Build a string representing a function name, including arg types. *		The result is something like "foo(integer)". * * This is typically used in the construction of function-not-found error * messages. */const char *funcname_signature_string(const char *funcname,						  int nargs, const Oid *argtypes){	StringInfoData argbuf;	int			i;	initStringInfo(&argbuf);	appendStringInfo(&argbuf, "%s(", funcname);	for (i = 0; i < nargs; i++)	{		if (i)			appendStringInfoString(&argbuf, ", ");		appendStringInfoString(&argbuf, format_type_be(argtypes[i]));	}	appendStringInfoChar(&argbuf, ')');	return argbuf.data;			/* return palloc'd string buffer */}/* * func_signature_string *		As above, but function name is passed as a qualified name list. */const char *func_signature_string(List *funcname, int nargs, const Oid *argtypes){	return funcname_signature_string(NameListToString(funcname),									 nargs, argtypes);}/* * find_aggregate_func *		Convenience routine to check that a function exists and is an *		aggregate. * * Note: basetype is ANYOID if we are looking for an aggregate on * all types. */Oidfind_aggregate_func(List *aggname, Oid basetype, bool noError){	Oid			oid;	HeapTuple	ftup;	Form_pg_proc pform;	oid = LookupFuncName(aggname, 1, &basetype, true);	if (!OidIsValid(oid))	{		if (noError)			return InvalidOid;		if (basetype == ANYOID)			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_FUNCTION),					 errmsg("aggregate %s(*) does not exist",							NameListToString(aggname))));		else			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_FUNCTION),					 errmsg("aggregate %s(%s) does not exist",							NameListToString(aggname),							format_type_be(basetype))));	}	/* Make sure it's an aggregate */	ftup = SearchSysCache(PROCOID,						  ObjectIdGetDatum(oid),						  0, 0, 0);	if (!HeapTupleIsValid(ftup))	/* should not happen */		elog(ERROR, "cache lookup failed for function %u", oid);	pform = (Form_pg_proc) GETSTRUCT(ftup);	if (!pform->proisagg)	{		ReleaseSysCache(ftup);		if (noError)			return InvalidOid;		/* we do not use the (*) notation for functions... */		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("function %s(%s) is not an aggregate",					  NameListToString(aggname), format_type_be(basetype))));	}	ReleaseSysCache(ftup);	return oid;}/* * LookupFuncName *		Given a possibly-qualified function name and a set of argument types, *		look up the function. * * If the function name is not schema-qualified, it is sought in the current * namespace search path. * * If the function is not found, we return InvalidOid if noError is true, * else raise an error. */OidLookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError){	FuncCandidateList clist;	clist = FuncnameGetCandidates(funcname, nargs);	while (clist)	{		if (memcmp(argtypes, clist->args, nargs * sizeof(Oid)) == 0)			return clist->oid;		clist = clist->next;	}	if (!noError)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_FUNCTION),				 errmsg("function %s does not exist",						func_signature_string(funcname, nargs, argtypes))));	return InvalidOid;}/* * LookupFuncNameTypeNames *		Like LookupFuncName, but the argument types are specified by a *		list of TypeName nodes. */OidLookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError){	Oid			argoids[FUNC_MAX_ARGS];	int			argcount;	int			i;	ListCell   *args_item;	argcount = list_length(argtypes);	if (argcount > FUNC_MAX_ARGS)		ereport(ERROR,				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),				 errmsg("functions cannot have more than %d arguments",						FUNC_MAX_ARGS)));	args_item = list_head(argtypes);	for (i = 0; i < argcount; i++)	{		TypeName   *t = (TypeName *) lfirst(args_item);		argoids[i] = LookupTypeName(t);		if (!OidIsValid(argoids[i]))			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_OBJECT),					 errmsg("type \"%s\" does not exist",							TypeNameToString(t))));		args_item = lnext(args_item);	}	return LookupFuncName(funcname, argcount, argoids, noError);}

⌨️ 快捷键说明

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