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

📄 parse_coerce.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
				 * both types in different categories? then not much hope...				 */				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),				/*				 * translator: first %s is name of a SQL construct, eg CASE				 */						 errmsg("%s types %s and %s cannot be matched",								context,								format_type_be(ptype),								format_type_be(ntype))));			}			else if (!IsPreferredType(pcategory, ptype) &&					 can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&					 !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))			{				/*				 * take new type if can coerce to it implicitly but not the				 * other way; but if we have a preferred type, stay on it.				 */				ptype = ntype;				pcategory = TypeCategory(ptype);			}		}	}	/*	 * If all the inputs were UNKNOWN type --- ie, unknown-type literals ---	 * then resolve as type TEXT.  This situation comes up with constructs	 * like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'	 * UNION SELECT 'bar'; It might seem desirable to leave the construct's	 * output type as UNKNOWN, but that really doesn't work, because we'd	 * probably end up needing a runtime coercion from UNKNOWN to something	 * else, and we usually won't have it.  We need to coerce the unknown	 * literals while they are still literals, so a decision has to be made	 * now.	 */	if (ptype == UNKNOWNOID)		ptype = TEXTOID;	return ptype;}/* coerce_to_common_type() *		Coerce an expression to the given type. * * This is used following select_common_type() to coerce the individual * expressions to the desired type.  'context' is a phrase to use in the * error message if we fail to coerce. * * As with coerce_type, pstate may be NULL if no special unknown-Param * processing is wanted. */Node *coerce_to_common_type(ParseState *pstate, Node *node,					  Oid targetTypeId, const char *context){	Oid			inputTypeId = exprType(node);	if (inputTypeId == targetTypeId)		return node;			/* no work */	if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))		node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,						   COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);	else		ereport(ERROR,				(errcode(ERRCODE_CANNOT_COERCE),		/* translator: first %s is name of a SQL construct, eg CASE */				 errmsg("%s could not convert type %s to %s",						context,						format_type_be(inputTypeId),						format_type_be(targetTypeId))));	return node;}/* * check_generic_type_consistency() *		Are the actual arguments potentially compatible with a *		polymorphic function? * * The argument consistency rules are: * * 1) All arguments declared ANYARRAY must have matching datatypes, *	  and must in fact be varlena arrays. * 2) All arguments declared ANYELEMENT must have matching datatypes. * 3) If there are arguments of both ANYELEMENT and ANYARRAY, make sure *	  the actual ANYELEMENT datatype is in fact the element type for *	  the actual ANYARRAY datatype. * * If we have UNKNOWN input (ie, an untyped literal) for any ANYELEMENT * or ANYARRAY argument, assume it is okay. * * If an input is of type ANYARRAY (ie, we know it's an array, but not * what element type), we will accept it as a match to an argument declared * ANYARRAY, so long as we don't have to determine an element type --- * that is, so long as there is no use of ANYELEMENT.  This is mostly for * backwards compatibility with the pre-7.4 behavior of ANYARRAY. * * We do not ereport here, but just return FALSE if a rule is violated. */boolcheck_generic_type_consistency(Oid *actual_arg_types,							   Oid *declared_arg_types,							   int nargs){	int			j;	Oid			elem_typeid = InvalidOid;	Oid			array_typeid = InvalidOid;	Oid			array_typelem;	bool		have_anyelement = false;	/*	 * Loop through the arguments to see if we have any that are ANYARRAY or	 * ANYELEMENT. If so, require the actual types to be self-consistent	 */	for (j = 0; j < nargs; j++)	{		Oid			actual_type = actual_arg_types[j];		if (declared_arg_types[j] == ANYELEMENTOID)		{			have_anyelement = true;			if (actual_type == UNKNOWNOID)				continue;			if (OidIsValid(elem_typeid) && actual_type != elem_typeid)				return false;			elem_typeid = actual_type;		}		else if (declared_arg_types[j] == ANYARRAYOID)		{			if (actual_type == UNKNOWNOID)				continue;			if (OidIsValid(array_typeid) && actual_type != array_typeid)				return false;			array_typeid = actual_type;		}	}	/* Get the element type based on the array type, if we have one */	if (OidIsValid(array_typeid))	{		if (array_typeid == ANYARRAYOID)		{			/* Special case for ANYARRAY input: okay iff no ANYELEMENT */			if (have_anyelement)				return false;			return true;		}		array_typelem = get_element_type(array_typeid);		if (!OidIsValid(array_typelem))			return false;		/* should be an array, but isn't */		if (!OidIsValid(elem_typeid))		{			/*			 * if we don't have an element type yet, use the one we just got			 */			elem_typeid = array_typelem;		}		else if (array_typelem != elem_typeid)		{			/* otherwise, they better match */			return false;		}	}	/* Looks valid */	return true;}/* * enforce_generic_type_consistency() *		Make sure a polymorphic function is legally callable, and *		deduce actual argument and result types. * * If ANYARRAY or ANYELEMENT is used for a function's arguments or * return type, we make sure the actual data types are consistent with * each other. The argument consistency rules are shown above for * check_generic_type_consistency(). * * If we have UNKNOWN input (ie, an untyped literal) for any ANYELEMENT * or ANYARRAY argument, we attempt to deduce the actual type it should * have.  If successful, we alter that position of declared_arg_types[] * so that make_fn_arguments will coerce the literal to the right thing. * * Rules are applied to the function's return type (possibly altering it) * if it is declared ANYARRAY or ANYELEMENT: * * 1) If return type is ANYARRAY, and any argument is ANYARRAY, use the *	  argument's actual type as the function's return type. * 2) If return type is ANYARRAY, no argument is ANYARRAY, but any argument *	  is ANYELEMENT, use the actual type of the argument to determine *	  the function's return type, i.e. the element type's corresponding *	  array type. * 3) If return type is ANYARRAY, no argument is ANYARRAY or ANYELEMENT, *	  generate an ERROR. This condition is prevented by CREATE FUNCTION *	  and is therefore not expected here. * 4) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the *	  argument's actual type as the function's return type. * 5) If return type is ANYELEMENT, no argument is ANYELEMENT, but any *	  argument is ANYARRAY, use the actual type of the argument to determine *	  the function's return type, i.e. the array type's corresponding *	  element type. * 6) If return type is ANYELEMENT, no argument is ANYARRAY or ANYELEMENT, *	  generate an ERROR. This condition is prevented by CREATE FUNCTION *	  and is therefore not expected here. */Oidenforce_generic_type_consistency(Oid *actual_arg_types,								 Oid *declared_arg_types,								 int nargs,								 Oid rettype){	int			j;	bool		have_generics = false;	bool		have_unknowns = false;	Oid			elem_typeid = InvalidOid;	Oid			array_typeid = InvalidOid;	Oid			array_typelem;	bool		have_anyelement = (rettype == ANYELEMENTOID);	/*	 * Loop through the arguments to see if we have any that are ANYARRAY or	 * ANYELEMENT. If so, require the actual types to be self-consistent	 */	for (j = 0; j < nargs; j++)	{		Oid			actual_type = actual_arg_types[j];		if (declared_arg_types[j] == ANYELEMENTOID)		{			have_generics = have_anyelement = true;			if (actual_type == UNKNOWNOID)			{				have_unknowns = true;				continue;			}			if (OidIsValid(elem_typeid) && actual_type != elem_typeid)				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),				errmsg("arguments declared \"anyelement\" are not all alike"),						 errdetail("%s versus %s",								   format_type_be(elem_typeid),								   format_type_be(actual_type))));			elem_typeid = actual_type;		}		else if (declared_arg_types[j] == ANYARRAYOID)		{			have_generics = true;			if (actual_type == UNKNOWNOID)			{				have_unknowns = true;				continue;			}			if (OidIsValid(array_typeid) && actual_type != array_typeid)				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("arguments declared \"anyarray\" are not all alike"),						 errdetail("%s versus %s",								   format_type_be(array_typeid),								   format_type_be(actual_type))));			array_typeid = actual_type;		}	}	/*	 * Fast Track: if none of the arguments are ANYARRAY or ANYELEMENT, return	 * the unmodified rettype.	 */	if (!have_generics)		return rettype;	/* Get the element type based on the array type, if we have one */	if (OidIsValid(array_typeid))	{		if (array_typeid == ANYARRAYOID && !have_anyelement)		{			/* Special case for ANYARRAY input: okay iff no ANYELEMENT */			array_typelem = InvalidOid;		}		else		{			array_typelem = get_element_type(array_typeid);			if (!OidIsValid(array_typelem))				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("argument declared \"anyarray\" is not an array but type %s",								format_type_be(array_typeid))));		}		if (!OidIsValid(elem_typeid))		{			/*			 * if we don't have an element type yet, use the one we just got			 */			elem_typeid = array_typelem;		}		else if (array_typelem != elem_typeid)		{			/* otherwise, they better match */			ereport(ERROR,					(errcode(ERRCODE_DATATYPE_MISMATCH),					 errmsg("argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""),					 errdetail("%s versus %s",							   format_type_be(array_typeid),							   format_type_be(elem_typeid))));		}	}	else if (!OidIsValid(elem_typeid))	{		/* Only way to get here is if all the generic args are UNKNOWN */		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("could not determine anyarray/anyelement type because input has type \"unknown\"")));	}	/*	 * If we had any unknown inputs, re-scan to assign correct types	 */	if (have_unknowns)	{		for (j = 0; j < nargs; j++)		{			Oid			actual_type = actual_arg_types[j];			if (actual_type != UNKNOWNOID)				continue;			if (declared_arg_types[j] == ANYELEMENTOID)				declared_arg_types[j] = elem_typeid;			else if (declared_arg_types[j] == ANYARRAYOID)			{				if (!OidIsValid(array_typeid))				{					array_typeid = get_array_type(elem_typeid);					if (!OidIsValid(array_typeid))						ereport(ERROR,								(errcode(ERRCODE_UNDEFINED_OBJECT),						 errmsg("could not find array type for data type %s",								format_type_be(elem_typeid))));				}				declared_arg_types[j] = array_typeid;			}		}	}	/* if we return ANYARRAYOID use the appropriate argument type */	if (rettype == ANYARRAYOID)	{		if (!OidIsValid(array_typeid))		{			array_typeid = get_array_type(elem_typeid);			if (!OidIsValid(array_typeid))				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_OBJECT),						 errmsg("could not find array type for data type %s",								format_type_be(elem_typeid))));		}		return array_typeid;	}	/* if we return ANYELEMENTOID use the appropriate argument type */	if (rettype == ANYELEMENTOID)		return elem_typeid;	/* we don't return a generic type; send back the original return type */	return rettype;}/* * resolve_generic_type() *		Deduce an individual actual datatype on the assumption that *		the rules for ANYARRAY/ANYELEMENT are being followed. * * declared_type is the declared datatype we want to resolve. * context_actual_type is the actual input datatype to some argument * that has declared datatype context_declared_type. * * If declared_type isn't polymorphic, we just return it.  Otherwise, * context_declared_type must be polymorphic, and we deduce the correct * return type based on the relationship of the two polymorphic types. */Oidresolve_generic_type(Oid declared_type,					 Oid context_actual_type,					 Oid context_declared_type){	if (declared_type == ANYARRAYOID)	{		if (context_declared_type == ANYARRAYOID)		{			/* Use actual type, but it must be an array */			Oid			array_typelem = get_element_type(context_actual_type);			if (!OidIsValid(array_typelem))				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("argument declared \"anyarray\" is not an array but type %s",								format_type_be(context_actual_type))));			return context_actual_type;		}		else if (context_declared_type == ANYELEMENTOID)		{			/* Use the array type corresponding to actual type */			Oid			array_typeid = get_array_type(context_actual_type);			if (!OidIsValid(array_typeid))				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_OBJECT),						 errmsg("could not find array type for data type %s",								format_type_be(context_actual_type))));			return array_typeid;		}	}	else if (declared_type == ANYELEMENTOID)	{		if (context_declared_type == ANYARRAYOID)		{			/* Use the element type corresponding to actual type */			Oid			array_typelem = get_element_type(context_actual_type);			if (!OidIsValid(array_typelem))				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("argument declared \"anyarray\" is not an array but type %s",								format_type_be(context_actual_type))));			return array_typelem;		}		else if (context_declared_type == ANYELEMENTOID)		{			/* Use the actual type; it doesn't matter if array or not */			return context_actual_type;		}	}	else	{		/* declared_type isn't polymorphic, so return it as-is */		return declared_type;	}	/* If we get here, declared_type is polymorphic and context isn't */	/* NB: this is a calling-code logic error, not a user error */	elog(ERROR, "could not determine ANYARRAY/ANYELEMENT type because context isn't polymorphic");	return InvalidOid;			/* keep compiler quiet */

⌨️ 快捷键说明

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