1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.65 2002/03/22 02:56:35 tgl Exp $
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
18 #include "access/tupmacs.h"
19 #include "catalog/pg_amop.h"
20 #include "catalog/pg_opclass.h"
21 #include "catalog/pg_operator.h"
22 #include "catalog/pg_proc.h"
23 #include "catalog/pg_shadow.h"
24 #include "catalog/pg_statistic.h"
25 #include "catalog/pg_type.h"
26 #include "nodes/makefuncs.h"
27 #include "utils/array.h"
28 #include "utils/builtins.h"
29 #include "utils/lsyscache.h"
30 #include "utils/syscache.h"
33 /* ---------- AMOP CACHES ---------- */
38 * Return t iff operator 'opno' is in operator class 'opclass'.
41 op_in_opclass(Oid opno, Oid opclass)
43 return SearchSysCacheExists(AMOPOPID,
44 ObjectIdGetDatum(opclass),
45 ObjectIdGetDatum(opno),
52 * Return t if operator 'opno' requires a recheck when used as a
53 * member of opclass 'opclass' (ie, this opclass is lossy for this
56 * Caller should already have verified that opno is a member of opclass,
57 * therefore we raise an error if the tuple is not found.
60 op_requires_recheck(Oid opno, Oid opclass)
63 Form_pg_amop amop_tup;
66 tp = SearchSysCache(AMOPOPID,
67 ObjectIdGetDatum(opclass),
68 ObjectIdGetDatum(opno),
70 if (!HeapTupleIsValid(tp))
71 elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u",
73 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
75 result = amop_tup->amopreqcheck;
80 /* ---------- ATTRIBUTE CACHES ---------- */
85 * Given the relation id and the attribute number,
86 * return the "attname" field from the attribute relation.
88 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
91 get_attname(Oid relid, AttrNumber attnum)
95 tp = SearchSysCache(ATTNUM,
96 ObjectIdGetDatum(relid),
97 Int16GetDatum(attnum),
99 if (HeapTupleIsValid(tp))
101 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
104 result = pstrdup(NameStr(att_tup->attname));
115 * Given the relation id and the attribute name,
116 * return the "attnum" field from the attribute relation.
119 get_attnum(Oid relid, char *attname)
123 tp = SearchSysCache(ATTNAME,
124 ObjectIdGetDatum(relid),
125 PointerGetDatum(attname),
127 if (HeapTupleIsValid(tp))
129 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
132 result = att_tup->attnum;
137 return InvalidAttrNumber;
143 * Given the relation OID and the attribute number with the relation,
144 * return the attribute type OID.
147 get_atttype(Oid relid, AttrNumber attnum)
151 tp = SearchSysCache(ATTNUM,
152 ObjectIdGetDatum(relid),
153 Int16GetDatum(attnum),
155 if (HeapTupleIsValid(tp))
157 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
160 result = att_tup->atttypid;
168 /* This routine uses the attname instead of the attnum because it
169 * replaces the routine find_atttype, which is called sometimes when
170 * only the attname, not the attno, is available.
173 get_attisset(Oid relid, char *attname)
177 tp = SearchSysCache(ATTNAME,
178 ObjectIdGetDatum(relid),
179 PointerGetDatum(attname),
181 if (HeapTupleIsValid(tp))
183 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
186 result = att_tup->attisset;
197 * Given the relation id and the attribute number,
198 * return the "atttypmod" field from the attribute relation.
201 get_atttypmod(Oid relid, AttrNumber attnum)
205 tp = SearchSysCache(ATTNUM,
206 ObjectIdGetDatum(relid),
207 Int16GetDatum(attnum),
209 if (HeapTupleIsValid(tp))
211 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
214 result = att_tup->atttypmod;
225 * A two-fer: given the relation id and the attribute number,
226 * fetch both type OID and atttypmod in a single cache lookup.
228 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
229 * raises an error if it can't obtain the information.
232 get_atttypetypmod(Oid relid, AttrNumber attnum,
233 Oid *typid, int32 *typmod)
236 Form_pg_attribute att_tup;
238 tp = SearchSysCache(ATTNUM,
239 ObjectIdGetDatum(relid),
240 Int16GetDatum(attnum),
242 if (!HeapTupleIsValid(tp))
243 elog(ERROR, "cache lookup failed for relation %u attribute %d",
245 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
247 *typid = att_tup->atttypid;
248 *typmod = att_tup->atttypmod;
252 /* ---------- INDEX CACHE ---------- */
254 /* watch this space...
257 /* ---------- OPCLASS CACHE ---------- */
262 * Returns TRUE iff the specified opclass is associated with the
263 * btree index access method.
266 opclass_is_btree(Oid opclass)
269 Form_pg_opclass cla_tup;
272 tp = SearchSysCache(CLAOID,
273 ObjectIdGetDatum(opclass),
275 if (!HeapTupleIsValid(tp))
276 elog(ERROR, "cache lookup failed for opclass %u", opclass);
277 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
279 result = (cla_tup->opcamid == BTREE_AM_OID);
284 /* ---------- OPERATOR CACHE ---------- */
289 * Returns the regproc id of the routine used to implement an
290 * operator given the operator oid.
297 tp = SearchSysCache(OPEROID,
298 ObjectIdGetDatum(opno),
300 if (HeapTupleIsValid(tp))
302 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
305 result = optup->oprcode;
310 return (RegProcedure) InvalidOid;
315 * returns the name of the operator with the given opno
317 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
324 tp = SearchSysCache(OPEROID,
325 ObjectIdGetDatum(opno),
327 if (HeapTupleIsValid(tp))
329 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
332 result = pstrdup(NameStr(optup->oprname));
343 * Returns the left and right sort operators and types corresponding to a
344 * mergejoinable operator, or nil if the operator is not mergejoinable.
347 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
352 tp = SearchSysCache(OPEROID,
353 ObjectIdGetDatum(opno),
355 if (HeapTupleIsValid(tp))
357 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
359 if (optup->oprlsortop &&
361 optup->oprleft == ltype &&
362 optup->oprright == rtype)
364 *leftOp = optup->oprlsortop;
365 *rightOp = optup->oprrsortop;
374 * op_mergejoin_crossops
376 * Returns the cross-type comparison operators (ltype "<" rtype and
377 * ltype ">" rtype) for an operator previously determined to be
378 * mergejoinable. Optionally, fetches the regproc ids of these
379 * operators, as well as their operator OIDs.
381 * Raises error if operators cannot be found. Assuming that the operator
382 * had indeed been marked mergejoinable, this indicates that whoever marked
383 * it so was mistaken.
386 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
387 RegProcedure *ltproc, RegProcedure *gtproc)
390 Form_pg_operator optup;
395 * Get the declared left and right operand types of the operator.
397 tp = SearchSysCache(OPEROID,
398 ObjectIdGetDatum(opno),
400 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
401 elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
402 optup = (Form_pg_operator) GETSTRUCT(tp);
403 oprleft = optup->oprleft;
404 oprright = optup->oprright;
408 * Look up the "<" operator with the same input types. If there isn't
409 * one, whoever marked the "=" operator mergejoinable was a loser.
411 tp = SearchSysCache(OPERNAME,
412 PointerGetDatum("<"),
413 ObjectIdGetDatum(oprleft),
414 ObjectIdGetDatum(oprright),
416 if (!HeapTupleIsValid(tp))
417 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
419 optup = (Form_pg_operator) GETSTRUCT(tp);
420 *ltop = tp->t_data->t_oid;
422 *ltproc = optup->oprcode;
426 * And the same for the ">" operator.
428 tp = SearchSysCache(OPERNAME,
429 PointerGetDatum(">"),
430 ObjectIdGetDatum(oprleft),
431 ObjectIdGetDatum(oprright),
433 if (!HeapTupleIsValid(tp))
434 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
436 optup = (Form_pg_operator) GETSTRUCT(tp);
437 *gtop = tp->t_data->t_oid;
439 *gtproc = optup->oprcode;
446 * Returns the hash operator corresponding to a hashjoinable operator,
447 * or InvalidOid if the operator is not hashjoinable.
450 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
453 Oid result = InvalidOid;
455 tp = SearchSysCache(OPEROID,
456 ObjectIdGetDatum(opno),
458 if (HeapTupleIsValid(tp))
460 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
462 if (optup->oprcanhash &&
463 optup->oprleft == ltype &&
464 optup->oprright == rtype)
474 * Get the proiscachable flag for the operator's underlying function.
477 op_iscachable(Oid opno)
479 RegProcedure funcid = get_opcode(opno);
481 if (funcid == (RegProcedure) InvalidOid)
482 elog(ERROR, "Operator OID %u does not exist", opno);
484 return func_iscachable((Oid) funcid);
490 * Returns the corresponding commutator of an operator.
493 get_commutator(Oid opno)
497 tp = SearchSysCache(OPEROID,
498 ObjectIdGetDatum(opno),
500 if (HeapTupleIsValid(tp))
502 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
505 result = optup->oprcom;
516 * Returns the corresponding negator of an operator.
519 get_negator(Oid opno)
523 tp = SearchSysCache(OPEROID,
524 ObjectIdGetDatum(opno),
526 if (HeapTupleIsValid(tp))
528 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
531 result = optup->oprnegate;
542 * Returns procedure id for computing selectivity of an operator.
545 get_oprrest(Oid opno)
549 tp = SearchSysCache(OPEROID,
550 ObjectIdGetDatum(opno),
552 if (HeapTupleIsValid(tp))
554 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
557 result = optup->oprrest;
562 return (RegProcedure) InvalidOid;
568 * Returns procedure id for computing selectivity of a join.
571 get_oprjoin(Oid opno)
575 tp = SearchSysCache(OPEROID,
576 ObjectIdGetDatum(opno),
578 if (HeapTupleIsValid(tp))
580 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
583 result = optup->oprjoin;
588 return (RegProcedure) InvalidOid;
591 /* ---------- FUNCTION CACHE ---------- */
595 * Given procedure id, return the function's result type.
598 get_func_rettype(Oid funcid)
603 tp = SearchSysCache(PROCOID,
604 ObjectIdGetDatum(funcid),
606 if (!HeapTupleIsValid(tp))
607 elog(ERROR, "Function OID %u does not exist", funcid);
609 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
616 * Given procedure id, return the function's proiscachable flag.
619 func_iscachable(Oid funcid)
624 tp = SearchSysCache(PROCOID,
625 ObjectIdGetDatum(funcid),
627 if (!HeapTupleIsValid(tp))
628 elog(ERROR, "Function OID %u does not exist", funcid);
630 result = ((Form_pg_proc) GETSTRUCT(tp))->proiscachable;
635 /* ---------- RELATION CACHE ---------- */
641 * Returns the number of attributes for a given relation.
644 get_relnatts(Oid relid)
648 tp = SearchSysCache(RELOID,
649 ObjectIdGetDatum(relid),
651 if (HeapTupleIsValid(tp))
653 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
656 result = reltup->relnatts;
661 return InvalidAttrNumber;
668 * Returns the name of a given relation.
670 * Note: returns a palloc'd copy of the string, or NULL if no such relation.
673 get_rel_name(Oid relid)
677 tp = SearchSysCache(RELOID,
678 ObjectIdGetDatum(relid),
680 if (HeapTupleIsValid(tp))
682 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
685 result = pstrdup(NameStr(reltup->relname));
696 * Returns the pg_type OID associated with a given relation.
698 * Note: not all pg_class entries have associated pg_type OIDs; so be
699 * careful to check for InvalidOid result.
702 get_rel_type_id(Oid relid)
706 tp = SearchSysCache(RELOID,
707 ObjectIdGetDatum(relid),
709 if (HeapTupleIsValid(tp))
711 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
714 result = reltup->reltype;
722 /* ---------- TYPE CACHE ---------- */
727 * Given the type OID, return the length of the type.
730 get_typlen(Oid typid)
734 tp = SearchSysCache(TYPEOID,
735 ObjectIdGetDatum(typid),
737 if (HeapTupleIsValid(tp))
739 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
742 result = typtup->typlen;
753 * Given the type OID, determine whether the type is returned by value or
754 * not. Returns true if by value, false if by reference.
757 get_typbyval(Oid typid)
761 tp = SearchSysCache(TYPEOID,
762 ObjectIdGetDatum(typid),
764 if (HeapTupleIsValid(tp))
766 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
769 result = typtup->typbyval;
780 * A two-fer: given the type OID, return both typlen and typbyval.
782 * Since both pieces of info are needed to know how to copy a Datum,
783 * many places need both. Might as well get them with one cache lookup
784 * instead of two. Also, this routine raises an error instead of
785 * returning a bogus value when given a bad type OID.
788 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
793 tp = SearchSysCache(TYPEOID,
794 ObjectIdGetDatum(typid),
796 if (!HeapTupleIsValid(tp))
797 elog(ERROR, "cache lookup failed for type %u", typid);
798 typtup = (Form_pg_type) GETSTRUCT(tp);
799 *typlen = typtup->typlen;
800 *typbyval = typtup->typbyval;
806 get_typalign(Oid typid)
810 tp = SearchSysCache(TYPEOID,
811 ObjectIdGetDatum(typid),
813 if (HeapTupleIsValid(tp))
815 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
818 result = typtup->typalign;
828 get_typstorage(Oid typid)
832 tp = SearchSysCache(TYPEOID,
833 ObjectIdGetDatum(typid),
835 if (HeapTupleIsValid(tp))
837 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
840 result = typtup->typstorage;
850 * Given a type OID, return the type's default value, if any.
852 * The result is a palloc'd expression node tree, or NULL if there
853 * is no defined default for the datatype.
855 * NB: caller should be prepared to coerce result to correct datatype;
856 * the returned expression tree might produce something of the wrong type.
859 get_typdefault(Oid typid)
867 typeTuple = SearchSysCache(TYPEOID,
868 ObjectIdGetDatum(typid),
870 if (!HeapTupleIsValid(typeTuple))
871 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
872 type = (Form_pg_type) GETSTRUCT(typeTuple);
875 * typdefault and typdefaultbin are potentially null, so don't try to
876 * access 'em as struct fields. Must do it the hard way with
879 datum = SysCacheGetAttr(TYPEOID,
881 Anum_pg_type_typdefaultbin,
886 /* We have an expression default */
887 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
892 /* Perhaps we have a plain literal default */
893 datum = SysCacheGetAttr(TYPEOID,
895 Anum_pg_type_typdefault,
902 /* Convert text datum to C string */
903 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
905 /* Convert C string to a value of the given type */
906 datum = OidFunctionCall3(type->typinput,
907 CStringGetDatum(strDefaultVal),
908 ObjectIdGetDatum(type->typelem),
910 /* Build a Const node containing the value */
911 expr = (Node *) makeConst(typid,
916 false, /* not a set */
918 pfree(strDefaultVal);
927 ReleaseSysCache(typeTuple);
934 * If the given type is a domain, return its base type;
935 * otherwise return the type's own OID.
938 getBaseType(Oid typid)
941 * We loop to find the bottom base type in a stack of domains.
948 tup = SearchSysCache(TYPEOID,
949 ObjectIdGetDatum(typid),
951 if (!HeapTupleIsValid(tup))
952 elog(ERROR, "getBaseType: failed to lookup type %u", typid);
953 typTup = (Form_pg_type) GETSTRUCT(tup);
954 if (typTup->typtype != 'd')
956 /* Not a domain, so done */
957 ReleaseSysCache(tup);
961 typid = typTup->typbasetype;
962 ReleaseSysCache(tup);
971 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
972 * estimate the average width of values of the type. This is used by
973 * the planner, which doesn't require absolutely correct results;
974 * it's OK (and expected) to guess if we don't know for sure.
977 get_typavgwidth(Oid typid, int32 typmod)
979 int typlen = get_typlen(typid);
983 * Easy if it's a fixed-width type
989 * type_maximum_size knows the encoding of typmod for some datatypes;
990 * don't duplicate that knowledge here.
992 maxwidth = type_maximum_size(typid, typmod);
996 * For BPCHAR, the max width is also the only width. Otherwise we
997 * need to guess about the typical data width given the max. A
998 * sliding scale for percentage of max width seems reasonable.
1000 if (typid == BPCHAROID)
1003 return maxwidth; /* assume full width */
1004 if (maxwidth < 1000)
1005 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1008 * Beyond 1000, assume we're looking at something like
1009 * "varchar(10000)" where the limit isn't actually reached often,
1010 * and use a fixed estimate.
1012 return 32 + (1000 - 32) / 2;
1016 * Ooops, we have no idea ... wild guess time.
1024 * Given the type OID, find if it is a basic type, a named relation
1025 * or the generic type 'relation'.
1026 * It returns the null char if the cache lookup fails...
1030 get_typtype(Oid typid)
1034 tp = SearchSysCache(TYPEOID,
1035 ObjectIdGetDatum(typid),
1037 if (HeapTupleIsValid(tp))
1039 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1042 result = typtup->typtype;
1043 ReleaseSysCache(tp);
1051 /* ---------- STATISTICS CACHE ---------- */
1056 * Given the table and attribute number of a column, get the average
1057 * width of entries in the column. Return zero if no data available.
1060 get_attavgwidth(Oid relid, AttrNumber attnum)
1064 tp = SearchSysCache(STATRELATT,
1065 ObjectIdGetDatum(relid),
1066 Int16GetDatum(attnum),
1068 if (HeapTupleIsValid(tp))
1070 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1072 ReleaseSysCache(tp);
1082 * Extract the contents of a "slot" of a pg_statistic tuple.
1083 * Returns TRUE if requested slot type was found, else FALSE.
1085 * Unlike other routines in this file, this takes a pointer to an
1086 * already-looked-up tuple in the pg_statistic cache. We do this since
1087 * most callers will want to extract more than one value from the cache
1088 * entry, and we don't want to repeat the cache lookup unnecessarily.
1090 * statstuple: pg_statistics tuple to be examined.
1091 * atttype: type OID of attribute.
1092 * atttypmod: typmod of attribute.
1093 * reqkind: STAKIND code for desired statistics slot kind.
1094 * reqop: STAOP value wanted, or InvalidOid if don't care.
1095 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1096 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1098 * If assigned, values and numbers are set to point to palloc'd arrays.
1099 * If the attribute type is pass-by-reference, the values referenced by
1100 * the values array are themselves palloc'd. The palloc'd stuff can be
1101 * freed by calling free_attstatsslot.
1104 get_attstatsslot(HeapTuple statstuple,
1105 Oid atttype, int32 atttypmod,
1106 int reqkind, Oid reqop,
1107 Datum **values, int *nvalues,
1108 float4 **numbers, int *nnumbers)
1110 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1115 ArrayType *statarray;
1117 HeapTuple typeTuple;
1121 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1123 if ((&stats->stakind1)[i] == reqkind &&
1124 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1127 if (i >= STATISTIC_NUM_SLOTS)
1128 return false; /* not there */
1132 val = SysCacheGetAttr(STATRELATT, statstuple,
1133 Anum_pg_statistic_stavalues1 + i,
1136 elog(ERROR, "get_attstatsslot: stavalues is null");
1137 statarray = DatumGetArrayTypeP(val);
1140 * Do initial examination of the array. This produces a list of
1141 * text Datums --- ie, pointers into the text array value.
1143 deconstruct_array(statarray, false, -1, 'i', values, nvalues);
1144 narrayelem = *nvalues;
1147 * We now need to replace each text Datum by its internal
1150 * Get the type input proc and typelem for the column datatype.
1152 typeTuple = SearchSysCache(TYPEOID,
1153 ObjectIdGetDatum(atttype),
1155 if (!HeapTupleIsValid(typeTuple))
1156 elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u",
1158 fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc);
1159 typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
1160 ReleaseSysCache(typeTuple);
1163 * Do the conversions. The palloc'd array of Datums is reused in
1166 for (j = 0; j < narrayelem; j++)
1170 strval = DatumGetCString(DirectFunctionCall1(textout,
1172 (*values)[j] = FunctionCall3(&inputproc,
1173 CStringGetDatum(strval),
1174 ObjectIdGetDatum(typelem),
1175 Int32GetDatum(atttypmod));
1180 * Free statarray if it's a detoasted copy.
1182 if ((Pointer) statarray != DatumGetPointer(val))
1188 val = SysCacheGetAttr(STATRELATT, statstuple,
1189 Anum_pg_statistic_stanumbers1 + i,
1192 elog(ERROR, "get_attstatsslot: stanumbers is null");
1193 statarray = DatumGetArrayTypeP(val);
1196 * We expect the array to be a 1-D float4 array; verify that. We
1197 * don't need to use deconstruct_array() since the array data is
1198 * just going to look like a C array of float4 values.
1200 narrayelem = ARR_DIMS(statarray)[0];
1201 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1202 ARR_SIZE(statarray) != (ARR_OVERHEAD(1) + narrayelem * sizeof(float4)))
1203 elog(ERROR, "get_attstatsslot: stanumbers is bogus");
1204 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1205 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1206 *nnumbers = narrayelem;
1209 * Free statarray if it's a detoasted copy.
1211 if ((Pointer) statarray != DatumGetPointer(val))
1219 free_attstatsslot(Oid atttype,
1220 Datum *values, int nvalues,
1221 float4 *numbers, int nnumbers)
1225 if (!get_typbyval(atttype))
1229 for (i = 0; i < nvalues; i++)
1230 pfree(DatumGetPointer(values[i]));
1238 /* ---------- PG_SHADOW CACHE ---------- */
1243 * Given a user name, look up the user's sysid.
1244 * Raises an error if no such user (rather than returning zero,
1245 * which might possibly be a valid usesysid).
1247 * Note: the type of usesysid is currently int4, but may change to Oid
1248 * someday. It'd be reasonable to return zero on failure if we were
1252 get_usesysid(const char *username)
1257 userTup = SearchSysCache(SHADOWNAME,
1258 PointerGetDatum(username),
1260 if (!HeapTupleIsValid(userTup))
1261 elog(ERROR, "user \"%s\" does not exist", username);
1263 result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
1265 ReleaseSysCache(userTup);