diff options
Diffstat (limited to 'src/backend/commands/indexcmds.c')
-rw-r--r-- | src/backend/commands/indexcmds.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 5f54f66f591..a5cc047c69b 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.149 2006/10/04 00:29:51 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.150 2006/12/23 00:43:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -802,31 +802,37 @@ GetIndexOpClass(List *opclass, Oid attrType, Oid GetDefaultOpClass(Oid type_id, Oid am_id) { + Oid result = InvalidOid; int nexact = 0; int ncompatible = 0; - Oid exactOid = InvalidOid; - Oid compatibleOid = InvalidOid; + int ncompatiblepreferred = 0; Relation rel; ScanKeyData skey[1]; SysScanDesc scan; HeapTuple tup; + CATEGORY tcategory; /* If it's a domain, look at the base type instead */ type_id = getBaseType(type_id); + tcategory = TypeCategory(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. + * We could find more than one binary-compatible match. If just one is + * for a preferred type, use that one; otherwise we fail, forcing the user + * to specify which one he wants. (The preferred-type special case is a + * kluge for varchar: it's binary-compatible to both text and bpchar, so + * we need a tiebreaker.) If we find more than one exact match, then + * someone put bogus entries in pg_opclass. */ rel = heap_open(OperatorClassRelationId, AccessShareLock); ScanKeyInit(&skey[0], - Anum_pg_opclass_opcamid, + Anum_pg_opclass_opcmethod, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(am_id)); @@ -837,17 +843,26 @@ GetDefaultOpClass(Oid type_id, Oid am_id) { Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup); - if (opclass->opcdefault) + /* ignore altogether if not a default opclass */ + if (!opclass->opcdefault) + continue; + if (opclass->opcintype == type_id) { - if (opclass->opcintype == type_id) + nexact++; + result = HeapTupleGetOid(tup); + } + else if (nexact == 0 && + IsBinaryCoercible(type_id, opclass->opcintype)) + { + if (IsPreferredType(tcategory, opclass->opcintype)) { - nexact++; - exactOid = HeapTupleGetOid(tup); + ncompatiblepreferred++; + result = HeapTupleGetOid(tup); } - else if (IsBinaryCoercible(type_id, opclass->opcintype)) + else if (ncompatiblepreferred == 0) { ncompatible++; - compatibleOid = HeapTupleGetOid(tup); + result = HeapTupleGetOid(tup); } } } @@ -856,15 +871,17 @@ GetDefaultOpClass(Oid type_id, Oid am_id) heap_close(rel, AccessShareLock); - if (nexact == 1) - return exactOid; - if (nexact != 0) + /* raise error if pg_opclass contains inconsistent data */ + if (nexact > 1) 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; + + if (nexact == 1 || + ncompatiblepreferred == 1 || + (ncompatiblepreferred == 0 && ncompatible == 1)) + return result; return InvalidOid; } |