diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/heap.c | 6 | ||||
-rw-r--r-- | src/backend/catalog/pg_type.c | 8 | ||||
-rw-r--r-- | src/backend/commands/indexcmds.c | 4 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 35 | ||||
-rw-r--r-- | src/backend/parser/parse_coerce.c | 224 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 33 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 25 |
7 files changed, 121 insertions, 214 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 797bee82a7b..5510e72b4e6 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.334 2008/05/12 00:00:46 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.335 2008/07/30 17:05:04 tgl Exp $ * * * INTERFACE ROUTINES @@ -761,6 +761,8 @@ AddNewRelationType(const char *typeName, new_rel_kind, /* relation kind */ -1, /* internal size (varlena) */ TYPTYPE_COMPOSITE, /* type-type (composite) */ + TYPCATEGORY_COMPOSITE, /* type-category (ditto) */ + true, /* all composite types are preferred */ DEFAULT_TYPDELIM, /* default array delimiter */ F_RECORD_IN, /* input procedure */ F_RECORD_OUT, /* output procedure */ @@ -938,6 +940,8 @@ heap_create_with_catalog(const char *relname, 0, /* relkind, also N/A here */ -1, /* Internal size (varlena) */ TYPTYPE_BASE, /* Not composite - typelem is */ + TYPCATEGORY_ARRAY, /* type-category (array) */ + true, /* all array types are preferred */ DEFAULT_TYPDELIM, /* default array delimiter */ F_ARRAY_IN, /* array input proc */ F_ARRAY_OUT, /* array output proc */ diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 42caacc96be..a6aec623cad 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.119 2008/06/19 00:46:04 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.120 2008/07/30 17:05:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -91,6 +91,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace) values[i++] = Int16GetDatum(sizeof(int4)); /* typlen */ values[i++] = BoolGetDatum(true); /* typbyval */ values[i++] = CharGetDatum(TYPTYPE_PSEUDO); /* typtype */ + values[i++] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE); /* typcategory */ + values[i++] = BoolGetDatum(false); /* typispreferred */ values[i++] = BoolGetDatum(false); /* typisdefined */ values[i++] = CharGetDatum(DEFAULT_TYPDELIM); /* typdelim */ values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */ @@ -173,6 +175,8 @@ TypeCreate(Oid newTypeOid, char relationKind, /* ditto */ int16 internalSize, char typeType, + char typeCategory, + bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, @@ -253,6 +257,8 @@ TypeCreate(Oid newTypeOid, values[i++] = Int16GetDatum(internalSize); /* typlen */ values[i++] = BoolGetDatum(passedByValue); /* typbyval */ values[i++] = CharGetDatum(typeType); /* typtype */ + values[i++] = CharGetDatum(typeCategory); /* typcategory */ + values[i++] = BoolGetDatum(typePreferred); /* typispreferred */ values[i++] = BoolGetDatum(true); /* typisdefined */ values[i++] = CharGetDatum(typDelim); /* typdelim */ values[i++] = ObjectIdGetDatum(relationOid); /* typrelid */ diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index a8a78b561fb..1427b2a10ed 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.177 2008/06/14 18:04:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.178 2008/07/30 17:05:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1012,7 +1012,7 @@ GetDefaultOpClass(Oid type_id, Oid am_id) ScanKeyData skey[1]; SysScanDesc scan; HeapTuple tup; - CATEGORY tcategory; + TYPCATEGORY tcategory; /* If it's a domain, look at the base type instead */ type_id = getBaseType(type_id); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 793e9262e3e..84d8036057c 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.119 2008/06/14 18:04:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.120 2008/07/30 17:05:04 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -111,6 +111,8 @@ DefineType(List *names, List *parameters) List *analyzeName = NIL; char *defaultValue = NULL; bool byValue = false; + char category = TYPCATEGORY_USER; + bool preferred = true; char delimiter = DEFAULT_TYPDELIM; char alignment = 'i'; /* default alignment */ char storage = 'p'; /* default TOAST storage method */ @@ -188,8 +190,6 @@ DefineType(List *names, List *parameters) if (pg_strcasecmp(defel->defname, "internallength") == 0) internalLength = defGetTypeLength(defel); - else if (pg_strcasecmp(defel->defname, "externallength") == 0) - ; /* ignored -- remove after 7.3 */ else if (pg_strcasecmp(defel->defname, "input") == 0) inputName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "output") == 0) @@ -205,11 +205,26 @@ DefineType(List *names, List *parameters) else if (pg_strcasecmp(defel->defname, "analyze") == 0 || pg_strcasecmp(defel->defname, "analyse") == 0) analyzeName = defGetQualifiedName(defel); + else if (pg_strcasecmp(defel->defname, "category") == 0) + { + char *p = defGetString(defel); + + category = p[0]; + /* restrict to non-control ASCII */ + if (category < 32 || category > 126) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid type category \"%s\": must be simple ASCII", + p))); + } + else if (pg_strcasecmp(defel->defname, "preferred") == 0) + preferred = defGetBoolean(defel); else if (pg_strcasecmp(defel->defname, "delimiter") == 0) { char *p = defGetString(defel); delimiter = p[0]; + /* XXX shouldn't we restrict the delimiter? */ } else if (pg_strcasecmp(defel->defname, "element") == 0) { @@ -421,6 +436,8 @@ DefineType(List *names, List *parameters) 0, /* relation kind (ditto) */ internalLength, /* internal size */ TYPTYPE_BASE, /* type-type (base type) */ + category, /* type-category */ + preferred, /* is it a preferred type? */ delimiter, /* array element delimiter */ inputOid, /* input procedure */ outputOid, /* output procedure */ @@ -457,6 +474,8 @@ DefineType(List *names, List *parameters) 0, /* relation kind (ditto) */ -1, /* internal size (always varlena) */ TYPTYPE_BASE, /* type-type (base type) */ + TYPCATEGORY_ARRAY, /* type-category (array) */ + true, /* all array types are preferred */ DEFAULT_TYPDELIM, /* array element delimiter */ F_ARRAY_IN, /* input procedure */ F_ARRAY_OUT, /* output procedure */ @@ -624,6 +643,7 @@ DefineDomain(CreateDomainStmt *stmt) Oid analyzeProcedure; bool byValue; Oid typelem; + char category; char delimiter; char alignment; char storage; @@ -705,6 +725,9 @@ DefineDomain(CreateDomainStmt *stmt) /* Storage Length */ internalLength = baseType->typlen; + /* Type Category */ + category = baseType->typcategory; + /* Array element type (in case base type is an array) */ typelem = baseType->typelem; @@ -895,6 +918,8 @@ DefineDomain(CreateDomainStmt *stmt) 0, /* relation kind (ditto) */ internalLength, /* internal size */ TYPTYPE_DOMAIN, /* type-type (domain type) */ + category, /* type-category */ + false, /* domains are never preferred types */ delimiter, /* array element delimiter */ inputProcedure, /* input procedure */ outputProcedure, /* output procedure */ @@ -1006,6 +1031,8 @@ DefineEnum(CreateEnumStmt *stmt) 0, /* relation kind (ditto) */ sizeof(Oid), /* internal size */ TYPTYPE_ENUM, /* type-type (enum type) */ + TYPCATEGORY_ENUM, /* type-category (enum type) */ + true, /* all enum types are preferred */ DEFAULT_TYPDELIM, /* array element delimiter */ F_ENUM_IN, /* input procedure */ F_ENUM_OUT, /* output procedure */ @@ -1042,6 +1069,8 @@ DefineEnum(CreateEnumStmt *stmt) 0, /* relation kind (ditto) */ -1, /* internal size (always varlena) */ TYPTYPE_BASE, /* type-type (base type) */ + TYPCATEGORY_ARRAY, /* type-category (array) */ + true, /* all array types are preferred */ DEFAULT_TYPDELIM, /* array element delimiter */ F_ARRAY_IN, /* input procedure */ F_ARRAY_OUT, /* output procedure */ diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 24676404340..df5ad09bae1 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -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() diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 3bb5c452a8e..785e8816a94 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.203 2008/07/16 01:30:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.204 2008/07/30 17:05:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -439,8 +439,9 @@ func_select_candidate(int nargs, int nbestMatch, nmatch; Oid input_base_typeids[FUNC_MAX_ARGS]; - CATEGORY slot_category[FUNC_MAX_ARGS], + TYPCATEGORY slot_category[FUNC_MAX_ARGS], current_category; + bool current_is_preferred; bool slot_has_preferred_type[FUNC_MAX_ARGS]; bool resolved_unknowns; @@ -591,7 +592,7 @@ func_select_candidate(int nargs, if (input_base_typeids[i] != UNKNOWNOID) continue; resolved_unknowns = true; /* assume we can do it */ - slot_category[i] = INVALID_TYPE; + slot_category[i] = TYPCATEGORY_INVALID; slot_has_preferred_type[i] = false; have_conflict = false; for (current_candidate = candidates; @@ -600,29 +601,28 @@ func_select_candidate(int nargs, { current_typeids = current_candidate->args; current_type = current_typeids[i]; - current_category = TypeCategory(current_type); - if (slot_category[i] == INVALID_TYPE) + get_type_category_preferred(current_type, + ¤t_category, + ¤t_is_preferred); + if (slot_category[i] == TYPCATEGORY_INVALID) { /* first candidate */ slot_category[i] = current_category; - slot_has_preferred_type[i] = - IsPreferredType(current_category, current_type); + slot_has_preferred_type[i] = current_is_preferred; } else if (current_category == slot_category[i]) { /* more candidates in same category */ - slot_has_preferred_type[i] |= - IsPreferredType(current_category, current_type); + slot_has_preferred_type[i] |= current_is_preferred; } else { /* category conflict! */ - if (current_category == STRING_TYPE) + if (current_category == TYPCATEGORY_STRING) { /* STRING always wins if available */ slot_category[i] = current_category; - slot_has_preferred_type[i] = - IsPreferredType(current_category, current_type); + slot_has_preferred_type[i] = current_is_preferred; } else { @@ -633,7 +633,7 @@ func_select_candidate(int nargs, } } } - if (have_conflict && slot_category[i] != STRING_TYPE) + if (have_conflict && slot_category[i] != TYPCATEGORY_STRING) { /* Failed to resolve category conflict at this position */ resolved_unknowns = false; @@ -658,14 +658,15 @@ func_select_candidate(int nargs, if (input_base_typeids[i] != UNKNOWNOID) continue; current_type = current_typeids[i]; - current_category = TypeCategory(current_type); + get_type_category_preferred(current_type, + ¤t_category, + ¤t_is_preferred); if (current_category != slot_category[i]) { keepit = false; break; } - if (slot_has_preferred_type[i] && - !IsPreferredType(current_category, current_type)) + if (slot_has_preferred_type[i] && !current_is_preferred) { keepit = false; break; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index e17bd49e629..79362441f8e 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.157 2008/04/13 20:51:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.158 2008/07/30 17:05:04 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -2168,6 +2168,29 @@ type_is_enum(Oid typid) } /* + * get_type_category_preferred + * + * Given the type OID, fetch its category and preferred-type status. + * Throws error on failure. + */ +void +get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred) +{ + HeapTuple tp; + Form_pg_type typtup; + + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for type %u", typid); + typtup = (Form_pg_type) GETSTRUCT(tp); + *typcategory = typtup->typcategory; + *typispreferred = typtup->typispreferred; + ReleaseSysCache(tp); +} + +/* * get_typ_typrelid * * Given the type OID, get the typrelid (InvalidOid if not a complex |