Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "postgres.h"
00027
00028 #include "access/htup_details.h"
00029 #include "funcapi.h"
00030 #include "utils/builtins.h"
00031 #include "miscadmin.h"
00032
00033 Datum heap_page_items(PG_FUNCTION_ARGS);
00034
00035
00036
00037
00038
00039
00040
00041
00042 static char *
00043 bits_to_text(bits8 *bits, int len)
00044 {
00045 int i;
00046 char *str;
00047
00048 str = palloc(len + 1);
00049
00050 for (i = 0; i < len; i++)
00051 str[i] = (bits[(i / 8)] & (1 << (i % 8))) ? '1' : '0';
00052
00053 str[i] = '\0';
00054
00055 return str;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064 PG_FUNCTION_INFO_V1(heap_page_items);
00065
00066 typedef struct heap_page_items_state
00067 {
00068 TupleDesc tupd;
00069 Page page;
00070 uint16 offset;
00071 } heap_page_items_state;
00072
00073 Datum
00074 heap_page_items(PG_FUNCTION_ARGS)
00075 {
00076 bytea *raw_page = PG_GETARG_BYTEA_P(0);
00077 heap_page_items_state *inter_call_data = NULL;
00078 FuncCallContext *fctx;
00079 int raw_page_size;
00080
00081 if (!superuser())
00082 ereport(ERROR,
00083 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00084 (errmsg("must be superuser to use raw page functions"))));
00085
00086 raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
00087
00088 if (SRF_IS_FIRSTCALL())
00089 {
00090 TupleDesc tupdesc;
00091 MemoryContext mctx;
00092
00093 if (raw_page_size < SizeOfPageHeaderData)
00094 ereport(ERROR,
00095 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00096 errmsg("input page too small (%d bytes)", raw_page_size)));
00097
00098 fctx = SRF_FIRSTCALL_INIT();
00099 mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
00100
00101 inter_call_data = palloc(sizeof(heap_page_items_state));
00102
00103
00104 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
00105 elog(ERROR, "return type must be a row type");
00106
00107 inter_call_data->tupd = tupdesc;
00108
00109 inter_call_data->offset = FirstOffsetNumber;
00110 inter_call_data->page = VARDATA(raw_page);
00111
00112 fctx->max_calls = PageGetMaxOffsetNumber(inter_call_data->page);
00113 fctx->user_fctx = inter_call_data;
00114
00115 MemoryContextSwitchTo(mctx);
00116 }
00117
00118 fctx = SRF_PERCALL_SETUP();
00119 inter_call_data = fctx->user_fctx;
00120
00121 if (fctx->call_cntr < fctx->max_calls)
00122 {
00123 Page page = inter_call_data->page;
00124 HeapTuple resultTuple;
00125 Datum result;
00126 ItemId id;
00127 Datum values[13];
00128 bool nulls[13];
00129 uint16 lp_offset;
00130 uint16 lp_flags;
00131 uint16 lp_len;
00132
00133 memset(nulls, 0, sizeof(nulls));
00134
00135
00136
00137 id = PageGetItemId(page, inter_call_data->offset);
00138
00139 lp_offset = ItemIdGetOffset(id);
00140 lp_flags = ItemIdGetFlags(id);
00141 lp_len = ItemIdGetLength(id);
00142
00143 values[0] = UInt16GetDatum(inter_call_data->offset);
00144 values[1] = UInt16GetDatum(lp_offset);
00145 values[2] = UInt16GetDatum(lp_flags);
00146 values[3] = UInt16GetDatum(lp_len);
00147
00148
00149
00150
00151
00152
00153 if (ItemIdHasStorage(id) &&
00154 lp_len >= sizeof(HeapTupleHeader) &&
00155 lp_offset == MAXALIGN(lp_offset) &&
00156 lp_offset + lp_len <= raw_page_size)
00157 {
00158 HeapTupleHeader tuphdr;
00159 int bits_len;
00160
00161
00162
00163 tuphdr = (HeapTupleHeader) PageGetItem(page, id);
00164
00165 values[4] = UInt32GetDatum(HeapTupleHeaderGetXmin(tuphdr));
00166 values[5] = UInt32GetDatum(HeapTupleHeaderGetRawXmax(tuphdr));
00167 values[6] = UInt32GetDatum(HeapTupleHeaderGetRawCommandId(tuphdr));
00168 values[7] = PointerGetDatum(&tuphdr->t_ctid);
00169 values[8] = UInt32GetDatum(tuphdr->t_infomask2);
00170 values[9] = UInt32GetDatum(tuphdr->t_infomask);
00171 values[10] = UInt8GetDatum(tuphdr->t_hoff);
00172
00173
00174
00175
00176
00177
00178
00179 if (tuphdr->t_hoff >= sizeof(HeapTupleHeader) &&
00180 tuphdr->t_hoff <= lp_len)
00181 {
00182 if (tuphdr->t_infomask & HEAP_HASNULL)
00183 {
00184 bits_len = tuphdr->t_hoff -
00185 (((char *) tuphdr->t_bits) -((char *) tuphdr));
00186
00187 values[11] = CStringGetTextDatum(
00188 bits_to_text(tuphdr->t_bits, bits_len * 8));
00189 }
00190 else
00191 nulls[11] = true;
00192
00193 if (tuphdr->t_infomask & HEAP_HASOID)
00194 values[12] = HeapTupleHeaderGetOid(tuphdr);
00195 else
00196 nulls[12] = true;
00197 }
00198 else
00199 {
00200 nulls[11] = true;
00201 nulls[12] = true;
00202 }
00203 }
00204 else
00205 {
00206
00207
00208
00209
00210 int i;
00211
00212 for (i = 4; i <= 12; i++)
00213 nulls[i] = true;
00214 }
00215
00216
00217 resultTuple = heap_form_tuple(inter_call_data->tupd, values, nulls);
00218 result = HeapTupleGetDatum(resultTuple);
00219
00220 inter_call_data->offset++;
00221
00222 SRF_RETURN_NEXT(fctx, result);
00223 }
00224 else
00225 SRF_RETURN_DONE(fctx);
00226 }