1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-16 15:02:33 +03:00

Implement types regprocedure, regoper, regoperator, regclass, regtype

per pghackers discussion.  Add some more typsanity tests, and clean
up some problems exposed thereby (broken or missing array types for
some built-in types).  Also, clean up loose ends from unknownin/out
patch.
This commit is contained in:
Tom Lane
2002-04-25 02:56:56 +00:00
parent 4eac3919dd
commit 52200befd0
28 changed files with 1638 additions and 229 deletions

View File

@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.125 2002/03/26 19:15:16 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.126 2002/04/25 02:56:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -109,12 +109,14 @@ static struct typinfo Procid[] = {
{"int2vector", INT2VECTOROID, 0, INDEX_MAX_KEYS * 2, F_INT2VECTORIN, F_INT2VECTOROUT},
{"int4", INT4OID, 0, 4, F_INT4IN, F_INT4OUT},
{"regproc", REGPROCOID, 0, 4, F_REGPROCIN, F_REGPROCOUT},
{"regclass", REGCLASSOID, 0, 4, F_REGCLASSIN, F_REGCLASSOUT},
{"regtype", REGTYPEOID, 0, 4, F_REGTYPEIN, F_REGTYPEOUT},
{"text", TEXTOID, 0, -1, F_TEXTIN, F_TEXTOUT},
{"oid", OIDOID, 0, 4, F_OIDIN, F_OIDOUT},
{"tid", TIDOID, 0, 6, F_TIDIN, F_TIDOUT},
{"xid", XIDOID, 0, 4, F_XIDIN, F_XIDOUT},
{"cid", CIDOID, 0, 4, F_CIDIN, F_CIDOUT},
{"oidvector", 30, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT},
{"oidvector", OIDVECTOROID, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT},
{"smgr", 210, 0, 2, F_SMGRIN, F_SMGROUT},
{"_int4", 1007, INT4OID, -1, F_ARRAY_IN, F_ARRAY_OUT},
{"_aclitem", 1034, 1033, -1, F_ARRAY_IN, F_ARRAY_OUT}
@@ -600,7 +602,7 @@ DefineAttr(char *name, char *type, int attnum)
attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen;
attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;;
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
attrtypes[attnum]->attalign = Ap->am_typ.typalign;
}
else
@@ -610,28 +612,37 @@ DefineAttr(char *name, char *type, int attnum)
elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
attrtypes[attnum]->attstorage = 'p';
/*
* Cheat like mad to fill in these items from the length only.
* This only has to work for types used in the system catalogs...
* This only has to work for types that appear in Procid[].
*/
switch (attlen)
{
case 1:
attrtypes[attnum]->attbyval = true;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 'c';
break;
case 2:
attrtypes[attnum]->attbyval = true;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 's';
break;
case 4:
attrtypes[attnum]->attbyval = true;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 'i';
break;
case -1:
attrtypes[attnum]->attbyval = false;
attrtypes[attnum]->attstorage = 'x';
attrtypes[attnum]->attalign = 'i';
break;
default:
/* TID and fixed-length arrays, such as oidvector */
attrtypes[attnum]->attbyval = false;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 'i';
break;
}
@@ -803,6 +814,13 @@ cleanup()
/* ----------------
* gettype
*
* NB: this is really ugly; it will return an integer index into Procid[],
* and not an OID at all, until the first reference to a type not known in
* Procid[]. At that point it will read and cache pg_type in the Typ array,
* and subsequently return a real OID (and set the global pointer Ap to
* point at the found row in Typ). So caller must check whether Typ is
* still NULL to determine what the return value is!
* ----------------
*/
static Oid
@@ -827,7 +845,7 @@ gettype(char *type)
}
else
{
for (i = 0; i <= n_types; i++)
for (i = 0; i < n_types; i++)
{
if (strncmp(type, Procid[i].name, NAMEDATALEN) == 0)
return i;

View File

@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.11 2002/04/17 20:57:56 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.12 2002/04/25 02:56:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -365,9 +365,12 @@ OpclassnameGetOpcid(Oid amid, const char *opcname)
* Given a possibly-qualified function name and argument count,
* retrieve a list of the possible matches.
*
* If nargs is -1, we return all functions matching the given name,
* regardless of argument count.
*
* We search a single namespace if the function name is qualified, else
* all namespaces in the search path. The return list will never contain
* multiple entries with identical argument types --- in the multiple-
* multiple entries with identical argument lists --- in the multiple-
* namespace case, we arrange for entries in earlier namespaces to mask
* identical entries in later namespaces.
*/
@@ -423,11 +426,16 @@ FuncnameGetCandidates(List *names, int nargs)
namespaceId = InvalidOid;
}
/* Search syscache by name and nargs only */
catlist = SearchSysCacheList(PROCNAMENSP, 2,
CStringGetDatum(funcname),
Int16GetDatum(nargs),
0, 0);
/* Search syscache by name and (optionally) nargs only */
if (nargs >= 0)
catlist = SearchSysCacheList(PROCNAMENSP, 2,
CStringGetDatum(funcname),
Int16GetDatum(nargs),
0, 0);
else
catlist = SearchSysCacheList(PROCNAMENSP, 1,
CStringGetDatum(funcname),
0, 0, 0);
for (i = 0; i < catlist->n_members; i++)
{
@@ -436,6 +444,8 @@ FuncnameGetCandidates(List *names, int nargs)
int pathpos = 0;
FuncCandidateList newResult;
nargs = procform->pronargs;
if (OidIsValid(namespaceId))
{
/* Consider only procs in specified namespace */
@@ -478,7 +488,8 @@ FuncnameGetCandidates(List *names, int nargs)
if (catlist->ordered)
{
if (memcmp(procform->proargtypes, resultList->args,
if (nargs == resultList->nargs &&
memcmp(procform->proargtypes, resultList->args,
nargs * sizeof(Oid)) == 0)
prevResult = resultList;
else
@@ -490,7 +501,8 @@ FuncnameGetCandidates(List *names, int nargs)
prevResult;
prevResult = prevResult->next)
{
if (memcmp(procform->proargtypes, prevResult->args,
if (nargs == prevResult->nargs &&
memcmp(procform->proargtypes, prevResult->args,
nargs * sizeof(Oid)) == 0)
break;
}
@@ -517,6 +529,7 @@ FuncnameGetCandidates(List *names, int nargs)
+ nargs * sizeof(Oid));
newResult->pathpos = pathpos;
newResult->oid = proctup->t_data->t_oid;
newResult->nargs = nargs;
memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
newResult->next = resultList;
@@ -533,14 +546,17 @@ FuncnameGetCandidates(List *names, int nargs)
* Given a possibly-qualified operator name and operator kind,
* retrieve a list of the possible matches.
*
* If oprkind is '\0', we return all operators matching the given name,
* regardless of arguments.
*
* We search a single namespace if the operator name is qualified, else
* all namespaces in the search path. The return list will never contain
* multiple entries with identical argument types --- in the multiple-
* multiple entries with identical argument lists --- in the multiple-
* namespace case, we arrange for entries in earlier namespaces to mask
* identical entries in later namespaces.
*
* The returned items always have two args[] entries --- one or the other
* will be InvalidOid for a prefix or postfix oprkind.
* will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
*/
FuncCandidateList
OpernameGetCandidates(List *names, char oprkind)
@@ -606,8 +622,8 @@ OpernameGetCandidates(List *names, char oprkind)
int pathpos = 0;
FuncCandidateList newResult;
/* Ignore operators of wrong kind */
if (operform->oprkind != oprkind)
/* Ignore operators of wrong kind, if specific kind requested */
if (oprkind && operform->oprkind != oprkind)
continue;
if (OidIsValid(namespaceId))
@@ -690,6 +706,7 @@ OpernameGetCandidates(List *names, char oprkind)
palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
newResult->pathpos = pathpos;
newResult->oid = opertup->t_data->t_oid;
newResult->nargs = 2;
newResult->args[0] = operform->oprleft;
newResult->args[1] = operform->oprright;
newResult->next = resultList;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.66 2002/04/16 23:08:10 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.67 2002/04/25 02:56:55 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
@@ -138,7 +138,7 @@ OperatorGet(const char *operatorName,
ObjectIdGetDatum(operatorNamespace));
if (HeapTupleIsValid(tup))
{
regproc oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
operatorObjectId = tup->t_data->t_oid;
*defined = RegProcedureIsValid(oprcode);
@@ -168,7 +168,7 @@ OperatorLookup(List *operatorName,
bool *defined)
{
Oid operatorObjectId;
regproc oprcode;
RegProcedure oprcode;
operatorObjectId = LookupOperName(operatorName, leftObjectId,
rightObjectId);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.70 2002/04/11 20:00:00 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.71 2002/04/25 02:56:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -81,8 +81,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
if (!con->constisnull)
{
/* We know the source constant is really of type 'text' */
char *val = DatumGetCString(DirectFunctionCall1(textout,
char *val = DatumGetCString(DirectFunctionCall1(unknownout,
con->constvalue));
newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
@@ -477,6 +476,11 @@ TypeCategory(Oid inType)
case (OIDOID):
case (REGPROCOID):
case (REGPROCEDUREOID):
case (REGOPEROID):
case (REGOPERATOROID):
case (REGCLASSOID):
case (REGTYPEOID):
case (INT2OID):
case (INT4OID):
case (INT8OID):
@@ -540,38 +544,72 @@ TypeCategory(Oid inType)
* to allow for better type extensibility.
*/
#define TypeIsTextGroup(t) \
((t) == TEXTOID || \
(t) == BPCHAROID || \
(t) == VARCHAROID)
/* Notice OidGroup is a subset of Int4GroupA */
#define TypeIsOidGroup(t) \
((t) == OIDOID || \
(t) == REGPROCOID || \
(t) == REGPROCEDUREOID || \
(t) == REGOPEROID || \
(t) == REGOPERATOROID || \
(t) == REGCLASSOID || \
(t) == REGTYPEOID)
/*
* This macro describes hard-coded knowledge of binary compatibility
* for built-in types.
* INT4 is binary-compatible with many types, but we don't want to allow
* implicit coercion directly between, say, OID and AbsTime. So we subdivide
* the categories.
*/
#define IS_BINARY_COMPATIBLE(a,b) \
(((a) == BPCHAROID && (b) == TEXTOID) \
|| ((a) == BPCHAROID && (b) == VARCHAROID) \
|| ((a) == VARCHAROID && (b) == TEXTOID) \
|| ((a) == VARCHAROID && (b) == BPCHAROID) \
|| ((a) == TEXTOID && (b) == BPCHAROID) \
|| ((a) == TEXTOID && (b) == VARCHAROID) \
|| ((a) == OIDOID && (b) == INT4OID) \
|| ((a) == OIDOID && (b) == REGPROCOID) \
|| ((a) == INT4OID && (b) == OIDOID) \
|| ((a) == INT4OID && (b) == REGPROCOID) \
|| ((a) == REGPROCOID && (b) == OIDOID) \
|| ((a) == REGPROCOID && (b) == INT4OID) \
|| ((a) == ABSTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == ABSTIMEOID) \
|| ((a) == RELTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == RELTIMEOID) \
|| ((a) == INETOID && (b) == CIDROID) \
|| ((a) == CIDROID && (b) == INETOID) \
|| ((a) == BITOID && (b) == VARBITOID) \
|| ((a) == VARBITOID && (b) == BITOID))
#define TypeIsInt4GroupA(t) \
((t) == INT4OID || \
TypeIsOidGroup(t))
#define TypeIsInt4GroupB(t) \
((t) == INT4OID || \
(t) == ABSTIMEOID)
#define TypeIsInt4GroupC(t) \
((t) == INT4OID || \
(t) == RELTIMEOID)
#define TypeIsInetGroup(t) \
((t) == INETOID || \
(t) == CIDROID)
#define TypeIsBitGroup(t) \
((t) == BITOID || \
(t) == VARBITOID)
static bool
DirectlyBinaryCompatible(Oid type1, Oid type2)
{
if (type1 == type2)
return true;
if (TypeIsTextGroup(type1) && TypeIsTextGroup(type2))
return true;
if (TypeIsInt4GroupA(type1) && TypeIsInt4GroupA(type2))
return true;
if (TypeIsInt4GroupB(type1) && TypeIsInt4GroupB(type2))
return true;
if (TypeIsInt4GroupC(type1) && TypeIsInt4GroupC(type2))
return true;
if (TypeIsInetGroup(type1) && TypeIsInetGroup(type2))
return true;
if (TypeIsBitGroup(type1) && TypeIsBitGroup(type2))
return true;
return false;
}
bool
IsBinaryCompatible(Oid type1, Oid type2)
{
if (type1 == type2)
return true;
if (IS_BINARY_COMPATIBLE(type1, type2))
if (DirectlyBinaryCompatible(type1, type2))
return true;
/*
* Perhaps the types are domains; if so, look at their base types
@@ -580,9 +618,7 @@ IsBinaryCompatible(Oid type1, Oid type2)
type1 = getBaseType(type1);
if (OidIsValid(type2))
type2 = getBaseType(type2);
if (type1 == type2)
return true;
if (IS_BINARY_COMPATIBLE(type1, type2))
if (DirectlyBinaryCompatible(type1, type2))
return true;
return false;
}
@@ -627,7 +663,7 @@ PreferredType(CATEGORY category, Oid type)
break;
case (NUMERIC_TYPE):
if (type == OIDOID)
if (TypeIsOidGroup(type))
result = OIDOID;
else if (type == NUMERICOID)
result = NUMERICOID;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.62 2002/04/16 23:08:11 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.63 2002/04/25 02:56:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -424,7 +424,8 @@ make_const(Value *value)
break;
case T_String:
val = DirectFunctionCall1(textin, CStringGetDatum(strVal(value)));
val = DirectFunctionCall1(unknownin,
CStringGetDatum(strVal(value)));
typeid = UNKNOWNOID; /* will be coerced later */
typelen = -1; /* variable len */

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.98 2002/04/19 23:13:54 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.99 2002/04/25 02:56:55 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -123,7 +123,7 @@ static void get_delete_query_def(Query *query, deparse_context *context);
static void get_utility_query_def(Query *query, deparse_context *context);
static void get_basic_select_query(Query *query, deparse_context *context);
static void get_setop_query(Node *setOp, Query *query,
deparse_context *context, bool toplevel);
deparse_context *context);
static void get_rule_sortgroupclause(SortClause *srt, List *tlist,
bool force_colno,
deparse_context *context);
@@ -142,7 +142,6 @@ static void get_from_clause_item(Node *jtnode, Query *query,
static void get_opclass_name(Oid opclass, Oid actual_datatype,
StringInfo buf);
static bool tleIsArrayAssign(TargetEntry *tle);
static char *quote_identifier(char *ident);
static char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
@@ -1109,7 +1108,7 @@ get_select_query_def(Query *query, deparse_context *context)
*/
if (query->setOperations)
{
get_setop_query(query->setOperations, query, context, true);
get_setop_query(query->setOperations, query, context);
/* ORDER BY clauses must be simple in this case */
force_colno = true;
}
@@ -1266,8 +1265,7 @@ get_basic_select_query(Query *query, deparse_context *context)
}
static void
get_setop_query(Node *setOp, Query *query, deparse_context *context,
bool toplevel)
get_setop_query(Node *setOp, Query *query, deparse_context *context)
{
StringInfo buf = context->buf;
@@ -1284,33 +1282,29 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
{
SetOperationStmt *op = (SetOperationStmt *) setOp;
/*
* Must suppress parens at top level of a setop tree because of
* grammar limitations...
*/
if (!toplevel)
appendStringInfo(buf, "(");
get_setop_query(op->larg, query, context, false);
appendStringInfo(buf, "((");
get_setop_query(op->larg, query, context);
switch (op->op)
{
case SETOP_UNION:
appendStringInfo(buf, " UNION ");
appendStringInfo(buf, ") UNION ");
break;
case SETOP_INTERSECT:
appendStringInfo(buf, " INTERSECT ");
appendStringInfo(buf, ") INTERSECT ");
break;
case SETOP_EXCEPT:
appendStringInfo(buf, " EXCEPT ");
appendStringInfo(buf, ") EXCEPT ");
break;
default:
elog(ERROR, "get_setop_query: unexpected set op %d",
(int) op->op);
}
if (op->all)
appendStringInfo(buf, "ALL ");
get_setop_query(op->rarg, query, context, false);
if (!toplevel)
appendStringInfo(buf, ")");
appendStringInfo(buf, "ALL (");
else
appendStringInfo(buf, "(");
get_setop_query(op->rarg, query, context);
appendStringInfo(buf, "))");
}
else
{
@@ -2585,8 +2579,8 @@ tleIsArrayAssign(TargetEntry *tle)
* space-wasteful but well worth it for notational simplicity.
* ----------
*/
static char *
quote_identifier(char *ident)
const char *
quote_identifier(const char *ident)
{
/*
* Can avoid quoting if ident starts with a lowercase letter and
@@ -2603,7 +2597,7 @@ quote_identifier(char *ident)
safe = (ident[0] >= 'a' && ident[0] <= 'z');
if (safe)
{
char *ptr;
const char *ptr;
for (ptr = ident + 1; *ptr; ptr++)
{
@@ -2628,7 +2622,7 @@ quote_identifier(char *ident)
* Note: ScanKeywordLookup() does case-insensitive comparison, but
* that's fine, since we already know we have all-lower-case.
*/
if (ScanKeywordLookup(ident) != NULL)
if (ScanKeywordLookup((char *) ident) != NULL)
safe = false;
}
@@ -2640,6 +2634,26 @@ quote_identifier(char *ident)
return result;
}
/* ----------
* quote_qualified_identifier - Quote a possibly-qualified identifier
*
* Return a name of the form namespace.ident, or just ident if namespace
* is NULL, quoting each component if necessary. The result is palloc'd.
* ----------
*/
char *
quote_qualified_identifier(const char *namespace,
const char *ident)
{
StringInfoData buf;
initStringInfo(&buf);
if (namespace)
appendStringInfo(&buf, "%s.", quote_identifier(namespace));
appendStringInfo(&buf, "%s", quote_identifier(ident));
return buf.data;
}
/* ----------
* get_relid_attribute_name
* Get an attribute name by its relations Oid and its attnum

View File

@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.109 2002/04/21 19:48:13 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.110 2002/04/25 02:56:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1991,6 +1991,11 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case NUMERICOID:
case OIDOID:
case REGPROCOID:
case REGPROCEDUREOID:
case REGOPEROID:
case REGOPERATOROID:
case REGCLASSOID:
case REGTYPEOID:
*scaledvalue = convert_numeric_to_scalar(value, valuetypid);
*scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
*scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
@@ -2088,6 +2093,11 @@ convert_numeric_to_scalar(Datum value, Oid typid)
value));
case OIDOID:
case REGPROCOID:
case REGPROCEDUREOID:
case REGOPEROID:
case REGOPERATOROID:
case REGCLASSOID:
case REGTYPEOID:
/* we can treat OIDs as integers... */
return (double) DatumGetObjectId(value);
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.84 2002/04/24 02:12:53 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.85 2002/04/25 02:56:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,13 @@
#include "utils/builtins.h"
#include "utils/pg_locale.h"
typedef struct varlena unknown;
#define DatumGetUnknownP(X) ((unknown *) PG_DETOAST_DATUM(X))
#define PG_GETARG_UNKNOWN_P(n) DatumGetUnknownP(PG_GETARG_DATUM(n))
#define PG_RETURN_UNKNOWN_P(x) PG_RETURN_POINTER(x)
static int text_cmp(text *arg1, text *arg2);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.94 2002/04/06 06:59:22 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.95 2002/04/25 02:56:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,8 +136,13 @@ GetCCHashFunc(Oid keytype)
return hashint4;
case TEXTOID:
return hashvarlena;
case REGPROCOID:
case OIDOID:
case REGPROCOID:
case REGPROCEDUREOID:
case REGOPEROID:
case REGOPERATOROID:
case REGCLASSOID:
case REGTYPEOID:
return hashoid;
case OIDVECTOROID:
return hashoidvector;