/* * List-search interface */ struct catclist * SearchSysCacheKeyArrayList(int cacheId, int numkeys, Datum *keys) { /* for catquery */ Datum key1 = 0, key2 = 0, key3 = 0, key4 = 0; Assert(numkeys < 5); switch(numkeys) { case 4: key4 = keys[3]; case 3: key3 = keys[2]; case 2: key2 = keys[1]; case 1: key1 = keys[0]; default: break; } return SearchSysCacheList(cacheId, numkeys, key1, key2, key3, key4); }
/* * FindDefaultConversion * * Find "default" conversion proc by for_encoding and to_encoding in the * given namespace. * * If found, returns the procedure's oid, otherwise InvalidOid. Note that * you get the procedure's OID not the conversion's OID! */ Oid FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding) { CatCList *catlist; HeapTuple tuple; Form_pg_conversion body; Oid proc = InvalidOid; int i; catlist = SearchSysCacheList(CONDEFAULT, 3, ObjectIdGetDatum(name_space), Int32GetDatum(for_encoding), Int32GetDatum(to_encoding), 0); for (i = 0; i < catlist->n_members; i++) { tuple = &catlist->members[i]->tuple; body = (Form_pg_conversion) GETSTRUCT(tuple); if (body->condefault) { proc = body->conproc; break; } } ReleaseSysCacheList(catlist); return proc; }
/* * get_op_hash_function * Get the OID of the datatype-specific hash function associated with * a hashable equality operator. * * Returns InvalidOid if no hash function can be found. (This indicates * that the operator should not have been marked oprcanhash.) */ Oid get_op_hash_function(Oid opno) { CatCList *catlist; int i; Oid opclass = InvalidOid; /* * Search pg_amop to see if the target operator is registered as the "=" * operator of any hash opclass. If the operator is registered in * multiple opclasses, assume we can use the associated hash function from * any one. */ catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(opno), 0, 0, 0); for (i = 0; i < catlist->n_members; i++) { HeapTuple tuple = &catlist->members[i]->tuple; Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple); if (aform->amopstrategy == HTEqualStrategyNumber && opclass_is_hash(aform->amopclaid)) { opclass = aform->amopclaid; break; } } ReleaseSysCacheList(catlist); if (OidIsValid(opclass)) { /* Found a suitable opclass, get its default hash support function */ return get_opclass_proc(opclass, InvalidOid, HASHPROC); } /* Didn't find a match... */ return InvalidOid; }
static ArrayType * enum_range_internal(Oid enumtypoid, Oid lower, Oid upper) { ArrayType *result; CatCList *list; int total, i, j; Datum *elems; list = SearchSysCacheList(ENUMTYPOIDNAME, 1, ObjectIdGetDatum(enumtypoid), 0, 0, 0); total = list->n_members; elems = (Datum *) palloc(total * sizeof(Datum)); j = 0; for (i = 0; i < total; i++) { Oid val = HeapTupleGetOid(&(list->members[i]->tuple)); if ((!OidIsValid(lower) || lower <= val) && (!OidIsValid(upper) || val <= upper)) elems[j++] = ObjectIdGetDatum(val); } /* shouldn't need the cache anymore */ ReleaseCatCacheList(list); /* sort results into OID order */ qsort(elems, j, sizeof(Datum), enum_elem_cmp); /* note this hardwires some details about the representation of Oid */ result = construct_array(elems, j, enumtypoid, sizeof(Oid), true, 'i'); pfree(elems); return result; }
Datum enum_last(PG_FUNCTION_ARGS) { Oid enumtypoid; Oid max = InvalidOid; CatCList *list; int num, i; /* * We rely on being able to get the specific enum type from the calling * expression tree. Notice that the actual value of the argument isn't * examined at all; in particular it might be NULL. */ enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0); if (enumtypoid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine actual enum type"))); list = SearchSysCacheList(ENUMTYPOIDNAME, 1, ObjectIdGetDatum(enumtypoid), 0, 0, 0); num = list->n_members; for (i = 0; i < num; i++) { Oid valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data); if (!OidIsValid(max) || valoid > max) max = valoid; } ReleaseCatCacheList(list); if (!OidIsValid(max)) /* should not happen */ elog(ERROR, "no values found for enum %s", format_type_be(enumtypoid)); PG_RETURN_OID(max); }
/* * get_op_btree_interpretation * Given an operator's OID, find out which btree opclasses it belongs to, * and what strategy number it has within each one. The results are * returned as an OID list and a parallel integer list. * * In addition to the normal btree operators, we consider a <> operator to be * a "member" of an opclass if its negator is the opclass' equality operator. * ROWCOMPARE_NE is returned as the strategy number for this case. */ void get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats) { Oid lefttype, righttype; CatCList *catlist; bool op_negated; int i; *opclasses = NIL; *opstrats = NIL; /* * Get the nominal left-hand input type of the operator; we will ignore * opclasses that don't have that as the expected input datatype. This is * a kluge to avoid being confused by binary-compatible opclasses (such as * text_ops and varchar_ops, which share the same operators). */ op_input_types(opno, &lefttype, &righttype); Assert(OidIsValid(lefttype)); /* * Find all the pg_amop entries containing the operator. */ catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(opno), 0, 0, 0); /* * If we can't find any opclass containing the op, perhaps it is a <> * operator. See if it has a negator that is in an opclass. */ op_negated = false; if (catlist->n_members == 0) { Oid op_negator = get_negator(opno); if (OidIsValid(op_negator)) { op_negated = true; ReleaseSysCacheList(catlist); catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(op_negator), 0, 0, 0); } } /* Now search the opclasses */ for (i = 0; i < catlist->n_members; i++) { HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); Oid opclass_id; StrategyNumber op_strategy; opclass_id = op_form->amopclaid; /* must be btree */ if (!opclass_is_btree(opclass_id)) continue; /* must match operator input type exactly */ if (get_opclass_input_type(opclass_id) != lefttype) continue; /* Get the operator's btree strategy number */ op_strategy = (StrategyNumber) op_form->amopstrategy; Assert(op_strategy >= 1 && op_strategy <= 5); if (op_negated) { /* Only consider negators that are = */ if (op_strategy != BTEqualStrategyNumber) continue; op_strategy = ROWCOMPARE_NE; } *opclasses = lappend_oid(*opclasses, opclass_id); *opstrats = lappend_int(*opstrats, op_strategy); } ReleaseSysCacheList(catlist); }