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

📄 parse_coerce.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* TypeCategory() *		Assign a category to the specified type OID. * * NB: this must not return INVALID_TYPE. * * XXX This should be moved to system catalog lookups * to allow for better type extensibility. * - thomas 2001-09-30 */CATEGORYTypeCategory(Oid inType){	CATEGORY	result;	switch (inType)	{		case (BOOLOID):			result = BOOLEAN_TYPE;			break;		case (CHAROID):		case (NAMEOID):		case (BPCHAROID):		case (VARCHAROID):		case (TEXTOID):			result = STRING_TYPE;			break;		case (BITOID):		case (VARBITOID):			result = BITSTRING_TYPE;			break;		case (OIDOID):		case (REGPROCOID):		case (REGPROCEDUREOID):		case (REGOPEROID):		case (REGOPERATOROID):		case (REGCLASSOID):		case (REGTYPEOID):		case (INT2OID):		case (INT4OID):		case (INT8OID):		case (FLOAT4OID):		case (FLOAT8OID):		case (NUMERICOID):		case (CASHOID):			result = NUMERIC_TYPE;			break;		case (DATEOID):		case (TIMEOID):		case (TIMETZOID):		case (ABSTIMEOID):		case (TIMESTAMPOID):		case (TIMESTAMPTZOID):			result = DATETIME_TYPE;			break;		case (RELTIMEOID):		case (TINTERVALOID):		case (INTERVALOID):			result = TIMESPAN_TYPE;			break;		case (POINTOID):		case (LSEGOID):		case (PATHOID):		case (BOXOID):		case (POLYGONOID):		case (LINEOID):		case (CIRCLEOID):			result = GEOMETRIC_TYPE;			break;		case (INETOID):		case (CIDROID):			result = NETWORK_TYPE;			break;		case (UNKNOWNOID):		case (InvalidOid):			result = UNKNOWN_TYPE;			break;		case (RECORDOID):		case (CSTRINGOID):		case (ANYOID):		case (ANYARRAYOID):		case (VOIDOID):		case (TRIGGEROID):		case (LANGUAGE_HANDLEROID):		case (INTERNALOID):		case (OPAQUEOID):		case (ANYELEMENTOID):			result = GENERIC_TYPE;			break;		default:			result = USER_TYPE;			break;	}	return result;}	/* TypeCategory() *//* IsPreferredType() *		Check if this type is a preferred type for the given category. * * If category is INVALID_TYPE, then we'll return TRUE for preferred types * of any category; otherwise, only for preferred types of that category. * * XXX This should be moved to system catalog lookups * to allow for better type extensibility. * - thomas 2001-09-30 */boolIsPreferredType(CATEGORY category, Oid type){	Oid			preftype;	if (category == INVALID_TYPE)		category = TypeCategory(type);	else if (category != TypeCategory(type))		return false;	/*	 * This switch should agree with TypeCategory(), above.  Note that at this	 * point, category certainly matches the type.	 */	switch (category)	{		case (UNKNOWN_TYPE):		case (GENERIC_TYPE):			preftype = UNKNOWNOID;			break;		case (BOOLEAN_TYPE):			preftype = BOOLOID;			break;		case (STRING_TYPE):			preftype = TEXTOID;			break;		case (BITSTRING_TYPE):			preftype = VARBITOID;			break;		case (NUMERIC_TYPE):			if (type == OIDOID ||				type == REGPROCOID ||				type == REGPROCEDUREOID ||				type == REGOPEROID ||				type == REGOPERATOROID ||				type == REGCLASSOID ||				type == REGTYPEOID)				preftype = OIDOID;			else				preftype = FLOAT8OID;			break;		case (DATETIME_TYPE):			if (type == DATEOID)				preftype = TIMESTAMPOID;			else				preftype = TIMESTAMPTZOID;			break;		case (TIMESPAN_TYPE):			preftype = INTERVALOID;			break;		case (GEOMETRIC_TYPE):			preftype = type;			break;		case (NETWORK_TYPE):			preftype = INETOID;			break;		case (USER_TYPE):			preftype = type;			break;		default:			elog(ERROR, "unrecognized type category: %d", (int) category);			preftype = UNKNOWNOID;			break;	}	return (type == preftype);}	/* IsPreferredType() *//* IsBinaryCoercible() *		Check if srctype is binary-coercible to targettype. * * This notion allows us to cheat and directly exchange values without * going through the trouble of calling a conversion function.	Note that * in general, this should only be an implementation shortcut.	Before 7.4, * this was also used as a heuristic for resolving overloaded functions and * operators, but that's basically a bad idea. * * As of 7.3, binary coercibility isn't hardwired into the code anymore. * We consider two types binary-coercible if there is an implicitly * invokable, no-function-needed pg_cast entry.  Also, a domain is always * binary-coercible to its base type, though *not* vice versa (in the other * direction, one must apply domain constraint checks before accepting the * value as legitimate).  We also need to special-case the polymorphic * ANYARRAY type. * * This function replaces IsBinaryCompatible(), which was an inherently * symmetric test.	Since the pg_cast entries aren't necessarily symmetric, * the order of the operands is now significant. */boolIsBinaryCoercible(Oid srctype, Oid targettype){	HeapTuple	tuple;	Form_pg_cast castForm;	bool		result;	/* Fast path if same type */	if (srctype == targettype)		return true;	/* If srctype is a domain, reduce to its base type */	if (OidIsValid(srctype))		srctype = getBaseType(srctype);	/* Somewhat-fast path for domain -> base type case */	if (srctype == targettype)		return true;	/* Also accept any array type as coercible to ANYARRAY */	if (targettype == ANYARRAYOID)		if (get_element_type(srctype) != InvalidOid)			return true;	/* Else look in pg_cast */	tuple = SearchSysCache(CASTSOURCETARGET,						   ObjectIdGetDatum(srctype),						   ObjectIdGetDatum(targettype),						   0, 0);	if (!HeapTupleIsValid(tuple))		return false;			/* no cast */	castForm = (Form_pg_cast) GETSTRUCT(tuple);	result = (castForm->castfunc == InvalidOid &&			  castForm->castcontext == COERCION_CODE_IMPLICIT);	ReleaseSysCache(tuple);	return result;}/* * find_coercion_pathway *		Look for a coercion pathway between two types. * * ccontext determines the set of available casts. * * If we find a suitable entry in pg_cast, return TRUE, and set *funcid * to the castfunc value, which may be InvalidOid for a binary-compatible * coercion. * * NOTE: *funcid == InvalidOid does not necessarily mean that no work is * needed to do the coercion; if the target is a domain then we may need to * apply domain constraint checking.  If you want to check for a zero-effort * conversion then use IsBinaryCoercible(). */boolfind_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,					  CoercionContext ccontext,					  Oid *funcid){	bool		result = false;	HeapTuple	tuple;	*funcid = InvalidOid;	/* Perhaps the types are domains; if so, look at their base types */	if (OidIsValid(sourceTypeId))		sourceTypeId = getBaseType(sourceTypeId);	if (OidIsValid(targetTypeId))		targetTypeId = getBaseType(targetTypeId);	/* Domains are always coercible to and from their base type */	if (sourceTypeId == targetTypeId)		return true;	/* Look in pg_cast */	tuple = SearchSysCache(CASTSOURCETARGET,						   ObjectIdGetDatum(sourceTypeId),						   ObjectIdGetDatum(targetTypeId),						   0, 0);	if (HeapTupleIsValid(tuple))	{		Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);		CoercionContext castcontext;		/* convert char value for castcontext to CoercionContext enum */		switch (castForm->castcontext)		{			case COERCION_CODE_IMPLICIT:				castcontext = COERCION_IMPLICIT;				break;			case COERCION_CODE_ASSIGNMENT:				castcontext = COERCION_ASSIGNMENT;				break;			case COERCION_CODE_EXPLICIT:				castcontext = COERCION_EXPLICIT;				break;			default:				elog(ERROR, "unrecognized castcontext: %d",					 (int) castForm->castcontext);				castcontext = 0;	/* keep compiler quiet */				break;		}		/* Rely on ordering of enum for correct behavior here */		if (ccontext >= castcontext)		{			*funcid = castForm->castfunc;			result = true;		}		ReleaseSysCache(tuple);	}	else	{		/*		 * If there's no pg_cast entry, perhaps we are dealing with a pair of		 * array types.  If so, and if the element types have a suitable cast,		 * use array_type_coerce() or array_type_length_coerce().		 *		 * Hack: disallow coercions to oidvector and int2vector, which		 * otherwise tend to capture coercions that should go to "real" array		 * types.  We want those types to be considered "real" arrays for many		 * purposes, but not this one.	(Also, array_type_coerce isn't		 * guaranteed to produce an output that meets the restrictions of		 * these datatypes, such as being 1-dimensional.)		 */		Oid			targetElemType;		Oid			sourceElemType;		Oid			elemfuncid;		if (targetTypeId == OIDVECTOROID || targetTypeId == INT2VECTOROID)			return false;		if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&			(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)		{			if (find_coercion_pathway(targetElemType, sourceElemType,									  ccontext, &elemfuncid))			{				if (!OidIsValid(elemfuncid))				{					/* binary-compatible element type conversion */					*funcid = F_ARRAY_TYPE_COERCE;				}				else				{					/* does the function take a typmod arg? */					if (get_func_nargs(elemfuncid) > 1)						*funcid = F_ARRAY_TYPE_LENGTH_COERCE;					else						*funcid = F_ARRAY_TYPE_COERCE;				}				result = true;			}		}	}	return result;}/* * find_typmod_coercion_function -- does the given type need length coercion? * * If the target type possesses a pg_cast function from itself to itself, * it must need length coercion. * * "bpchar" (ie, char(N)) and "numeric" are examples of such types. * * If the given type is a varlena array type, we do not look for a coercion * function associated directly with the array type, but instead look for * one associated with the element type.  If one exists, we report * array_length_coerce() as the coercion function to use. */Oidfind_typmod_coercion_function(Oid typeId){	Oid			funcid = InvalidOid;	bool		isArray = false;	Type		targetType;	Form_pg_type typeForm;	HeapTuple	tuple;	targetType = typeidType(typeId);	typeForm = (Form_pg_type) GETSTRUCT(targetType);	/* Check for a varlena array type (and not a domain) */	if (typeForm->typelem != InvalidOid &&		typeForm->typlen == -1 &&		typeForm->typtype != 'd')	{		/* Yes, switch our attention to the element type */		typeId = typeForm->typelem;		isArray = true;	}	ReleaseSysCache(targetType);	/* Look in pg_cast */	tuple = SearchSysCache(CASTSOURCETARGET,						   ObjectIdGetDatum(typeId),						   ObjectIdGetDatum(typeId),						   0, 0);	if (HeapTupleIsValid(tuple))	{		Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);		funcid = castForm->castfunc;		ReleaseSysCache(tuple);	}	/*	 * Now, if we did find a coercion function for an array element type,	 * report array_length_coerce() as the function to use.	 */	if (isArray && OidIsValid(funcid))		funcid = F_ARRAY_LENGTH_COERCE;	return funcid;}

⌨️ 快捷键说明

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