/*------------------------------------------------------------------------- * * lsyscache.c-- * Routines to access information within system caches * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.23 1999/02/03 21:17:33 momjian Exp $ * * NOTES * Eventually, the index information should go through here, too. * * Most of these routines call SearchSysCacheStruct() and thus simply * (1) allocate some space for the return struct and (2) call it. * *------------------------------------------------------------------------- */ #include #include "postgres.h" #include "nodes/pg_list.h" #include "utils/syscache.h" #include "utils/lsyscache.h" #include "access/tupmacs.h" #include "utils/rel.h" #include "utils/palloc.h" #include "utils/elog.h" #include "access/attnum.h" #include "access/heapam.h" #include "catalog/pg_amop.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" /* ---------- AMOP CACHES ---------- */ /* * op_class - * * Return t iff operator 'opno' is in operator class 'opclass'. * */ bool op_class(Oid oprno, int32 opclass, Oid amopid) { FormData_pg_amop amoptup; if (SearchSysCacheStruct(AMOPOPID, (char *) &amoptup, ObjectIdGetDatum(opclass), ObjectIdGetDatum(oprno), ObjectIdGetDatum(amopid), 0)) return true; else return false; } /* ---------- ATTRIBUTE CACHES ---------- */ /* * get_attname - * * Given the relation id and the attribute number, * return the "attname" field from the attribute relation. * */ char * get_attname(Oid relid, AttrNumber attnum) { FormData_pg_attribute att_tup; if (SearchSysCacheStruct(ATTNUM, (char *) &att_tup, ObjectIdGetDatum(relid), UInt16GetDatum(attnum), 0, 0)) return pstrdup(att_tup.attname.data); else return NULL; } /* * get_attnum - * * Given the relation id and the attribute name, * return the "attnum" field from the attribute relation. * */ AttrNumber get_attnum(Oid relid, char *attname) { FormData_pg_attribute att_tup; if (SearchSysCacheStruct(ATTNAME, (char *) &att_tup, ObjectIdGetDatum(relid), PointerGetDatum(attname), 0, 0)) return att_tup.attnum; else return InvalidAttrNumber; } /* * get_atttype - * * Given the relation OID and the attribute number with the relation, * return the attribute type OID. * */ Oid get_atttype(Oid relid, AttrNumber attnum) { Form_pg_attribute att_tup = (Form_pg_attribute) palloc(sizeof(*att_tup)); if (SearchSysCacheStruct(ATTNUM, (char *) att_tup, ObjectIdGetDatum(relid), UInt16GetDatum(attnum), 0, 0)) return att_tup->atttypid; else return (Oid) NULL; } /* This routine uses the attname instead of the attnum because it * replaces the routine find_atttype, which is called sometimes when * only the attname, not the attno, is available. */ bool get_attisset(Oid relid, char *attname) { HeapTuple tuple; AttrNumber attno; Form_pg_attribute att_tup; attno = get_attnum(relid, attname); tuple = SearchSysCacheTuple(ATTNAME, ObjectIdGetDatum(relid), PointerGetDatum(attname), 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "get_attisset: no attribute %s in relation %d", attname, relid); if (heap_attisnull(tuple, attno)) return false; else { att_tup = (Form_pg_attribute) GETSTRUCT(tuple); return att_tup->attisset; } } /* * get_atttypmod - * * Given the relation id and the attribute number, * return the "atttypmod" field from the attribute relation. * */ int32 get_atttypmod(Oid relid, AttrNumber attnum) { FormData_pg_attribute att_tup; if (SearchSysCacheStruct(ATTNUM, (char *) &att_tup, ObjectIdGetDatum(relid), Int16GetDatum(attnum), 0, 0)) return att_tup.atttypmod; else return -1; } /* ---------- INDEX CACHE ---------- */ /* watch this space... */ /* ---------- OPERATOR CACHE ---------- */ /* * get_opcode - * * Returns the regproc id of the routine used to implement an * operator given the operator uid. * */ RegProcedure get_opcode(Oid opno) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0)) return optup.oprcode; else return (RegProcedure) NULL; } /* * get_opname - * returns the name of the operator with the given opno * * Note: return the struct so that it gets copied. */ char * get_opname(Oid opno) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0)) return pstrdup(optup.oprname.data); else { /* don't throw an error anymore; we want to continue... */ #if FALSE elog(ERROR, "can't look up operator %d\n", opno); #endif return NULL; } } /* * op_mergejoinable - * * Returns the left and right sort operators and types corresponding to a * mergejoinable operator, or nil if the operator is not mergejoinable. * */ bool op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0) && optup.oprlsortop && optup.oprrsortop && optup.oprleft == ltype && optup.oprright == rtype) { *leftOp = ObjectIdGetDatum(optup.oprlsortop); *rightOp = ObjectIdGetDatum(optup.oprrsortop); return TRUE; } else return FALSE; } /* * op_hashjoinable-- * * Returns the hash operator corresponding to a hashjoinable operator, * or nil if the operator is not hashjoinable. * */ Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0) && optup.oprcanhash && optup.oprleft == ltype && optup.oprright == rtype) return opno; else return InvalidOid; } /* * get_commutator - * * Returns the corresponding commutator of an operator. * */ Oid get_commutator(Oid opno) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0)) return optup.oprcom; else return (Oid) NULL; } HeapTuple get_operator_tuple(Oid opno) { HeapTuple optup; if ((optup = SearchSysCacheTuple(OPROID, ObjectIdGetDatum(opno), 0, 0, 0))) return optup; else return (HeapTuple) NULL; } /* * get_negator - * * Returns the corresponding negator of an operator. * */ Oid get_negator(Oid opno) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0)) return optup.oprnegate; else return (Oid) NULL; } /* * get_oprrest - * * Returns procedure id for computing selectivity of an operator. * */ RegProcedure get_oprrest(Oid opno) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0)) return optup.oprrest; else return (RegProcedure) NULL; } /* * get_oprjoin - * * Returns procedure id for computing selectivity of a join. * */ RegProcedure get_oprjoin(Oid opno) { FormData_pg_operator optup; if (SearchSysCacheStruct(OPROID, (char *) &optup, ObjectIdGetDatum(opno), 0, 0, 0)) return optup.oprjoin; else return (RegProcedure) NULL; } /* ---------- RELATION CACHE ---------- */ /* * get_relnatts - * * Returns the number of attributes for a given relation. * */ int get_relnatts(Oid relid) { FormData_pg_class reltup; if (SearchSysCacheStruct(RELOID, (char *) &reltup, ObjectIdGetDatum(relid), 0, 0, 0)) return reltup.relnatts; else return InvalidAttrNumber; } /* * get_rel_name - * * Returns the name of a given relation. * */ char * get_rel_name(Oid relid) { FormData_pg_class reltup; if ((SearchSysCacheStruct(RELOID, (char *) &reltup, ObjectIdGetDatum(relid), 0, 0, 0))) return pstrdup(reltup.relname.data); else return NULL; } /* ---------- TYPE CACHE ---------- */ /* * get_typlen - * * Given the type OID, return the length of the type. * */ int16 get_typlen(Oid typid) { FormData_pg_type typtup; if (SearchSysCacheStruct(TYPOID, (char *) &typtup, ObjectIdGetDatum(typid), 0, 0, 0)) return typtup.typlen; else return (int16) NULL; } /* * get_typbyval - * * Given the type OID, determine whether the type is returned by value or * not. Returns 1 if by value, 0 if by reference. * */ bool get_typbyval(Oid typid) { FormData_pg_type typtup; if (SearchSysCacheStruct(TYPOID, (char *) &typtup, ObjectIdGetDatum(typid), 0, 0, 0)) return (bool) typtup.typbyval; else return false; } /* * get_typbyval - * * Given the type OID, determine whether the type is returned by value or * not. Returns 1 if by value, 0 if by reference. * */ #ifdef NOT_USED char get_typalign(Oid typid) { FormData_pg_type typtup; if (SearchSysCacheStruct(TYPOID, (char *) &typtup, ObjectIdGetDatum(typid), 0, 0, 0)) return typtup.typalign; else return 'i'; } #endif /* * get_typdefault - * * Given the type OID, return the default value of the ADT. * */ struct varlena * get_typdefault(Oid typid) { struct varlena *typdefault = (struct varlena *) TypeDefaultRetrieve(typid); return typdefault; } /* * get_typtype - * * Given the type OID, find if it is a basic type, a named relation * or the generic type 'relation'. * It returns the null char if the cache lookup fails... * */ #ifdef NOT_USED char get_typtype(Oid typid) { FormData_pg_type typtup; if (SearchSysCacheStruct(TYPOID, (char *) &typtup, ObjectIdGetDatum(typid), 0, 0, 0)) return typtup.typtype; else return '\0'; } #endif