diff options
Diffstat (limited to 'src/backend/utils/cache/lsyscache.c')
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 1389 |
1 files changed, 0 insertions, 1389 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c deleted file mode 100644 index 233910a85c3..00000000000 --- a/src/backend/utils/cache/lsyscache.c +++ /dev/null @@ -1,1389 +0,0 @@ -/*------------------------------------------------------------------------- - * - * lsyscache.c - * Convenience routines for common queries in the system catalog cache. - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.74 2002/06/20 20:29:39 momjian Exp $ - * - * NOTES - * Eventually, the index information should go through here, too. - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "access/tupmacs.h" -#include "catalog/pg_amop.h" -#include "catalog/pg_namespace.h" -#include "catalog/pg_opclass.h" -#include "catalog/pg_operator.h" -#include "catalog/pg_proc.h" -#include "catalog/pg_shadow.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/lsyscache.h" -#include "utils/syscache.h" - - -/* ---------- AMOP CACHES ---------- */ - -/* - * op_in_opclass - * - * Return t iff operator 'opno' is in operator class 'opclass'. - */ -bool -op_in_opclass(Oid opno, Oid opclass) -{ - return SearchSysCacheExists(AMOPOPID, - ObjectIdGetDatum(opclass), - ObjectIdGetDatum(opno), - 0, 0); -} - -/* - * op_requires_recheck - * - * Return t if operator 'opno' requires a recheck when used as a - * member of opclass 'opclass' (ie, this opclass is lossy for this - * operator). - * - * Caller should already have verified that opno is a member of opclass, - * therefore we raise an error if the tuple is not found. - */ -bool -op_requires_recheck(Oid opno, Oid opclass) -{ - HeapTuple tp; - Form_pg_amop amop_tup; - bool result; - - tp = SearchSysCache(AMOPOPID, - ObjectIdGetDatum(opclass), - ObjectIdGetDatum(opno), - 0, 0); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u", - opno, opclass); - amop_tup = (Form_pg_amop) GETSTRUCT(tp); - - result = amop_tup->amopreqcheck; - 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 operator. - */ -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_attnum - * - * Given the relation id and the attribute name, - * return the "attnum" field from the attribute relation. - */ -AttrNumber -get_attnum(Oid relid, char *attname) -{ - HeapTuple tp; - - tp = SearchSysCache(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0, 0); - 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. - */ -Oid -get_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; -} - -/* 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 tp; - - tp = SearchSysCache(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); - bool result; - - result = att_tup->attisset; - ReleaseSysCache(tp); - return result; - } - else - return false; -} - -/* - * 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) -{ - 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. - */ -void -get_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 relation %u attribute %d", - relid, attnum); - 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. - */ -bool -opclass_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; -} - -/* ---------- OPERATOR CACHE ---------- */ - -/* - * get_opcode - * - * Returns the regproc id of the routine used to implement an - * operator given the operator oid. - */ -RegProcedure -get_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_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) -{ - 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 && - optup->oprleft == ltype && - optup->oprright == rtype) - { - *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. - */ -void -op_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, "op_mergejoin_crossops: operator %u not found", opno); - optup = (Form_pg_operator) GETSTRUCT(tp); - *ltop = optup->oprltcmpop; - *gtop = optup->oprgtcmpop; - ReleaseSysCache(tp); - - /* Check < op provided */ - if (!OidIsValid(*ltop)) - elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator", - opno); - if (ltproc) - *ltproc = get_opcode(*ltop); - - /* Check > op provided */ - if (!OidIsValid(*gtop)) - elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator", - opno); - if (gtproc) - *gtproc = get_opcode(*gtop); -} - -/* - * op_hashjoinable - * - * Returns the hash operator corresponding to a hashjoinable operator, - * or InvalidOid if the operator is not hashjoinable. - */ -Oid -op_hashjoinable(Oid opno, Oid ltype, Oid rtype) -{ - HeapTuple tp; - Oid result = InvalidOid; - - tp = SearchSysCache(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); - - if (optup->oprcanhash && - optup->oprleft == ltype && - optup->oprright == rtype) - result = opno; - ReleaseSysCache(tp); - } - return result; -} - -/* - * op_volatile - * - * Get the provolatile flag for the operator's underlying function. - */ -char -op_volatile(Oid opno) -{ - RegProcedure funcid = get_opcode(opno); - - if (funcid == (RegProcedure) InvalidOid) - elog(ERROR, "Operator OID %u does not exist", opno); - - return func_volatile((Oid) funcid); -} - -/* - * get_commutator - * - * Returns the corresponding commutator of an operator. - */ -Oid -get_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. - */ -Oid -get_negator(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->oprnegate; - ReleaseSysCache(tp); - return result; - } - else - return InvalidOid; -} - -/* - * get_oprrest - * - * Returns procedure id for computing selectivity of an operator. - */ -RegProcedure -get_oprrest(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->oprrest; - ReleaseSysCache(tp); - return result; - } - else - return (RegProcedure) InvalidOid; -} - -/* - * get_oprjoin - * - * Returns procedure id for computing selectivity of a join. - */ -RegProcedure -get_oprjoin(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->oprjoin; - ReleaseSysCache(tp); - return result; - } - else - return (RegProcedure) InvalidOid; -} - -/* ---------- FUNCTION CACHE ---------- */ - -/* - * get_func_name - * returns the name of the function with the given funcid - * - * Note: returns a palloc'd copy of the string, or NULL if no such function. - */ -char * -get_func_name(Oid funcid) -{ - HeapTuple tp; - - tp = SearchSysCache(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp); - char *result; - - result = pstrdup(NameStr(functup->proname)); - ReleaseSysCache(tp); - return result; - } - else - return NULL; -} - -/* - * get_func_rettype - * Given procedure id, return the function's result type. - */ -Oid -get_func_rettype(Oid funcid) -{ - HeapTuple tp; - Oid result; - - tp = SearchSysCache(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "Function OID %u does not exist", funcid); - - result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype; - ReleaseSysCache(tp); - return result; -} - -/* - * get_func_retset - * Given procedure id, return the function's proretset flag. - */ -bool -get_func_retset(Oid funcid) -{ - HeapTuple tp; - bool result; - - tp = SearchSysCache(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "Function OID %u does not exist", funcid); - - result = ((Form_pg_proc) GETSTRUCT(tp))->proretset; - ReleaseSysCache(tp); - return result; -} - -/* - * func_volatile - * Given procedure id, return the function's provolatile flag. - */ -char -func_volatile(Oid funcid) -{ - HeapTuple tp; - char result; - - tp = SearchSysCache(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "Function OID %u does not exist", funcid); - - result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile; - ReleaseSysCache(tp); - return result; -} - -/* ---------- RELATION CACHE ---------- */ - -/* - * get_relname_relid - * Given name and namespace of a relation, look up the OID. - * - * Returns InvalidOid if there is no such relation. - */ -Oid -get_relname_relid(const char *relname, Oid relnamespace) -{ - return GetSysCacheOid(RELNAMENSP, - PointerGetDatum(relname), - ObjectIdGetDatum(relnamespace), - 0, 0); -} - -#ifdef NOT_USED -/* - * get_relnatts - * - * Returns the number of attributes for a given relation. - */ -int -get_relnatts(Oid relid) -{ - HeapTuple tp; - - tp = SearchSysCache(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); - int result; - - result = reltup->relnatts; - ReleaseSysCache(tp); - return result; - } - else - return InvalidAttrNumber; -} -#endif - -/* - * get_rel_name - * Returns the name of a given relation. - * - * Returns a palloc'd copy of the string, or NULL if no such relation. - * - * NOTE: since relation name is not unique, be wary of code that uses this - * for anything except preparing error messages. - */ -char * -get_rel_name(Oid relid) -{ - HeapTuple tp; - - tp = SearchSysCache(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); - char *result; - - result = pstrdup(NameStr(reltup->relname)); - ReleaseSysCache(tp); - return result; - } - else - return NULL; -} - -/* - * get_rel_namespace - * - * Returns the pg_namespace OID associated with a given relation. - */ -Oid -get_rel_namespace(Oid relid) -{ - HeapTuple tp; - - tp = SearchSysCache(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); - Oid result; - - result = reltup->relnamespace; - ReleaseSysCache(tp); - return result; - } - else - return InvalidOid; -} - -/* - * get_rel_type_id - * - * Returns the pg_type OID associated with a given relation. - * - * Note: not all pg_class entries have associated pg_type OIDs; so be - * careful to check for InvalidOid result. - */ -Oid -get_rel_type_id(Oid relid) -{ - HeapTuple tp; - - tp = SearchSysCache(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); - Oid result; - - result = reltup->reltype; - ReleaseSysCache(tp); - return result; - } - else - return InvalidOid; -} - -/* ---------- TYPE CACHE ---------- */ - -/* - * get_typisdefined - * - * Given the type OID, determine whether the type is defined - * (if not, it's only a shell). - */ -bool -get_typisdefined(Oid typid) -{ - HeapTuple tp; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - bool result; - - result = typtup->typisdefined; - ReleaseSysCache(tp); - return result; - } - else - return false; -} - -/* - * get_typlen - * - * Given the type OID, return the length of the type. - */ -int16 -get_typlen(Oid typid) -{ - HeapTuple tp; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - int16 result; - - result = typtup->typlen; - ReleaseSysCache(tp); - return result; - } - else - return 0; -} - -/* - * get_typbyval - * - * Given the type OID, determine whether the type is returned by value or - * not. Returns true if by value, false if by reference. - */ -bool -get_typbyval(Oid typid) -{ - HeapTuple tp; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - bool result; - - result = typtup->typbyval; - ReleaseSysCache(tp); - return result; - } - else - return false; -} - -/* - * get_typlenbyval - * - * A two-fer: given the type OID, return both typlen and typbyval. - * - * Since both pieces of info are needed to know how to copy a Datum, - * many places need both. Might as well get them with one cache lookup - * instead of two. Also, this routine raises an error instead of - * returning a bogus value when given a bad type OID. - */ -void -get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval) -{ - HeapTuple tp; - Form_pg_type typtup; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "cache lookup failed for type %u", typid); - typtup = (Form_pg_type) GETSTRUCT(tp); - *typlen = typtup->typlen; - *typbyval = typtup->typbyval; - ReleaseSysCache(tp); -} - -#ifdef NOT_USED -char -get_typalign(Oid typid) -{ - HeapTuple tp; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - char result; - - result = typtup->typalign; - ReleaseSysCache(tp); - return result; - } - else - return 'i'; -} -#endif - -char -get_typstorage(Oid typid) -{ - HeapTuple tp; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - char result; - - result = typtup->typstorage; - ReleaseSysCache(tp); - return result; - } - else - return 'p'; -} - -/* - * get_typdefault - * Given a type OID, return the type's default value, if any. - * - * The result is a palloc'd expression node tree, or NULL if there - * is no defined default for the datatype. - * - * NB: caller should be prepared to coerce result to correct datatype; - * the returned expression tree might produce something of the wrong type. - */ -Node * -get_typdefault(Oid typid) -{ - HeapTuple typeTuple; - Form_pg_type type; - Datum datum; - bool isNull; - Node *expr; - - typeTuple = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (!HeapTupleIsValid(typeTuple)) - elog(ERROR, "get_typdefault: failed to lookup type %u", typid); - type = (Form_pg_type) GETSTRUCT(typeTuple); - - /* - * typdefault and typdefaultbin are potentially null, so don't try to - * access 'em as struct fields. Must do it the hard way with - * SysCacheGetAttr. - */ - datum = SysCacheGetAttr(TYPEOID, - typeTuple, - Anum_pg_type_typdefaultbin, - &isNull); - - if (!isNull) - { - /* We have an expression default */ - expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout, - datum))); - } - else - { - /* Perhaps we have a plain literal default */ - datum = SysCacheGetAttr(TYPEOID, - typeTuple, - Anum_pg_type_typdefault, - &isNull); - - if (!isNull) - { - char *strDefaultVal; - - /* Convert text datum to C string */ - strDefaultVal = DatumGetCString(DirectFunctionCall1(textout, - datum)); - /* Convert C string to a value of the given type */ - datum = OidFunctionCall3(type->typinput, - CStringGetDatum(strDefaultVal), - ObjectIdGetDatum(type->typelem), - Int32GetDatum(-1)); - /* Build a Const node containing the value */ - expr = (Node *) makeConst(typid, - type->typlen, - datum, - false, - type->typbyval, - false, /* not a set */ - false); - pfree(strDefaultVal); - } - else - { - /* No default */ - expr = NULL; - } - } - - ReleaseSysCache(typeTuple); - - return expr; -} - -/* - * getBaseType - * If the given type is a domain, return its base type; - * otherwise return the type's own OID. - */ -Oid -getBaseType(Oid typid) -{ - /* - * We loop to find the bottom base type in a stack of domains. - */ - for (;;) - { - HeapTuple tup; - Form_pg_type typTup; - - tup = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "getBaseType: failed to lookup type %u", typid); - typTup = (Form_pg_type) GETSTRUCT(tup); - if (typTup->typtype != 'd') - { - /* Not a domain, so done */ - ReleaseSysCache(tup); - break; - } - - typid = typTup->typbasetype; - ReleaseSysCache(tup); - } - - return typid; -} - -/* - * get_typavgwidth - * - * Given a type OID and a typmod value (pass -1 if typmod is unknown), - * estimate the average width of values of the type. This is used by - * the planner, which doesn't require absolutely correct results; - * it's OK (and expected) to guess if we don't know for sure. - */ -int32 -get_typavgwidth(Oid typid, int32 typmod) -{ - int typlen = get_typlen(typid); - int32 maxwidth; - - /* - * Easy if it's a fixed-width type - */ - if (typlen > 0) - return typlen; - - /* - * type_maximum_size knows the encoding of typmod for some datatypes; - * don't duplicate that knowledge here. - */ - maxwidth = type_maximum_size(typid, typmod); - if (maxwidth > 0) - { - /* - * For BPCHAR, the max width is also the only width. Otherwise we - * need to guess about the typical data width given the max. A - * sliding scale for percentage of max width seems reasonable. - */ - if (typid == BPCHAROID) - return maxwidth; - if (maxwidth <= 32) - return maxwidth; /* assume full width */ - if (maxwidth < 1000) - return 32 + (maxwidth - 32) / 2; /* assume 50% */ - - /* - * Beyond 1000, assume we're looking at something like - * "varchar(10000)" where the limit isn't actually reached often, - * and use a fixed estimate. - */ - return 32 + (1000 - 32) / 2; - } - - /* - * Ooops, we have no idea ... wild guess time. - */ - return 32; -} - -/* - * 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) -{ - HeapTuple tp; - - tp = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - char result; - - result = typtup->typtype; - ReleaseSysCache(tp); - return result; - } - else - return '\0'; -} -#endif - -/* ---------- STATISTICS CACHE ---------- */ - -/* - * get_attavgwidth - * - * Given the table and attribute number of a column, get the average - * width of entries in the column. Return zero if no data available. - */ -int32 -get_attavgwidth(Oid relid, AttrNumber attnum) -{ - HeapTuple tp; - - tp = SearchSysCache(STATRELATT, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0, 0); - if (HeapTupleIsValid(tp)) - { - int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth; - - ReleaseSysCache(tp); - if (stawidth > 0) - return stawidth; - } - return 0; -} - -/* - * get_attstatsslot - * - * Extract the contents of a "slot" of a pg_statistic tuple. - * Returns TRUE if requested slot type was found, else FALSE. - * - * Unlike other routines in this file, this takes a pointer to an - * already-looked-up tuple in the pg_statistic cache. We do this since - * most callers will want to extract more than one value from the cache - * entry, and we don't want to repeat the cache lookup unnecessarily. - * - * statstuple: pg_statistics tuple to be examined. - * atttype: type OID of attribute. - * atttypmod: typmod of attribute. - * reqkind: STAKIND code for desired statistics slot kind. - * reqop: STAOP value wanted, or InvalidOid if don't care. - * values, nvalues: if not NULL, the slot's stavalues are extracted. - * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted. - * - * If assigned, values and numbers are set to point to palloc'd arrays. - * If the attribute type is pass-by-reference, the values referenced by - * the values array are themselves palloc'd. The palloc'd stuff can be - * freed by calling free_attstatsslot. - */ -bool -get_attstatsslot(HeapTuple statstuple, - Oid atttype, int32 atttypmod, - int reqkind, Oid reqop, - Datum **values, int *nvalues, - float4 **numbers, int *nnumbers) -{ - Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple); - int i, - j; - Datum val; - bool isnull; - ArrayType *statarray; - int narrayelem; - HeapTuple typeTuple; - FmgrInfo inputproc; - Oid typelem; - - for (i = 0; i < STATISTIC_NUM_SLOTS; i++) - { - if ((&stats->stakind1)[i] == reqkind && - (reqop == InvalidOid || (&stats->staop1)[i] == reqop)) - break; - } - if (i >= STATISTIC_NUM_SLOTS) - return false; /* not there */ - - if (values) - { - val = SysCacheGetAttr(STATRELATT, statstuple, - Anum_pg_statistic_stavalues1 + i, - &isnull); - if (isnull) - elog(ERROR, "get_attstatsslot: stavalues is null"); - statarray = DatumGetArrayTypeP(val); - - /* - * Do initial examination of the array. This produces a list of - * text Datums --- ie, pointers into the text array value. - */ - deconstruct_array(statarray, false, -1, 'i', values, nvalues); - narrayelem = *nvalues; - - /* - * We now need to replace each text Datum by its internal - * equivalent. - * - * Get the type input proc and typelem for the column datatype. - */ - typeTuple = SearchSysCache(TYPEOID, - ObjectIdGetDatum(atttype), - 0, 0, 0); - if (!HeapTupleIsValid(typeTuple)) - elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u", - atttype); - fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc); - typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem; - ReleaseSysCache(typeTuple); - - /* - * Do the conversions. The palloc'd array of Datums is reused in - * place. - */ - for (j = 0; j < narrayelem; j++) - { - char *strval; - - strval = DatumGetCString(DirectFunctionCall1(textout, - (*values)[j])); - (*values)[j] = FunctionCall3(&inputproc, - CStringGetDatum(strval), - ObjectIdGetDatum(typelem), - Int32GetDatum(atttypmod)); - pfree(strval); - } - - /* - * Free statarray if it's a detoasted copy. - */ - if ((Pointer) statarray != DatumGetPointer(val)) - pfree(statarray); - } - - if (numbers) - { - val = SysCacheGetAttr(STATRELATT, statstuple, - Anum_pg_statistic_stanumbers1 + i, - &isnull); - if (isnull) - elog(ERROR, "get_attstatsslot: stanumbers is null"); - statarray = DatumGetArrayTypeP(val); - - /* - * We expect the array to be a 1-D float4 array; verify that. We - * don't need to use deconstruct_array() since the array data is - * just going to look like a C array of float4 values. - */ - narrayelem = ARR_DIMS(statarray)[0]; - if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 || - ARR_SIZE(statarray) != (ARR_OVERHEAD(1) + narrayelem * sizeof(float4))) - elog(ERROR, "get_attstatsslot: stanumbers is bogus"); - *numbers = (float4 *) palloc(narrayelem * sizeof(float4)); - memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4)); - *nnumbers = narrayelem; - - /* - * Free statarray if it's a detoasted copy. - */ - if ((Pointer) statarray != DatumGetPointer(val)) - pfree(statarray); - } - - return true; -} - -void -free_attstatsslot(Oid atttype, - Datum *values, int nvalues, - float4 *numbers, int nnumbers) -{ - if (values) - { - if (!get_typbyval(atttype)) - { - int i; - - for (i = 0; i < nvalues; i++) - pfree(DatumGetPointer(values[i])); - } - pfree(values); - } - if (numbers) - pfree(numbers); -} - -/* ---------- PG_NAMESPACE CACHE ---------- */ - -/* - * get_namespace_name - * Returns the name of a given namespace - * - * Returns a palloc'd copy of the string, or NULL if no such namespace. - */ -char * -get_namespace_name(Oid nspid) -{ - HeapTuple tp; - - tp = SearchSysCache(NAMESPACEOID, - ObjectIdGetDatum(nspid), - 0, 0, 0); - if (HeapTupleIsValid(tp)) - { - Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp); - char *result; - - result = pstrdup(NameStr(nsptup->nspname)); - ReleaseSysCache(tp); - return result; - } - else - return NULL; -} - -/* ---------- PG_SHADOW CACHE ---------- */ - -/* - * get_usesysid - * - * Given a user name, look up the user's sysid. - * Raises an error if no such user (rather than returning zero, - * which might possibly be a valid usesysid). - * - * Note: the type of usesysid is currently int4, but may change to Oid - * someday. It'd be reasonable to return zero on failure if we were - * using Oid ... - */ -int32 -get_usesysid(const char *username) -{ - int32 result; - HeapTuple userTup; - - userTup = SearchSysCache(SHADOWNAME, - PointerGetDatum(username), - 0, 0, 0); - if (!HeapTupleIsValid(userTup)) - elog(ERROR, "user \"%s\" does not exist", username); - - result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid; - - ReleaseSysCache(userTup); - - return result; -} |