📄 lsyscache.c
字号:
{ 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, "cache lookup failed for 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(getTypeIOParam(typeTuple)), Int32GetDatum(-1)); /* Build a Const node containing the value */ expr = (Node *) makeConst(typid, type->typlen, datum, false, type->typbyval); 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. */OidgetBaseType(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, "cache lookup failed for 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. */int32get_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 complex type, etc. * It returns the null char if the cache lookup fails... */charget_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';}/* * get_typ_typrelid * * Given the type OID, get the typrelid (InvalidOid if not a complex * type). */Oidget_typ_typrelid(Oid typid){ HeapTuple tp; tp = SearchSysCache(TYPEOID, ObjectIdGetDatum(typid), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); Oid result; result = typtup->typrelid; ReleaseSysCache(tp); return result; } else return InvalidOid;}/* * get_element_type * * Given the type OID, get the typelem (InvalidOid if not an array type). * * NB: this only considers varlena arrays to be true arrays; InvalidOid is * returned if the input is a fixed-length array type. */Oidget_element_type(Oid typid){ HeapTuple tp; tp = SearchSysCache(TYPEOID, ObjectIdGetDatum(typid), 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); Oid result; if (typtup->typlen == -1) result = typtup->typelem; else result = InvalidOid; ReleaseSysCache(tp); return result; } else return InvalidOid;}/* * get_array_type * * Given the type OID, get the corresponding array type. * Returns InvalidOid if no array type can be found. * * NB: this only considers varlena arrays to be true arrays. */Oidget_array_type(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 *array_typename; Oid namespaceId; array_typename = makeArrayTypeName(NameStr(typtup->typname)); namespaceId = typtup->typnamespace; ReleaseSysCache(tp); tp = SearchSysCache(TYPENAMENSP, PointerGetDatum(array_typename), ObjectIdGetDatum(namespaceId), 0, 0); pfree(array_typename); if (HeapTupleIsValid(tp)) { Oid result; typtup = (Form_pg_type) GETSTRUCT(tp); if (typtup->typlen == -1 && typtup->typelem == typid) result = HeapTupleGetOid(tp); else result = InvalidOid; ReleaseSysCache(tp); return result; } } return InvalidOid;}/* * getTypeInputInfo * * Get info needed for converting values of a type to internal form */voidgetTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam){ HeapTuple typeTuple; Form_pg_type pt; typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", type); pt = (Form_pg_type) GETSTRUCT(typeTuple); if (!pt->typisdefined) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type %s is only a shell", format_type_be(type)))); if (!OidIsValid(pt->typinput)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("no input function available for type %s", format_type_be(type)))); *typInput = pt->typinput; *typIOParam = getTypeIOParam(typeTuple); ReleaseSysCache(typeTuple);}/* * getTypeOutputInfo * * Get info needed for printing values of a type */voidgetTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena){ HeapTuple typeTuple; Form_pg_type pt; typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", type); pt = (Form_pg_type) GETSTRUCT(typeTuple); if (!pt->typisdefined) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type %s is only a shell", format_type_be(type)))); if (!OidIsValid(pt->typoutput)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("no output function available for type %s", format_type_be(type)))); *typOutput = pt->typoutput; *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1); ReleaseSysCache(typeTuple);}/* * getTypeBinaryInputInfo * * Get info needed for binary input of values of a type */voidgetTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam){ HeapTuple typeTuple; Form_pg_type pt; typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", type); pt = (Form_pg_type) GETSTRUCT(typeTuple); if (!pt->typisdefined) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type %s is only a shell", format_type_be(type)))); if (!OidIsValid(pt->typreceive)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("no binary input function available for type %s", format_type_be(type)))); *typReceive = pt->typreceive; *typIOParam = getTypeIOParam(typeTuple); ReleaseSysCache(typeTuple);}/* * getTypeBinaryOutputInfo * * Get info needed for binary output of values of a type */voidgetTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena){ HeapTuple typeTuple; Form_pg_type pt; typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", type); pt = (Form_pg_type) GETSTRUCT(typeTuple); if (!pt->typisdefined) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type %s is only a shell", format_type_be(type)))); if (!OidIsValid(pt->typsend)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("no binary output function available for type %s", format_type_be(type)))); *typSend = pt->typsend; *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1); ReleaseSysCache(typeTuple);}/* ---------- 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. */int32get_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 (can be InvalidOid if values == NULL). * atttypmod: typmod of attribute (can be 0 if values == NULL). * 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. */boolget_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; Form_pg_type typeForm; 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, "stavalues is null"); statarray = DatumGetArrayTypeP(val); /* Need to get info about the array element type */ typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(atttype), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", atttype); typeForm = (Form_pg_type) GETSTRUCT(typeTuple); /* Deconstruct array into Datum elements */ deconstruct_array(statarray, atttype, typeForm->typlen, typeForm->typbyval, typeForm->typalign, values, nvalues); /* * If the element type is pass-by-reference, we now have a bunch of * Datums that are pointers into the syscache value. Copy them to * avoid problems if syscache decides to drop the entry. */ if (!typeForm->typbyval) { for (j = 0; j < *nvalues; j++) { (*values)[j] = datumCopy((*values)[j], typeForm->typbyval, typeForm->typlen); } } ReleaseSysCache(typeTuple); /* * 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, "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_ELEMTYPE(statarray) != FLOAT4OID) elog(ERROR, "stanumbers is not a 1-D float4 array"); *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;}/* * free_attstatsslot * Free data allocated by get_attstatsslot * * atttype need be valid only if values != NULL. */voidfree_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_AUTHID CACHE ---------- *//* * get_roleid * Given a role name, look up the role's OID. * Returns InvalidOid if no such role. */Oidget_roleid(const char *rolname){ return GetSysCacheOid(AUTHNAME, PointerGetDatum(rolname), 0, 0, 0);}/* * get_roleid_checked * Given a role name, look up the role's OID. * ereports if no such role. */Oidget_roleid_checked(const char *rolname){ Oid roleid; roleid = get_roleid(rolname); if (!OidIsValid(roleid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("role \"%s\" does not exist", rolname))); return roleid;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -