/* * make_oper_cache_key * Fill the lookup key struct given operator name and arg types. * * Returns TRUE if successful, FALSE if the search_path overflowed * (hence no caching is possible). */ static bool make_oper_cache_key(OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId) { char *schemaname; char *opername; /* deconstruct the name list */ DeconstructQualifiedName(opname, &schemaname, &opername); /* ensure zero-fill for stable hashing */ MemSet(key, 0, sizeof(OprCacheKey)); /* save operator name and input types into key */ strlcpy(key->oprname, opername, NAMEDATALEN); key->left_arg = ltypeId; key->right_arg = rtypeId; if (schemaname) { /* search only in exact schema given */ key->search_path[0] = LookupExplicitNamespace(schemaname); } else { /* get the active search path */ if (fetch_search_path_array(key->search_path, MAX_CACHED_PATH_LEN) > MAX_CACHED_PATH_LEN) return false; /* oops, didn't fit */ } return true; }
/* * Copied from src/backend/commands/indexcmds.c, not exported. * Resolve possibly-defaulted operator class specification */ Oid GetIndexOpClass(List *opclass, Oid attrType, char *accessMethodName, Oid accessMethodId) { char *schemaname; char *opcname; HeapTuple tuple; Oid opClassId, opInputType; /* * Release 7.0 removed network_ops, timespan_ops, and datetime_ops, so we * ignore those opclass names so the default *_ops is used. This can be * removed in some later release. bjm 2000/02/07 * * Release 7.1 removes lztext_ops, so suppress that too for a while. tgl * 2000/07/30 * * Release 7.2 renames timestamp_ops to timestamptz_ops, so suppress that * too for awhile. I'm starting to think we need a better approach. tgl * 2000/10/01 * * Release 8.0 removes bigbox_ops (which was dead code for a long while * anyway). tgl 2003/11/11 */ if (list_length(opclass) == 1) { char *claname = strVal(linitial(opclass)); if (strcmp(claname, "network_ops") == 0 || strcmp(claname, "timespan_ops") == 0 || strcmp(claname, "datetime_ops") == 0 || strcmp(claname, "lztext_ops") == 0 || strcmp(claname, "timestamp_ops") == 0 || strcmp(claname, "bigbox_ops") == 0) opclass = NIL; } if (opclass == NIL) { /* no operator class specified, so find the default */ opClassId = GetDefaultOpClass(attrType, accessMethodId); if (!OidIsValid(opClassId)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("data type %s has no default operator class for access method \"%s\"", format_type_be(attrType), accessMethodName), errhint("You must specify an operator class for the index or define a default operator class for the data type."))); return opClassId; } /* * Specific opclass name given, so look up the opclass. */ /* deconstruct the name list */ DeconstructQualifiedName(opclass, &schemaname, &opcname); if (schemaname) { /* Look in specific schema only */ Oid namespaceId; #if PG_VERSION_NUM >= 90300 namespaceId = LookupExplicitNamespace(schemaname, false); #else namespaceId = LookupExplicitNamespace(schemaname); #endif tuple = SearchSysCache3(CLAAMNAMENSP, ObjectIdGetDatum(accessMethodId), PointerGetDatum(opcname), ObjectIdGetDatum(namespaceId)); } else { /* Unqualified opclass name, so search the search path */ opClassId = OpclassnameGetOpcid(accessMethodId, opcname); if (!OidIsValid(opClassId)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("operator class \"%s\" does not exist for access method \"%s\"", opcname, accessMethodName))); tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opClassId)); } if (!HeapTupleIsValid(tuple)) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("operator class \"%s\" does not exist for access method \"%s\"", NameListToString(opclass), accessMethodName))); } /* * Verify that the index operator class accepts this datatype. Note we * will accept binary compatibility. */ opClassId = HeapTupleGetOid(tuple); opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype; if (!IsBinaryCoercible(attrType, opInputType)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("operator class \"%s\" does not accept data type %s", NameListToString(opclass), format_type_be(attrType)))); ReleaseSysCache(tuple); return opClassId; }