Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3ac1ac5

Browse files
committed
Change search for default operator classes so that it examines all opclasses
regardless of the current schema search path. Since CREATE OPERATOR CLASS only allows one default opclass per datatype regardless of schemas, this should have minimal impact, and it fixes problems with failure to find a desired opclass while restoring dump files. Per discussion at http://archives.postgresql.org/pgsql-hackers/2006-02/msg00284.php. Remove now-redundant-or-unused code in typcache.c and namespace.c, and backpatch as far as 8.0.
1 parent b35fdaa commit 3ac1ac5

File tree

5 files changed

+50
-248
lines changed

5 files changed

+50
-248
lines changed

src/backend/catalog/namespace.c

+1-114
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.80 2005/11/22 18:17:08 momjian Exp $
16+
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.81 2006/02/10 19:01:12 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -911,119 +911,6 @@ OperatorIsVisible(Oid oprid)
911911
}
912912

913913

914-
/*
915-
* OpclassGetCandidates
916-
* Given an index access method OID, retrieve a list of all the
917-
* opclasses for that AM that are visible in the search path.
918-
*
919-
* NOTE: the opcname_tmp field in the returned structs should not be used
920-
* by callers, because it points at syscache entries that we release at
921-
* the end of this routine. If any callers needed the name information,
922-
* we could pstrdup() the names ... but at present it'd be wasteful.
923-
*/
924-
OpclassCandidateList
925-
OpclassGetCandidates(Oid amid)
926-
{
927-
OpclassCandidateList resultList = NULL;
928-
CatCList *catlist;
929-
int i;
930-
931-
/* Search syscache by AM OID only */
932-
catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
933-
ObjectIdGetDatum(amid),
934-
0, 0, 0);
935-
936-
recomputeNamespacePath();
937-
938-
for (i = 0; i < catlist->n_members; i++)
939-
{
940-
HeapTuple opctup = &catlist->members[i]->tuple;
941-
Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
942-
int pathpos = 0;
943-
OpclassCandidateList newResult;
944-
ListCell *nsp;
945-
946-
/* Consider only opclasses that are in the search path */
947-
foreach(nsp, namespaceSearchPath)
948-
{
949-
if (opcform->opcnamespace == lfirst_oid(nsp))
950-
break;
951-
pathpos++;
952-
}
953-
if (nsp == NULL)
954-
continue; /* opclass is not in search path */
955-
956-
/*
957-
* Okay, it's in the search path, but does it have the same name as
958-
* something we already accepted? If so, keep only the one that
959-
* appears earlier in the search path.
960-
*
961-
* If we have an ordered list from SearchSysCacheList (the normal
962-
* case), then any conflicting opclass must immediately adjoin this
963-
* one in the list, so we only need to look at the newest result item.
964-
* If we have an unordered list, we have to scan the whole result
965-
* list.
966-
*/
967-
if (resultList)
968-
{
969-
OpclassCandidateList prevResult;
970-
971-
if (catlist->ordered)
972-
{
973-
if (strcmp(NameStr(opcform->opcname),
974-
resultList->opcname_tmp) == 0)
975-
prevResult = resultList;
976-
else
977-
prevResult = NULL;
978-
}
979-
else
980-
{
981-
for (prevResult = resultList;
982-
prevResult;
983-
prevResult = prevResult->next)
984-
{
985-
if (strcmp(NameStr(opcform->opcname),
986-
prevResult->opcname_tmp) == 0)
987-
break;
988-
}
989-
}
990-
if (prevResult)
991-
{
992-
/* We have a match with a previous result */
993-
Assert(pathpos != prevResult->pathpos);
994-
if (pathpos > prevResult->pathpos)
995-
continue; /* keep previous result */
996-
/* replace previous result */
997-
prevResult->opcname_tmp = NameStr(opcform->opcname);
998-
prevResult->pathpos = pathpos;
999-
prevResult->oid = HeapTupleGetOid(opctup);
1000-
prevResult->opcintype = opcform->opcintype;
1001-
prevResult->opcdefault = opcform->opcdefault;
1002-
prevResult->opckeytype = opcform->opckeytype;
1003-
continue;
1004-
}
1005-
}
1006-
1007-
/*
1008-
* Okay to add it to result list
1009-
*/
1010-
newResult = (OpclassCandidateList)
1011-
palloc(sizeof(struct _OpclassCandidateList));
1012-
newResult->opcname_tmp = NameStr(opcform->opcname);
1013-
newResult->pathpos = pathpos;
1014-
newResult->oid = HeapTupleGetOid(opctup);
1015-
newResult->opcintype = opcform->opcintype;
1016-
newResult->opcdefault = opcform->opcdefault;
1017-
newResult->opckeytype = opcform->opckeytype;
1018-
newResult->next = resultList;
1019-
resultList = newResult;
1020-
}
1021-
1022-
ReleaseSysCacheList(catlist);
1023-
1024-
return resultList;
1025-
}
1026-
1027914
/*
1028915
* OpclassnameGetOpcid
1029916
* Try to resolve an unqualified index opclass name.

src/backend/commands/indexcmds.c

+39-22
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,36 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.136 2005/11/22 18:17:09 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.137 2006/02/10 19:01:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515

1616
#include "postgres.h"
1717

18+
#include "access/genam.h"
1819
#include "access/heapam.h"
1920
#include "catalog/catalog.h"
2021
#include "catalog/dependency.h"
2122
#include "catalog/heap.h"
2223
#include "catalog/index.h"
23-
#include "catalog/namespace.h"
24+
#include "catalog/indexing.h"
2425
#include "catalog/pg_opclass.h"
25-
#include "catalog/pg_proc.h"
2626
#include "catalog/pg_tablespace.h"
2727
#include "commands/dbcommands.h"
2828
#include "commands/defrem.h"
2929
#include "commands/tablecmds.h"
3030
#include "commands/tablespace.h"
31-
#include "executor/executor.h"
3231
#include "mb/pg_wchar.h"
3332
#include "miscadmin.h"
3433
#include "optimizer/clauses.h"
35-
#include "optimizer/prep.h"
3634
#include "parser/parsetree.h"
3735
#include "parser/parse_coerce.h"
3836
#include "parser/parse_expr.h"
3937
#include "parser/parse_func.h"
4038
#include "utils/acl.h"
4139
#include "utils/builtins.h"
40+
#include "utils/fmgroids.h"
4241
#include "utils/lsyscache.h"
4342
#include "utils/memutils.h"
4443
#include "utils/relcache.h"
@@ -54,7 +53,6 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo, Oid *classOidP,
5453
bool isconstraint);
5554
static Oid GetIndexOpClass(List *opclass, Oid attrType,
5655
char *accessMethodName, Oid accessMethodId);
57-
static Oid GetDefaultOpClass(Oid attrType, Oid accessMethodId);
5856
static bool relationHasPrimaryKey(Relation rel);
5957

6058

@@ -658,17 +656,26 @@ GetIndexOpClass(List *opclass, Oid attrType,
658656
return opClassId;
659657
}
660658

661-
static Oid
662-
GetDefaultOpClass(Oid attrType, Oid accessMethodId)
659+
/*
660+
* GetDefaultOpClass
661+
*
662+
* Given the OIDs of a datatype and an access method, find the default
663+
* operator class, if any. Returns InvalidOid if there is none.
664+
*/
665+
Oid
666+
GetDefaultOpClass(Oid type_id, Oid am_id)
663667
{
664-
OpclassCandidateList opclass;
665668
int nexact = 0;
666669
int ncompatible = 0;
667670
Oid exactOid = InvalidOid;
668671
Oid compatibleOid = InvalidOid;
672+
Relation rel;
673+
ScanKeyData skey[1];
674+
SysScanDesc scan;
675+
HeapTuple tup;
669676

670677
/* If it's a domain, look at the base type instead */
671-
attrType = getBaseType(attrType);
678+
type_id = getBaseType(type_id);
672679

673680
/*
674681
* We scan through all the opclasses available for the access method,
@@ -678,37 +685,47 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
678685
* We could find more than one binary-compatible match, in which case we
679686
* require the user to specify which one he wants. If we find more than
680687
* one exact match, then someone put bogus entries in pg_opclass.
681-
*
682-
* The initial search is done by namespace.c so that we only consider
683-
* opclasses visible in the current namespace search path. (See also
684-
* typcache.c, which applies the same logic, but over all opclasses.)
685688
*/
686-
for (opclass = OpclassGetCandidates(accessMethodId);
687-
opclass != NULL;
688-
opclass = opclass->next)
689+
rel = heap_open(OperatorClassRelationId, AccessShareLock);
690+
691+
ScanKeyInit(&skey[0],
692+
Anum_pg_opclass_opcamid,
693+
BTEqualStrategyNumber, F_OIDEQ,
694+
ObjectIdGetDatum(am_id));
695+
696+
scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true,
697+
SnapshotNow, 1, skey);
698+
699+
while (HeapTupleIsValid(tup = systable_getnext(scan)))
689700
{
701+
Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
702+
690703
if (opclass->opcdefault)
691704
{
692-
if (opclass->opcintype == attrType)
705+
if (opclass->opcintype == type_id)
693706
{
694707
nexact++;
695-
exactOid = opclass->oid;
708+
exactOid = HeapTupleGetOid(tup);
696709
}
697-
else if (IsBinaryCoercible(attrType, opclass->opcintype))
710+
else if (IsBinaryCoercible(type_id, opclass->opcintype))
698711
{
699712
ncompatible++;
700-
compatibleOid = opclass->oid;
713+
compatibleOid = HeapTupleGetOid(tup);
701714
}
702715
}
703716
}
704717

718+
systable_endscan(scan);
719+
720+
heap_close(rel, AccessShareLock);
721+
705722
if (nexact == 1)
706723
return exactOid;
707724
if (nexact != 0)
708725
ereport(ERROR,
709726
(errcode(ERRCODE_DUPLICATE_OBJECT),
710727
errmsg("there are multiple default operator classes for data type %s",
711-
format_type_be(attrType))));
728+
format_type_be(type_id))));
712729
if (ncompatible == 1)
713730
return compatibleOid;
714731

0 commit comments

Comments
 (0)