mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since their creation. Instead put the information into two new pg_type columns, typcategory and typispreferred. Add support for setting these when creating a user-defined base type. The category column is just a "char" (i.e. a poor man's enum), allowing a crude form of user extensibility of the category list: just use an otherwise-unused character. This seems sufficient for foreseen uses, but we could upgrade to having an actual category catalog someday, if there proves to be a huge demand for custom type categories. In this patch I have attempted to hew exactly to the behavior of the previous hardwired logic, except for introducing new type categories for arrays, composites, and enums. In particular the default preferred state for user-defined types remains TRUE. That seems worth revisiting, but it should be done as a separate patch from introducing the infrastructure. Likewise, any adjustment of the standard set of categories should be done separately.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.161 2008/01/11 18:39:40 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.162 2008/07/30 17:05:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -967,7 +967,8 @@ Oid
|
||||
select_common_type(List *typeids, const char *context)
|
||||
{
|
||||
Oid ptype;
|
||||
CATEGORY pcategory;
|
||||
TYPCATEGORY pcategory;
|
||||
bool pispreferred;
|
||||
ListCell *type_item;
|
||||
|
||||
Assert(typeids != NIL);
|
||||
@ -993,7 +994,7 @@ select_common_type(List *typeids, const char *context)
|
||||
|
||||
/* Nope, so set up for the full algorithm */
|
||||
ptype = getBaseType(ptype);
|
||||
pcategory = TypeCategory(ptype);
|
||||
get_type_category_preferred(ptype, &pcategory, &pispreferred);
|
||||
|
||||
for_each_cell(type_item, lnext(list_head(typeids)))
|
||||
{
|
||||
@ -1002,13 +1003,18 @@ select_common_type(List *typeids, const char *context)
|
||||
/* move on to next one if no new information... */
|
||||
if (ntype != UNKNOWNOID && ntype != ptype)
|
||||
{
|
||||
TYPCATEGORY ncategory;
|
||||
bool nispreferred;
|
||||
|
||||
get_type_category_preferred(ntype, &ncategory, &nispreferred);
|
||||
if (ptype == UNKNOWNOID)
|
||||
{
|
||||
/* so far, only unknowns so take anything... */
|
||||
ptype = ntype;
|
||||
pcategory = TypeCategory(ptype);
|
||||
pcategory = ncategory;
|
||||
pispreferred = nispreferred;
|
||||
}
|
||||
else if (TypeCategory(ntype) != pcategory)
|
||||
else if (ncategory != pcategory)
|
||||
{
|
||||
/*
|
||||
* both types in different categories? then not much hope...
|
||||
@ -1023,7 +1029,7 @@ select_common_type(List *typeids, const char *context)
|
||||
format_type_be(ptype),
|
||||
format_type_be(ntype))));
|
||||
}
|
||||
else if (!IsPreferredType(pcategory, ptype) &&
|
||||
else if (!pispreferred &&
|
||||
can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
|
||||
!can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
|
||||
{
|
||||
@ -1032,7 +1038,8 @@ select_common_type(List *typeids, const char *context)
|
||||
* other way; but if we have a preferred type, stay on it.
|
||||
*/
|
||||
ptype = ntype;
|
||||
pcategory = TypeCategory(ptype);
|
||||
pcategory = ncategory;
|
||||
pispreferred = nispreferred;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1549,202 +1556,39 @@ resolve_generic_type(Oid declared_type,
|
||||
/* 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
|
||||
* NB: this must not return TYPCATEGORY_INVALID.
|
||||
*/
|
||||
CATEGORY
|
||||
TypeCategory(Oid inType)
|
||||
TYPCATEGORY
|
||||
TypeCategory(Oid type)
|
||||
{
|
||||
CATEGORY result;
|
||||
char typcategory;
|
||||
bool typispreferred;
|
||||
|
||||
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 (REGCONFIGOID):
|
||||
case (REGDICTIONARYOID):
|
||||
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):
|
||||
case (ANYNONARRAYOID):
|
||||
case (ANYENUMOID):
|
||||
result = GENERIC_TYPE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = USER_TYPE;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} /* TypeCategory() */
|
||||
get_type_category_preferred(type, &typcategory, &typispreferred);
|
||||
Assert(typcategory != TYPCATEGORY_INVALID);
|
||||
return (TYPCATEGORY) typcategory;
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
* If category is TYPCATEGORY_INVALID, then we'll return TRUE for preferred
|
||||
* types of any category; otherwise, only for preferred types of that
|
||||
* category.
|
||||
*/
|
||||
bool
|
||||
IsPreferredType(CATEGORY category, Oid type)
|
||||
IsPreferredType(TYPCATEGORY category, Oid type)
|
||||
{
|
||||
Oid preftype;
|
||||
char typcategory;
|
||||
bool typispreferred;
|
||||
|
||||
if (category == INVALID_TYPE)
|
||||
category = TypeCategory(type);
|
||||
else if (category != TypeCategory(type))
|
||||
get_type_category_preferred(type, &typcategory, &typispreferred);
|
||||
if (category == typcategory || category == TYPCATEGORY_INVALID)
|
||||
return typispreferred;
|
||||
else
|
||||
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 ||
|
||||
type == REGCONFIGOID ||
|
||||
type == REGDICTIONARYOID)
|
||||
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()
|
||||
|
Reference in New Issue
Block a user