📄 lsyscache.c
字号:
/*------------------------------------------------------------------------- * * lsyscache.c * Convenience routines for common queries in the system catalog cache. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.129 2005/10/15 02:49:31 momjian Exp $ * * NOTES * Eventually, the index information should go through here, too. *------------------------------------------------------------------------- */#include "postgres.h"#include "miscadmin.h"#include "access/hash.h"#include "access/tupmacs.h"#include "catalog/pg_amop.h"#include "catalog/pg_amproc.h"#include "catalog/pg_namespace.h"#include "catalog/pg_opclass.h"#include "catalog/pg_operator.h"#include "catalog/pg_proc.h"#include "catalog/pg_statistic.h"#include "catalog/pg_type.h"#include "nodes/makefuncs.h"#include "utils/array.h"#include "utils/builtins.h"#include "utils/catcache.h"#include "utils/datum.h"#include "utils/lsyscache.h"#include "utils/syscache.h"/* ---------- AMOP CACHES ---------- *//* * op_in_opclass * * Return t iff operator 'opno' is in operator class 'opclass'. */boolop_in_opclass(Oid opno, Oid opclass){ return SearchSysCacheExists(AMOPOPID, ObjectIdGetDatum(opno), ObjectIdGetDatum(opclass), 0, 0);}/* * get_op_opclass_strategy * * Get the operator's strategy number within the specified opclass, * or 0 if it's not a member of the opclass. */intget_op_opclass_strategy(Oid opno, Oid opclass){ HeapTuple tp; Form_pg_amop amop_tup; int result; tp = SearchSysCache(AMOPOPID, ObjectIdGetDatum(opno), ObjectIdGetDatum(opclass), 0, 0); if (!HeapTupleIsValid(tp)) return 0; amop_tup = (Form_pg_amop) GETSTRUCT(tp); result = amop_tup->amopstrategy; ReleaseSysCache(tp); return result;}/* * get_op_opclass_properties * * Get the operator's strategy number, subtype, and recheck (lossy) flag * within the specified opclass. * * Caller should already have verified that opno is a member of opclass, * therefore we raise an error if the tuple is not found. */voidget_op_opclass_properties(Oid opno, Oid opclass, int *strategy, Oid *subtype, bool *recheck){ HeapTuple tp; Form_pg_amop amop_tup; tp = SearchSysCache(AMOPOPID, ObjectIdGetDatum(opno), ObjectIdGetDatum(opclass), 0, 0); if (!HeapTupleIsValid(tp)) elog(ERROR, "operator %u is not a member of opclass %u", opno, opclass); amop_tup = (Form_pg_amop) GETSTRUCT(tp); *strategy = amop_tup->amopstrategy; *subtype = amop_tup->amopsubtype; *recheck = amop_tup->amopreqcheck; ReleaseSysCache(tp);}/* * get_opclass_member * Get the OID of the operator that implements the specified strategy * with the specified subtype for the specified opclass. * * Returns InvalidOid if there is no pg_amop entry for the given keys. */Oidget_opclass_member(Oid opclass, Oid subtype, int16 strategy){ HeapTuple tp; Form_pg_amop amop_tup; Oid result; tp = SearchSysCache(AMOPSTRATEGY, ObjectIdGetDatum(opclass), ObjectIdGetDatum(subtype), Int16GetDatum(strategy), 0); if (!HeapTupleIsValid(tp)) return InvalidOid; amop_tup = (Form_pg_amop) GETSTRUCT(tp); result = amop_tup->amopopr; ReleaseSysCache(tp); return result;}/* * 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.) */Oidget_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;}/* ---------- AMPROC CACHES ---------- *//* * get_opclass_proc * Get the OID of the specified support function * for the specified opclass and subtype. * * Returns InvalidOid if there is no pg_amproc entry for the given keys. */Oidget_opclass_proc(Oid opclass, Oid subtype, int16 procnum){ HeapTuple tp; Form_pg_amproc amproc_tup; RegProcedure result; tp = SearchSysCache(AMPROCNUM, ObjectIdGetDatum(opclass), ObjectIdGetDatum(subtype), Int16GetDatum(procnum), 0); if (!HeapTupleIsValid(tp)) return InvalidOid; amproc_tup = (Form_pg_amproc) GETSTRUCT(tp); result = amproc_tup->amproc; ReleaseSysCache(tp); return result;}/* ---------- ATTRIBUTE CACHES ---------- *//* * get_attname * Given the relation id and the attribute number, * return the "attname" field from the attribute relation. * * Note: returns a palloc'd copy of the string, or NULL if no such attribute. */char *get_attname(Oid relid, AttrNumber attnum){ HeapTuple tp; tp = SearchSysCache(ATTNUM, ObjectIdGetDatum(relid), Int16GetDatum(attnum), 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); char *result; result = pstrdup(NameStr(att_tup->attname)); ReleaseSysCache(tp); return result; } else return NULL;}/* * get_relid_attribute_name * * Same as above routine get_attname(), except that error * is handled by elog() instead of returning NULL. */char *get_relid_attribute_name(Oid relid, AttrNumber attnum){ char *attname; attname = get_attname(relid, attnum); if (attname == NULL) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, relid); return attname;}/* * get_attnum * * Given the relation id and the attribute name, * return the "attnum" field from the attribute relation. * * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped). */AttrNumberget_attnum(Oid relid, const char *attname){ HeapTuple tp; tp = SearchSysCacheAttName(relid, attname); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); AttrNumber result; result = att_tup->attnum; ReleaseSysCache(tp); return result; } else return InvalidAttrNumber;}/* * get_atttype * * Given the relation OID and the attribute number with the relation, * return the attribute type OID. */Oidget_atttype(Oid relid, AttrNumber attnum){ HeapTuple tp; tp = SearchSysCache(ATTNUM, ObjectIdGetDatum(relid), Int16GetDatum(attnum), 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); Oid result; result = att_tup->atttypid; ReleaseSysCache(tp); return result; } else return InvalidOid;}/* * get_atttypmod * * Given the relation id and the attribute number, * return the "atttypmod" field from the attribute relation. */int32get_atttypmod(Oid relid, AttrNumber attnum){ HeapTuple tp; tp = SearchSysCache(ATTNUM, ObjectIdGetDatum(relid), Int16GetDatum(attnum), 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); int32 result; result = att_tup->atttypmod; ReleaseSysCache(tp); return result; } else return -1;}/* * get_atttypetypmod * * A two-fer: given the relation id and the attribute number, * fetch both type OID and atttypmod in a single cache lookup. * * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine * raises an error if it can't obtain the information. */voidget_atttypetypmod(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod){ HeapTuple tp; Form_pg_attribute att_tup; tp = SearchSysCache(ATTNUM, ObjectIdGetDatum(relid), Int16GetDatum(attnum), 0, 0); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, relid); att_tup = (Form_pg_attribute) GETSTRUCT(tp); *typid = att_tup->atttypid; *typmod = att_tup->atttypmod; ReleaseSysCache(tp);}/* ---------- INDEX CACHE ---------- *//* watch this space... *//* ---------- OPCLASS CACHE ---------- *//* * opclass_is_btree * * Returns TRUE iff the specified opclass is associated with the * btree index access method. */boolopclass_is_btree(Oid opclass){ HeapTuple tp; Form_pg_opclass cla_tup; bool result; tp = SearchSysCache(CLAOID, ObjectIdGetDatum(opclass), 0, 0, 0); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for opclass %u", opclass); cla_tup = (Form_pg_opclass) GETSTRUCT(tp); result = (cla_tup->opcamid == BTREE_AM_OID); ReleaseSysCache(tp); return result;}/* * opclass_is_hash * * Returns TRUE iff the specified opclass is associated with the * hash index access method. */boolopclass_is_hash(Oid opclass){ HeapTuple tp; Form_pg_opclass cla_tup; bool result; tp = SearchSysCache(CLAOID, ObjectIdGetDatum(opclass), 0, 0, 0); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for opclass %u", opclass); cla_tup = (Form_pg_opclass) GETSTRUCT(tp); result = (cla_tup->opcamid == HASH_AM_OID); ReleaseSysCache(tp); return result;}/* ---------- OPERATOR CACHE ---------- *//* * get_opcode * * Returns the regproc id of the routine used to implement an * operator given the operator oid. */RegProcedureget_opcode(Oid opno){ HeapTuple tp; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); RegProcedure result; result = optup->oprcode; ReleaseSysCache(tp); return result; } else return (RegProcedure) InvalidOid;}/* * get_opname * returns the name of the operator with the given opno * * Note: returns a palloc'd copy of the string, or NULL if no such operator. */char *get_opname(Oid opno){ HeapTuple tp; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); char *result; result = pstrdup(NameStr(optup->oprname)); ReleaseSysCache(tp); return result; } else return NULL;}/* * op_input_types * * Returns the left and right input datatypes for an operator * (InvalidOid if not relevant). */voidop_input_types(Oid opno, Oid *lefttype, Oid *righttype){ HeapTuple tp; Form_pg_operator optup; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (!HeapTupleIsValid(tp)) /* shouldn't happen */ elog(ERROR, "cache lookup failed for operator %u", opno); optup = (Form_pg_operator) GETSTRUCT(tp); *lefttype = optup->oprleft; *righttype = optup->oprright; ReleaseSysCache(tp);}/* * op_mergejoinable * * Returns the left and right sort operators corresponding to a * mergejoinable operator, or false if the operator is not mergejoinable. */boolop_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp){ HeapTuple tp; bool result = false; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); if (optup->oprlsortop && optup->oprrsortop) { *leftOp = optup->oprlsortop; *rightOp = optup->oprrsortop; result = true; } ReleaseSysCache(tp); } return result;}/* * op_mergejoin_crossops * * Returns the cross-type comparison operators (ltype "<" rtype and * ltype ">" rtype) for an operator previously determined to be * mergejoinable. Optionally, fetches the regproc ids of these * operators, as well as their operator OIDs. */voidop_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop, RegProcedure *ltproc, RegProcedure *gtproc){ HeapTuple tp; Form_pg_operator optup; /* * Get the declared comparison operators of the operator. */ tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (!HeapTupleIsValid(tp)) /* shouldn't happen */ elog(ERROR, "cache lookup failed for operator %u", opno); optup = (Form_pg_operator) GETSTRUCT(tp); *ltop = optup->oprltcmpop; *gtop = optup->oprgtcmpop; ReleaseSysCache(tp); /* Check < op provided */ if (!OidIsValid(*ltop)) elog(ERROR, "mergejoin operator %u has no matching < operator", opno); if (ltproc) *ltproc = get_opcode(*ltop); /* Check > op provided */ if (!OidIsValid(*gtop)) elog(ERROR, "mergejoin operator %u has no matching > operator", opno); if (gtproc) *gtproc = get_opcode(*gtop);}/* * op_hashjoinable * * Returns true if the operator is hashjoinable. */boolop_hashjoinable(Oid opno){ HeapTuple tp; bool result = false; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); result = optup->oprcanhash; ReleaseSysCache(tp); } return result;}/* * op_strict * * Get the proisstrict flag for the operator's underlying function. */boolop_strict(Oid opno){ RegProcedure funcid = get_opcode(opno); if (funcid == (RegProcedure) InvalidOid) elog(ERROR, "operator %u does not exist", opno); return func_strict((Oid) funcid);}/* * op_volatile * * Get the provolatile flag for the operator's underlying function. */charop_volatile(Oid opno){ RegProcedure funcid = get_opcode(opno); if (funcid == (RegProcedure) InvalidOid) elog(ERROR, "operator %u does not exist", opno); return func_volatile((Oid) funcid);}/* * get_commutator * * Returns the corresponding commutator of an operator. */Oidget_commutator(Oid opno){ HeapTuple tp; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); Oid result; result = optup->oprcom; ReleaseSysCache(tp); return result; } else return InvalidOid;}/* * get_negator * * Returns the corresponding negator of an operator. */Oidget_negator(Oid opno){ HeapTuple tp; tp = SearchSysCache(OPEROID, ObjectIdGetDatum(opno), 0, 0, 0); if (HeapTupleIsValid(tp))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -