diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 0f04bd0ba3..fe61ee242e 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.80 2005/11/22 18:17:08 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.81 2006/02/10 19:01:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -911,119 +911,6 @@ OperatorIsVisible(Oid oprid) } -/* - * OpclassGetCandidates - * Given an index access method OID, retrieve a list of all the - * opclasses for that AM that are visible in the search path. - * - * NOTE: the opcname_tmp field in the returned structs should not be used - * by callers, because it points at syscache entries that we release at - * the end of this routine. If any callers needed the name information, - * we could pstrdup() the names ... but at present it'd be wasteful. - */ -OpclassCandidateList -OpclassGetCandidates(Oid amid) -{ - OpclassCandidateList resultList = NULL; - CatCList *catlist; - int i; - - /* Search syscache by AM OID only */ - catlist = SearchSysCacheList(CLAAMNAMENSP, 1, - ObjectIdGetDatum(amid), - 0, 0, 0); - - recomputeNamespacePath(); - - for (i = 0; i < catlist->n_members; i++) - { - HeapTuple opctup = &catlist->members[i]->tuple; - Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup); - int pathpos = 0; - OpclassCandidateList newResult; - ListCell *nsp; - - /* Consider only opclasses that are in the search path */ - foreach(nsp, namespaceSearchPath) - { - if (opcform->opcnamespace == lfirst_oid(nsp)) - break; - pathpos++; - } - if (nsp == NULL) - continue; /* opclass is not in search path */ - - /* - * Okay, it's in the search path, but does it have the same name as - * something we already accepted? If so, keep only the one that - * appears earlier in the search path. - * - * If we have an ordered list from SearchSysCacheList (the normal - * case), then any conflicting opclass must immediately adjoin this - * one in the list, so we only need to look at the newest result item. - * If we have an unordered list, we have to scan the whole result - * list. - */ - if (resultList) - { - OpclassCandidateList prevResult; - - if (catlist->ordered) - { - if (strcmp(NameStr(opcform->opcname), - resultList->opcname_tmp) == 0) - prevResult = resultList; - else - prevResult = NULL; - } - else - { - for (prevResult = resultList; - prevResult; - prevResult = prevResult->next) - { - if (strcmp(NameStr(opcform->opcname), - prevResult->opcname_tmp) == 0) - break; - } - } - if (prevResult) - { - /* We have a match with a previous result */ - Assert(pathpos != prevResult->pathpos); - if (pathpos > prevResult->pathpos) - continue; /* keep previous result */ - /* replace previous result */ - prevResult->opcname_tmp = NameStr(opcform->opcname); - prevResult->pathpos = pathpos; - prevResult->oid = HeapTupleGetOid(opctup); - prevResult->opcintype = opcform->opcintype; - prevResult->opcdefault = opcform->opcdefault; - prevResult->opckeytype = opcform->opckeytype; - continue; - } - } - - /* - * Okay to add it to result list - */ - newResult = (OpclassCandidateList) - palloc(sizeof(struct _OpclassCandidateList)); - newResult->opcname_tmp = NameStr(opcform->opcname); - newResult->pathpos = pathpos; - newResult->oid = HeapTupleGetOid(opctup); - newResult->opcintype = opcform->opcintype; - newResult->opcdefault = opcform->opcdefault; - newResult->opckeytype = opcform->opckeytype; - newResult->next = resultList; - resultList = newResult; - } - - ReleaseSysCacheList(catlist); - - return resultList; -} - /* * OpclassnameGetOpcid * Try to resolve an unqualified index opclass name. diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 4a425d4eb2..aa6ed6f9c2 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,37 +8,36 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.136 2005/11/22 18:17:09 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.137 2006/02/10 19:01:12 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/genam.h" #include "access/heapam.h" #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/heap.h" #include "catalog/index.h" -#include "catalog/namespace.h" +#include "catalog/indexing.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_proc.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" -#include "executor/executor.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "optimizer/clauses.h" -#include "optimizer/prep.h" #include "parser/parsetree.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/relcache.h" @@ -54,7 +53,6 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo, Oid *classOidP, bool isconstraint); static Oid GetIndexOpClass(List *opclass, Oid attrType, char *accessMethodName, Oid accessMethodId); -static Oid GetDefaultOpClass(Oid attrType, Oid accessMethodId); static bool relationHasPrimaryKey(Relation rel); @@ -658,17 +656,26 @@ GetIndexOpClass(List *opclass, Oid attrType, return opClassId; } -static Oid -GetDefaultOpClass(Oid attrType, Oid accessMethodId) +/* + * GetDefaultOpClass + * + * Given the OIDs of a datatype and an access method, find the default + * operator class, if any. Returns InvalidOid if there is none. + */ +Oid +GetDefaultOpClass(Oid type_id, Oid am_id) { - OpclassCandidateList opclass; int nexact = 0; int ncompatible = 0; Oid exactOid = InvalidOid; Oid compatibleOid = InvalidOid; + Relation rel; + ScanKeyData skey[1]; + SysScanDesc scan; + HeapTuple tup; /* If it's a domain, look at the base type instead */ - attrType = getBaseType(attrType); + type_id = getBaseType(type_id); /* * We scan through all the opclasses available for the access method, @@ -678,37 +685,47 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId) * We could find more than one binary-compatible match, in which case we * require the user to specify which one he wants. If we find more than * one exact match, then someone put bogus entries in pg_opclass. - * - * The initial search is done by namespace.c so that we only consider - * opclasses visible in the current namespace search path. (See also - * typcache.c, which applies the same logic, but over all opclasses.) */ - for (opclass = OpclassGetCandidates(accessMethodId); - opclass != NULL; - opclass = opclass->next) + rel = heap_open(OperatorClassRelationId, AccessShareLock); + + ScanKeyInit(&skey[0], + Anum_pg_opclass_opcamid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(am_id)); + + scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true, + SnapshotNow, 1, skey); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) { + Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup); + if (opclass->opcdefault) { - if (opclass->opcintype == attrType) + if (opclass->opcintype == type_id) { nexact++; - exactOid = opclass->oid; + exactOid = HeapTupleGetOid(tup); } - else if (IsBinaryCoercible(attrType, opclass->opcintype)) + else if (IsBinaryCoercible(type_id, opclass->opcintype)) { ncompatible++; - compatibleOid = opclass->oid; + compatibleOid = HeapTupleGetOid(tup); } } } + systable_endscan(scan); + + heap_close(rel, AccessShareLock); + if (nexact == 1) return exactOid; if (nexact != 0) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("there are multiple default operator classes for data type %s", - format_type_be(attrType)))); + format_type_be(type_id)))); if (ncompatible == 1) return compatibleOid; diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 9726bd499b..af03e2a7b0 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -36,23 +36,19 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.16 2005/11/22 18:17:24 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.17 2006/02/10 19:01:12 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/hash.h" #include "access/nbtree.h" -#include "catalog/indexing.h" -#include "catalog/pg_am.h" -#include "catalog/pg_opclass.h" -#include "parser/parse_coerce.h" +#include "catalog/pg_type.h" +#include "commands/defrem.h" #include "utils/builtins.h" #include "utils/catcache.h" -#include "utils/fmgroids.h" #include "utils/hsearch.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -92,9 +88,6 @@ static int32 RecordCacheArrayLen = 0; /* allocated length of array */ static int32 NextRecordTypmod = 0; /* number of entries used */ -static Oid lookup_default_opclass(Oid type_id, Oid am_id); - - /* * lookup_type_cache * @@ -177,14 +170,14 @@ lookup_type_cache(Oid type_id, int flags) TYPECACHE_EQ_OPR_FINFO | TYPECACHE_CMP_PROC_FINFO)) && typentry->btree_opc == InvalidOid) { - typentry->btree_opc = lookup_default_opclass(type_id, - BTREE_AM_OID); + typentry->btree_opc = GetDefaultOpClass(type_id, + BTREE_AM_OID); /* Only care about hash opclass if no btree opclass... */ if (typentry->btree_opc == InvalidOid) { if (typentry->hash_opc == InvalidOid) - typentry->hash_opc = lookup_default_opclass(type_id, - HASH_AM_OID); + typentry->hash_opc = GetDefaultOpClass(type_id, + HASH_AM_OID); } else { @@ -289,86 +282,6 @@ lookup_type_cache(Oid type_id, int flags) return typentry; } -/* - * lookup_default_opclass - * - * Given the OIDs of a datatype and an access method, find the default - * operator class, if any. Returns InvalidOid if there is none. - */ -static Oid -lookup_default_opclass(Oid type_id, Oid am_id) -{ - int nexact = 0; - int ncompatible = 0; - Oid exactOid = InvalidOid; - Oid compatibleOid = InvalidOid; - Relation rel; - ScanKeyData skey[1]; - SysScanDesc scan; - HeapTuple tup; - - /* If it's a domain, look at the base type instead */ - type_id = getBaseType(type_id); - - /* - * We scan through all the opclasses available for the access method, - * looking for one that is marked default and matches the target type - * (either exactly or binary-compatibly, but prefer an exact match). - * - * We could find more than one binary-compatible match, in which case we - * require the user to specify which one he wants. If we find more than - * one exact match, then someone put bogus entries in pg_opclass. - * - * This is the same logic as GetDefaultOpClass() in indexcmds.c, except - * that we consider all opclasses, regardless of the current search path. - */ - rel = heap_open(OperatorClassRelationId, AccessShareLock); - - ScanKeyInit(&skey[0], - Anum_pg_opclass_opcamid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(am_id)); - - scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true, - SnapshotNow, 1, skey); - - while (HeapTupleIsValid(tup = systable_getnext(scan))) - { - Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup); - - if (opclass->opcdefault) - { - if (opclass->opcintype == type_id) - { - nexact++; - exactOid = HeapTupleGetOid(tup); - } - else if (IsBinaryCoercible(type_id, opclass->opcintype)) - { - ncompatible++; - compatibleOid = HeapTupleGetOid(tup); - } - } - } - - systable_endscan(scan); - - heap_close(rel, AccessShareLock); - - if (nexact == 1) - return exactOid; - if (nexact != 0) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("there are multiple default operator classes for data type %s", - format_type_be(type_id)))); - if (ncompatible == 1) - return compatibleOid; - - return InvalidOid; -} - - /* * lookup_rowtype_tupdesc * diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index d3f0dc9809..4f2d1ef506 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.37 2005/10/15 02:49:42 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.38 2006/02/10 19:01:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,21 +32,6 @@ typedef struct _FuncCandidateList Oid args[1]; /* arg types --- VARIABLE LENGTH ARRAY */ } *FuncCandidateList; /* VARIABLE LENGTH STRUCT */ -/* - * This structure holds a list of opclass candidates found by namespace - * lookup. - */ -typedef struct _OpclassCandidateList -{ - struct _OpclassCandidateList *next; - char *opcname_tmp; /* for internal use of namespace lookup */ - int pathpos; /* for internal use of namespace lookup */ - Oid oid; /* the opclass's OID */ - Oid opcintype; /* type of data indexed by opclass */ - bool opcdefault; /* T if opclass is default for opcintype */ - Oid opckeytype; /* type of data in index, or InvalidOid */ -} *OpclassCandidateList; - extern Oid RangeVarGetRelid(const RangeVar *relation, bool failOK); extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation); @@ -62,7 +47,6 @@ extern bool FunctionIsVisible(Oid funcid); extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind); extern bool OperatorIsVisible(Oid oprid); -extern OpclassCandidateList OpclassGetCandidates(Oid amid); extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname); extern bool OpclassIsVisible(Oid opcid); diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 39603cf31f..230bd63765 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.69 2005/11/21 12:49:32 alvherre Exp $ + * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.70 2006/02/10 19:01:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,6 +42,7 @@ extern char *makeObjectName(const char *name1, const char *name2, const char *label); extern char *ChooseRelationName(const char *name1, const char *name2, const char *label, Oid namespace); +extern Oid GetDefaultOpClass(Oid type_id, Oid am_id); /* commands/functioncmds.c */ extern void CreateFunction(CreateFunctionStmt *stmt);