summaryrefslogtreecommitdiff
path: root/contrib/pageinspect/heapfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pageinspect/heapfuncs.c')
-rw-r--r--contrib/pageinspect/heapfuncs.c138
1 files changed, 78 insertions, 60 deletions
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 68f16cd400c..02e2ab9997a 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -507,99 +507,117 @@ PG_FUNCTION_INFO_V1(heap_tuple_infomask_flags);
Datum
heap_tuple_infomask_flags(PG_FUNCTION_ARGS)
{
+#define HEAP_TUPLE_INFOMASK_COLS 2
+ Datum values[HEAP_TUPLE_INFOMASK_COLS];
+ bool nulls[HEAP_TUPLE_INFOMASK_COLS];
uint16 t_infomask = PG_GETARG_INT16(0);
uint16 t_infomask2 = PG_GETARG_INT16(1);
- bool decode_combined = PG_GETARG_BOOL(2);
int cnt = 0;
ArrayType *a;
int bitcnt;
- Datum *d;
+ Datum *flags;
+ TupleDesc tupdesc;
+ HeapTuple tuple;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use raw page functions")));
+ /* Build a tuple descriptor for our result type */
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+
bitcnt = pg_popcount((const char *) &t_infomask, sizeof(uint16)) +
pg_popcount((const char *) &t_infomask2, sizeof(uint16));
- /* If no flags, return an empty array */
+ /* Initialize values and NULL flags arrays */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, 0, sizeof(nulls));
+
+ /* If no flags, return a set of empty arrays */
if (bitcnt <= 0)
- PG_RETURN_POINTER(construct_empty_array(TEXTOID));
+ {
+ values[0] = PointerGetDatum(construct_empty_array(TEXTOID));
+ values[1] = PointerGetDatum(construct_empty_array(TEXTOID));
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+ PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
+ }
- d = (Datum *) palloc0(sizeof(Datum) * bitcnt);
+ /* build set of raw flags */
+ flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
/* decode t_infomask */
if ((t_infomask & HEAP_HASNULL) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_HASNULL");
+ flags[cnt++] = CStringGetTextDatum("HEAP_HASNULL");
if ((t_infomask & HEAP_HASVARWIDTH) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_HASVARWIDTH");
+ flags[cnt++] = CStringGetTextDatum("HEAP_HASVARWIDTH");
if ((t_infomask & HEAP_HASEXTERNAL) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_HASEXTERNAL");
+ flags[cnt++] = CStringGetTextDatum("HEAP_HASEXTERNAL");
if ((t_infomask & HEAP_HASOID_OLD) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_HASOID_OLD");
+ flags[cnt++] = CStringGetTextDatum("HEAP_HASOID_OLD");
+ if ((t_infomask & HEAP_XMAX_KEYSHR_LOCK) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_KEYSHR_LOCK");
if ((t_infomask & HEAP_COMBOCID) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_COMBOCID");
+ flags[cnt++] = CStringGetTextDatum("HEAP_COMBOCID");
+ if ((t_infomask & HEAP_XMAX_EXCL_LOCK) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_EXCL_LOCK");
+ if ((t_infomask & HEAP_XMAX_LOCK_ONLY) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_LOCK_ONLY");
+ if ((t_infomask & HEAP_XMIN_COMMITTED) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMIN_COMMITTED");
+ if ((t_infomask & HEAP_XMIN_INVALID) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMIN_INVALID");
if ((t_infomask & HEAP_XMAX_COMMITTED) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_COMMITTED");
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_COMMITTED");
if ((t_infomask & HEAP_XMAX_INVALID) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_INVALID");
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_INVALID");
+ if ((t_infomask & HEAP_XMAX_IS_MULTI) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_IS_MULTI");
if ((t_infomask & HEAP_UPDATED) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_UPDATED");
-
- /* decode combined masks of t_infomaks */
- if (decode_combined && (t_infomask & HEAP_XMAX_SHR_LOCK) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_SHR_LOCK");
- else
- {
- if ((t_infomask & HEAP_XMAX_EXCL_LOCK) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_EXCL_LOCK");
- if ((t_infomask & HEAP_XMAX_KEYSHR_LOCK) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_KEYSHR_LOCK");
- }
-
- if (decode_combined && (t_infomask & HEAP_XMIN_FROZEN) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMIN_FROZEN");
- else
- {
- if ((t_infomask & HEAP_XMIN_COMMITTED) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMIN_COMMITTED");
- if ((t_infomask & HEAP_XMIN_INVALID) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMIN_INVALID");
- }
-
- if (decode_combined && (t_infomask & HEAP_MOVED) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_MOVED");
- else
- {
- if ((t_infomask & HEAP_MOVED_IN) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_MOVED_IN");
- if ((t_infomask & HEAP_MOVED_OFF) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_MOVED_OFF");
- }
-
- if (decode_combined && HEAP_LOCKED_UPGRADED(t_infomask))
- d[cnt++] = CStringGetTextDatum("HEAP_LOCKED_UPGRADED");
- else
- {
- if (HEAP_XMAX_IS_LOCKED_ONLY(t_infomask))
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_LOCK_ONLY");
- if ((t_infomask & HEAP_XMAX_IS_MULTI) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_XMAX_IS_MULTI");
- }
+ flags[cnt++] = CStringGetTextDatum("HEAP_UPDATED");
+ if ((t_infomask & HEAP_MOVED_OFF) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_MOVED_OFF");
+ if ((t_infomask & HEAP_MOVED_IN) != 0)
+ flags[cnt++] = CStringGetTextDatum("HEAP_MOVED_IN");
/* decode t_infomask2 */
if ((t_infomask2 & HEAP_KEYS_UPDATED) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_KEYS_UPDATED");
+ flags[cnt++] = CStringGetTextDatum("HEAP_KEYS_UPDATED");
if ((t_infomask2 & HEAP_HOT_UPDATED) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_HOT_UPDATED");
+ flags[cnt++] = CStringGetTextDatum("HEAP_HOT_UPDATED");
if ((t_infomask2 & HEAP_ONLY_TUPLE) != 0)
- d[cnt++] = CStringGetTextDatum("HEAP_ONLY_TUPLE");
+ flags[cnt++] = CStringGetTextDatum("HEAP_ONLY_TUPLE");
+ /* build value */
Assert(cnt <= bitcnt);
- a = construct_array(d, cnt, TEXTOID, -1, false, 'i');
+ a = construct_array(flags, cnt, TEXTOID, -1, false, 'i');
+ values[0] = PointerGetDatum(a);
- pfree(d);
+ /*
+ * Build set of combined flags. Use the same array as previously, this
+ * keeps the code simple.
+ */
+ cnt = 0;
+ MemSet(flags, 0, sizeof(Datum) * bitcnt);
+
+ /* decode combined masks of t_infomask */
+ if ((t_infomask & HEAP_XMAX_SHR_LOCK) == HEAP_XMAX_SHR_LOCK)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_SHR_LOCK");
+ if ((t_infomask & HEAP_XMIN_FROZEN) == HEAP_XMIN_FROZEN)
+ flags[cnt++] = CStringGetTextDatum("HEAP_XMIN_FROZEN");
+ if ((t_infomask & HEAP_MOVED) == HEAP_MOVED)
+ flags[cnt++] = CStringGetTextDatum("HEAP_MOVED");
+
+ /* Build an empty array if there are no combined flags */
+ if (cnt == 0)
+ a = construct_empty_array(TEXTOID);
+ else
+ a = construct_array(flags, cnt, TEXTOID, -1, false, 'i');
+ pfree(flags);
+ values[1] = PointerGetDatum(a);
- PG_RETURN_POINTER(a);
+ /* Returns the record as Datum */
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+ PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
}