aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/heap.c6
-rw-r--r--src/backend/catalog/pg_type.c8
-rw-r--r--src/backend/commands/indexcmds.c4
-rw-r--r--src/backend/commands/typecmds.c35
-rw-r--r--src/backend/parser/parse_coerce.c224
-rw-r--r--src/backend/parser/parse_func.c33
-rw-r--r--src/backend/utils/cache/lsyscache.c25
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,
+ &current_category,
+ &current_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,
+ &current_category,
+ &current_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