PostgreSQL Source Code git master
Loading...
Searching...
No Matches
heapfuncs.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "catalog/pg_am_d.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "pageinspect.h"
#include "port/pg_bitutils.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/rel.h"
Include dependency graph for heapfuncs.c:

Go to the source code of this file.

Data Structures

struct  heap_page_items_state
 

Macros

#define HEAP_TUPLE_INFOMASK_COLS   2
 

Typedefs

typedef struct heap_page_items_state heap_page_items_state
 

Functions

static Oid HeapTupleHeaderGetOidOld (const HeapTupleHeaderData *tup)
 
static charbits_to_text (bits8 *bits, int len)
 
static bits8text_to_bits (char *str, int len)
 
 PG_FUNCTION_INFO_V1 (heap_page_items)
 
Datum heap_page_items (PG_FUNCTION_ARGS)
 
static Datum tuple_data_split_internal (Oid relid, char *tupdata, uint16 tupdata_len, uint16 t_infomask, uint16 t_infomask2, bits8 *t_bits, bool do_detoast)
 
 PG_FUNCTION_INFO_V1 (tuple_data_split)
 
Datum tuple_data_split (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (heap_tuple_infomask_flags)
 
Datum heap_tuple_infomask_flags (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ HEAP_TUPLE_INFOMASK_COLS

#define HEAP_TUPLE_INFOMASK_COLS   2

Typedef Documentation

◆ heap_page_items_state

Function Documentation

◆ bits_to_text()

static char * bits_to_text ( bits8 bits,
int  len 
)
static

Definition at line 63 of file heapfuncs.c.

64{
65 int i;
66 char *str;
67
68 str = palloc(len + 1);
69
70 for (i = 0; i < len; i++)
71 str[i] = (bits[(i / 8)] & (1 << (i % 8))) ? '1' : '0';
72
73 str[i] = '\0';
74
75 return str;
76}
const char * str
int i
Definition isn.c:77
void * palloc(Size size)
Definition mcxt.c:1387
const void size_t len

References i, len, palloc(), and str.

Referenced by heap_page_items().

◆ heap_page_items()

Datum heap_page_items ( PG_FUNCTION_ARGS  )

Definition at line 131 of file heapfuncs.c.

132{
136
137 if (!superuser())
140 errmsg("must be superuser to use raw page functions")));
141
142 if (SRF_IS_FIRSTCALL())
143 {
144 TupleDesc tupdesc;
146
148 mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
149
151
152 /* Build a tuple descriptor for our result type */
153 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
154 elog(ERROR, "return type must be a row type");
155
156 inter_call_data->tupd = tupdesc;
157
160
161 fctx->max_calls = PageGetMaxOffsetNumber(inter_call_data->page);
162 fctx->user_fctx = inter_call_data;
163
165 }
166
168 inter_call_data = fctx->user_fctx;
169
170 if (fctx->call_cntr < fctx->max_calls)
171 {
172 Page page = inter_call_data->page;
174 Datum result;
175 ItemId id;
176 Datum values[14];
177 bool nulls[14];
179 uint16 lp_flags;
180 uint16 lp_len;
181
182 memset(nulls, 0, sizeof(nulls));
183
184 /* Extract information from the line pointer */
185
186 id = PageGetItemId(page, inter_call_data->offset);
187
189 lp_flags = ItemIdGetFlags(id);
190 lp_len = ItemIdGetLength(id);
191
194 values[2] = UInt16GetDatum(lp_flags);
195 values[3] = UInt16GetDatum(lp_len);
196
197 /*
198 * We do just enough validity checking to make sure we don't reference
199 * data outside the page passed to us. The page could be corrupt in
200 * many other ways, but at least we won't crash.
201 */
202 if (ItemIdHasStorage(id) &&
203 lp_len >= MinHeapTupleSize &&
205 lp_offset + lp_len <= BLCKSZ)
206 {
207 HeapTupleHeader tuphdr;
208
209 /* Extract information from the tuple header */
210 tuphdr = (HeapTupleHeader) PageGetItem(page, id);
211
214 /* shared with xvac */
216 values[7] = PointerGetDatum(&tuphdr->t_ctid);
217 values[8] = UInt32GetDatum(tuphdr->t_infomask2);
218 values[9] = UInt32GetDatum(tuphdr->t_infomask);
219 values[10] = UInt8GetDatum(tuphdr->t_hoff);
220
221 /*
222 * We already checked that the item is completely within the raw
223 * page passed to us, with the length given in the line pointer.
224 * But t_hoff could be out of range, so check it before relying on
225 * it to fetch additional info.
226 */
227 if (tuphdr->t_hoff >= SizeofHeapTupleHeader &&
228 tuphdr->t_hoff <= lp_len &&
229 tuphdr->t_hoff == MAXALIGN(tuphdr->t_hoff))
230 {
231 int tuple_data_len;
233
234 /* Copy null bitmask and OID, if present */
235 if (tuphdr->t_infomask & HEAP_HASNULL)
236 {
237 int bitmaplen;
238
240 /* better range-check the attribute count, too */
242 values[11] =
245 else
246 nulls[11] = true;
247 }
248 else
249 nulls[11] = true;
250
251 if (tuphdr->t_infomask & HEAP_HASOID_OLD)
253 else
254 nulls[12] = true;
255
256 /* Copy raw tuple data into bytea attribute */
257 tuple_data_len = lp_len - tuphdr->t_hoff;
260 if (tuple_data_len > 0)
262 (char *) tuphdr + tuphdr->t_hoff,
265 }
266 else
267 {
268 nulls[11] = true;
269 nulls[12] = true;
270 nulls[13] = true;
271 }
272 }
273 else
274 {
275 /*
276 * The line pointer is not used, or it's invalid. Set the rest of
277 * the fields to NULL
278 */
279 int i;
280
281 for (i = 4; i <= 13; i++)
282 nulls[i] = true;
283 }
284
285 /* Build and return the result tuple. */
288
289 inter_call_data->offset++;
290
291 SRF_RETURN_NEXT(fctx, result);
292 }
293 else
295}
static Datum values[MAXATTR]
Definition bootstrap.c:187
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:269
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
Definition bufpage.h:379
PageData * Page
Definition bufpage.h:81
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:397
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define MAXALIGN(LEN)
Definition c.h:868
#define VARHDRSZ
Definition c.h:753
uint16_t uint16
Definition c.h:587
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_GETARG_BYTEA_P(n)
Definition fmgr.h:336
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
static char * bits_to_text(bits8 *bits, int len)
Definition heapfuncs.c:63
static Oid HeapTupleHeaderGetOidOld(const HeapTupleHeaderData *tup)
Definition heapfuncs.c:47
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
HeapTupleHeaderData * HeapTupleHeader
Definition htup.h:23
#define HeapTupleHeaderGetNatts(tup)
#define SizeofHeapTupleHeader
#define MinHeapTupleSize
#define HEAP_HASNULL
static int BITMAPLEN(int NATTS)
static CommandId HeapTupleHeaderGetRawCommandId(const HeapTupleHeaderData *tup)
#define HEAP_HASOID_OLD
static TransactionId HeapTupleHeaderGetRawXmax(const HeapTupleHeaderData *tup)
static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)
#define ItemIdGetLength(itemId)
Definition itemid.h:59
#define ItemIdGetOffset(itemId)
Definition itemid.h:65
#define ItemIdGetFlags(itemId)
Definition itemid.h:71
#define ItemIdHasStorage(itemId)
Definition itemid.h:120
static char * errmsg
#define FirstOffsetNumber
Definition off.h:27
Page get_page_from_raw(bytea *raw_page)
Definition rawpage.c:216
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define BITS_PER_BYTE
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum UInt16GetDatum(uint16 X)
Definition postgres.h:192
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Datum UInt8GetDatum(uint8 X)
Definition postgres.h:152
static Datum UInt32GetDatum(uint32 X)
Definition postgres.h:232
static int fb(int x)
ItemPointerData t_ctid
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition c.h:748
bool superuser(void)
Definition superuser.c:47
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432

References BITMAPLEN(), BITS_PER_BYTE, bits_to_text(), CStringGetTextDatum, elog, ereport, errcode(), errmsg, ERROR, fb(), FirstOffsetNumber, get_call_result_type(), get_page_from_raw(), heap_form_tuple(), HEAP_HASNULL, HEAP_HASOID_OLD, HeapTupleGetDatum(), HeapTupleHeaderGetNatts, HeapTupleHeaderGetOidOld(), HeapTupleHeaderGetRawCommandId(), HeapTupleHeaderGetRawXmax(), HeapTupleHeaderGetRawXmin(), i, ItemIdGetFlags, ItemIdGetLength, ItemIdGetOffset, ItemIdHasStorage, MAXALIGN, MemoryContextSwitchTo(), MinHeapTupleSize, ObjectIdGetDatum(), PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), palloc(), palloc_object, PG_GETARG_BYTEA_P, PointerGetDatum(), SET_VARSIZE(), SizeofHeapTupleHeader, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, superuser(), HeapTupleHeaderData::t_bits, HeapTupleHeaderData::t_ctid, HeapTupleHeaderData::t_hoff, HeapTupleHeaderData::t_infomask, HeapTupleHeaderData::t_infomask2, TYPEFUNC_COMPOSITE, UInt16GetDatum(), UInt32GetDatum(), UInt8GetDatum(), values, VARDATA(), and VARHDRSZ.

◆ heap_tuple_infomask_flags()

Datum heap_tuple_infomask_flags ( PG_FUNCTION_ARGS  )

Definition at line 513 of file heapfuncs.c.

514{
515#define HEAP_TUPLE_INFOMASK_COLS 2
517 bool nulls[HEAP_TUPLE_INFOMASK_COLS] = {0};
518 uint16 t_infomask = PG_GETARG_INT16(0);
519 uint16 t_infomask2 = PG_GETARG_INT16(1);
520 int cnt = 0;
521 ArrayType *a;
522 int bitcnt;
523 Datum *flags;
524 TupleDesc tupdesc;
525 HeapTuple tuple;
526
527 if (!superuser())
530 errmsg("must be superuser to use raw page functions")));
531
532 /* Build a tuple descriptor for our result type */
533 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
534 elog(ERROR, "return type must be a row type");
535
536 bitcnt = pg_popcount((const char *) &t_infomask, sizeof(uint16)) +
537 pg_popcount((const char *) &t_infomask2, sizeof(uint16));
538
539 /* If no flags, return a set of empty arrays */
540 if (bitcnt <= 0)
541 {
544 tuple = heap_form_tuple(tupdesc, values, nulls);
546 }
547
548 /* build set of raw flags */
549 flags = palloc0_array(Datum, bitcnt);
550
551 /* decode t_infomask */
552 if ((t_infomask & HEAP_HASNULL) != 0)
553 flags[cnt++] = CStringGetTextDatum("HEAP_HASNULL");
554 if ((t_infomask & HEAP_HASVARWIDTH) != 0)
555 flags[cnt++] = CStringGetTextDatum("HEAP_HASVARWIDTH");
556 if ((t_infomask & HEAP_HASEXTERNAL) != 0)
557 flags[cnt++] = CStringGetTextDatum("HEAP_HASEXTERNAL");
558 if ((t_infomask & HEAP_HASOID_OLD) != 0)
559 flags[cnt++] = CStringGetTextDatum("HEAP_HASOID_OLD");
560 if ((t_infomask & HEAP_XMAX_KEYSHR_LOCK) != 0)
561 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_KEYSHR_LOCK");
562 if ((t_infomask & HEAP_COMBOCID) != 0)
563 flags[cnt++] = CStringGetTextDatum("HEAP_COMBOCID");
564 if ((t_infomask & HEAP_XMAX_EXCL_LOCK) != 0)
565 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_EXCL_LOCK");
566 if ((t_infomask & HEAP_XMAX_LOCK_ONLY) != 0)
567 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_LOCK_ONLY");
568 if ((t_infomask & HEAP_XMIN_COMMITTED) != 0)
569 flags[cnt++] = CStringGetTextDatum("HEAP_XMIN_COMMITTED");
570 if ((t_infomask & HEAP_XMIN_INVALID) != 0)
571 flags[cnt++] = CStringGetTextDatum("HEAP_XMIN_INVALID");
572 if ((t_infomask & HEAP_XMAX_COMMITTED) != 0)
573 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_COMMITTED");
574 if ((t_infomask & HEAP_XMAX_INVALID) != 0)
575 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_INVALID");
576 if ((t_infomask & HEAP_XMAX_IS_MULTI) != 0)
577 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_IS_MULTI");
578 if ((t_infomask & HEAP_UPDATED) != 0)
579 flags[cnt++] = CStringGetTextDatum("HEAP_UPDATED");
580 if ((t_infomask & HEAP_MOVED_OFF) != 0)
581 flags[cnt++] = CStringGetTextDatum("HEAP_MOVED_OFF");
582 if ((t_infomask & HEAP_MOVED_IN) != 0)
583 flags[cnt++] = CStringGetTextDatum("HEAP_MOVED_IN");
584
585 /* decode t_infomask2 */
586 if ((t_infomask2 & HEAP_KEYS_UPDATED) != 0)
587 flags[cnt++] = CStringGetTextDatum("HEAP_KEYS_UPDATED");
588 if ((t_infomask2 & HEAP_HOT_UPDATED) != 0)
589 flags[cnt++] = CStringGetTextDatum("HEAP_HOT_UPDATED");
590 if ((t_infomask2 & HEAP_ONLY_TUPLE) != 0)
591 flags[cnt++] = CStringGetTextDatum("HEAP_ONLY_TUPLE");
592
593 /* build value */
594 Assert(cnt <= bitcnt);
595 a = construct_array_builtin(flags, cnt, TEXTOID);
597
598 /*
599 * Build set of combined flags. Use the same array as previously, this
600 * keeps the code simple.
601 */
602 cnt = 0;
603 MemSet(flags, 0, sizeof(Datum) * bitcnt);
604
605 /* decode combined masks of t_infomask */
606 if ((t_infomask & HEAP_XMAX_SHR_LOCK) == HEAP_XMAX_SHR_LOCK)
607 flags[cnt++] = CStringGetTextDatum("HEAP_XMAX_SHR_LOCK");
608 if ((t_infomask & HEAP_XMIN_FROZEN) == HEAP_XMIN_FROZEN)
609 flags[cnt++] = CStringGetTextDatum("HEAP_XMIN_FROZEN");
610 if ((t_infomask & HEAP_MOVED) == HEAP_MOVED)
611 flags[cnt++] = CStringGetTextDatum("HEAP_MOVED");
612
613 /* Build an empty array if there are no combined flags */
614 if (cnt == 0)
616 else
617 a = construct_array_builtin(flags, cnt, TEXTOID);
618 pfree(flags);
620
621 /* Returns the record as Datum */
622 tuple = heap_form_tuple(tupdesc, values, nulls);
624}
ArrayType * construct_empty_array(Oid elmtype)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
#define Assert(condition)
Definition c.h:915
#define MemSet(start, val, len)
Definition c.h:1079
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
#define PG_GETARG_INT16(n)
Definition fmgr.h:271
#define HEAP_TUPLE_INFOMASK_COLS
#define HEAP_HASVARWIDTH
#define HEAP_MOVED_OFF
#define HEAP_XMAX_SHR_LOCK
#define HEAP_XMIN_FROZEN
#define HEAP_XMIN_COMMITTED
#define HEAP_KEYS_UPDATED
#define HEAP_HOT_UPDATED
#define HEAP_XMAX_LOCK_ONLY
#define HEAP_MOVED_IN
#define HEAP_MOVED
#define HEAP_XMAX_IS_MULTI
#define HEAP_XMAX_COMMITTED
#define HEAP_COMBOCID
#define HEAP_XMIN_INVALID
#define HEAP_HASEXTERNAL
#define HEAP_XMAX_EXCL_LOCK
#define HEAP_XMAX_INVALID
#define HEAP_UPDATED
#define HEAP_XMAX_KEYSHR_LOCK
#define HEAP_ONLY_TUPLE
int a
Definition isn.c:73
void pfree(void *pointer)
Definition mcxt.c:1616
static uint64 pg_popcount(const char *buf, int bytes)

References a, Assert, construct_array_builtin(), construct_empty_array(), CStringGetTextDatum, elog, ereport, errcode(), errmsg, ERROR, fb(), get_call_result_type(), HEAP_COMBOCID, heap_form_tuple(), HEAP_HASEXTERNAL, HEAP_HASNULL, HEAP_HASOID_OLD, HEAP_HASVARWIDTH, HEAP_HOT_UPDATED, HEAP_KEYS_UPDATED, HEAP_MOVED, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_ONLY_TUPLE, HEAP_TUPLE_INFOMASK_COLS, HEAP_UPDATED, HEAP_XMAX_COMMITTED, HEAP_XMAX_EXCL_LOCK, HEAP_XMAX_INVALID, HEAP_XMAX_IS_MULTI, HEAP_XMAX_KEYSHR_LOCK, HEAP_XMAX_LOCK_ONLY, HEAP_XMAX_SHR_LOCK, HEAP_XMIN_COMMITTED, HEAP_XMIN_FROZEN, HEAP_XMIN_INVALID, HeapTupleGetDatum(), MemSet, palloc0_array, pfree(), PG_GETARG_INT16, pg_popcount(), PG_RETURN_DATUM, PointerGetDatum(), superuser(), TYPEFUNC_COMPOSITE, and values.

◆ HeapTupleHeaderGetOidOld()

static Oid HeapTupleHeaderGetOidOld ( const HeapTupleHeaderData tup)
inlinestatic

Definition at line 47 of file heapfuncs.c.

48{
49 if (tup->t_infomask & HEAP_HASOID_OLD)
50 return *((const Oid *) ((const char *) (tup) + (tup)->t_hoff - sizeof(Oid)));
51 else
52 return InvalidOid;
53}
#define InvalidOid
unsigned int Oid

References fb(), HEAP_HASOID_OLD, and InvalidOid.

Referenced by heap_page_items().

◆ PG_FUNCTION_INFO_V1() [1/3]

PG_FUNCTION_INFO_V1 ( heap_page_items  )

◆ PG_FUNCTION_INFO_V1() [2/3]

PG_FUNCTION_INFO_V1 ( heap_tuple_infomask_flags  )

◆ PG_FUNCTION_INFO_V1() [3/3]

PG_FUNCTION_INFO_V1 ( tuple_data_split  )

◆ text_to_bits()

static bits8 * text_to_bits ( char str,
int  len 
)
static

Definition at line 86 of file heapfuncs.c.

87{
88 bits8 *bits;
89 int off = 0;
90 char byte = 0;
91
92 bits = palloc(len + 1);
93
94 while (off < len)
95 {
96 if (off % 8 == 0)
97 byte = 0;
98
99 if ((str[off] == '0') || (str[off] == '1'))
100 byte = byte | ((str[off] - '0') << off % 8);
101 else
104 errmsg("invalid character \"%.*s\" in t_bits string",
105 pg_mblen_cstr(str + off), str + off)));
106
107 if (off % 8 == 7)
108 bits[off / 8] = byte;
109
110 off++;
111 }
112
113 return bits;
114}
uint8 bits8
Definition c.h:595
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
#define ERRCODE_DATA_CORRUPTED

References ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg, ERROR, len, palloc(), pg_mblen_cstr(), and str.

Referenced by tuple_data_split().

◆ tuple_data_split()

Datum tuple_data_split ( PG_FUNCTION_ARGS  )

Definition at line 429 of file heapfuncs.c.

430{
431 Oid relid;
433 uint16 t_infomask;
434 uint16 t_infomask2;
435 char *t_bits_str;
436 bool do_detoast = false;
437 bits8 *t_bits = NULL;
438 Datum res;
439
440 relid = PG_GETARG_OID(0);
442 t_infomask = PG_GETARG_INT16(2);
443 t_infomask2 = PG_GETARG_INT16(3);
446
447 if (PG_NARGS() >= 6)
449
450 if (!superuser())
453 errmsg("must be superuser to use raw page functions")));
454
455 if (!raw_data)
457
458 /*
459 * Convert t_bits string back to the bits8 array as represented in the
460 * tuple header.
461 */
462 if (t_infomask & HEAP_HASNULL)
463 {
464 size_t bits_str_len;
465 size_t bits_len;
466
468 if (!t_bits_str)
471 errmsg("t_bits string must not be NULL")));
472
474 if (bits_len != bits_str_len)
477 errmsg("unexpected length of t_bits string: %zu, expected %zu",
479
480 /* do the conversion */
482 }
483 else
484 {
485 if (t_bits_str)
488 errmsg("t_bits string is expected to be NULL, but instead it is %zu bytes long",
489 strlen(t_bits_str))));
490 }
491
492 /* Split tuple data */
493 res = tuple_data_split_internal(relid, (char *) raw_data + VARHDRSZ,
495 t_infomask, t_infomask2, t_bits,
496 do_detoast);
497
498 if (t_bits)
499 pfree(t_bits);
500
501 PG_RETURN_DATUM(res);
502}
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_ARGISNULL(n)
Definition fmgr.h:209
#define PG_NARGS()
Definition fmgr.h:203
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
static Datum tuple_data_split_internal(Oid relid, char *tupdata, uint16 tupdata_len, uint16 t_infomask, uint16 t_infomask2, bits8 *t_bits, bool do_detoast)
Definition heapfuncs.c:306
static bits8 * text_to_bits(char *str, int len)
Definition heapfuncs.c:86
#define HEAP_NATTS_MASK
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
char * text_to_cstring(const text *t)
Definition varlena.c:215

References BITMAPLEN(), BITS_PER_BYTE, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg, ERROR, fb(), HEAP_HASNULL, HEAP_NATTS_MASK, pfree(), PG_ARGISNULL, PG_GETARG_BOOL, PG_GETARG_BYTEA_P, PG_GETARG_INT16, PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_NARGS, PG_RETURN_DATUM, PG_RETURN_NULL, superuser(), text_to_bits(), text_to_cstring(), tuple_data_split_internal(), VARHDRSZ, and VARSIZE().

◆ tuple_data_split_internal()

static Datum tuple_data_split_internal ( Oid  relid,
char tupdata,
uint16  tupdata_len,
uint16  t_infomask,
uint16  t_infomask2,
bits8 t_bits,
bool  do_detoast 
)
static

Definition at line 306 of file heapfuncs.c.

310{
312 int nattrs;
313 int i;
314 int off = 0;
315 Relation rel;
316 TupleDesc tupdesc;
317
318 /* Get tuple descriptor from relation OID */
319 rel = relation_open(relid, AccessShareLock);
320 tupdesc = RelationGetDescr(rel);
321
323 nattrs = tupdesc->natts;
324
325 /*
326 * Sequences always use heap AM, but they don't show that in the catalogs.
327 */
328 if (rel->rd_rel->relkind != RELKIND_SEQUENCE &&
329 rel->rd_rel->relam != HEAP_TABLE_AM_OID)
331 errmsg("only heap AM is supported")));
332
333 if (nattrs < (t_infomask2 & HEAP_NATTS_MASK))
336 errmsg("number of attributes in tuple header is greater than number of attributes in tuple descriptor")));
337
338 for (i = 0; i < nattrs; i++)
339 {
340 CompactAttribute *attr;
341 bool is_null;
343
344 attr = TupleDescCompactAttr(tupdesc, i);
345
346 /*
347 * Tuple header can specify fewer attributes than tuple descriptor as
348 * ALTER TABLE ADD COLUMN without DEFAULT keyword does not actually
349 * change tuples in pages, so attributes with numbers greater than
350 * (t_infomask2 & HEAP_NATTS_MASK) should be treated as NULL.
351 */
352 if (i >= (t_infomask2 & HEAP_NATTS_MASK))
353 is_null = true;
354 else
355 is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
356
357 if (!is_null)
358 {
359 int len;
360
361 if (attr->attlen == -1)
362 {
363 off = att_pointer_alignby(off, attr->attalignby, -1,
364 tupdata + off);
365
366 /*
367 * As VARSIZE_ANY throws an exception if it can't properly
368 * detect the type of external storage in macros VARTAG_SIZE,
369 * this check is repeated to have a nicer error handling.
370 */
371 if (VARATT_IS_EXTERNAL(tupdata + off) &&
372 !VARATT_IS_EXTERNAL_ONDISK(tupdata + off) &&
373 !VARATT_IS_EXTERNAL_INDIRECT(tupdata + off))
376 errmsg("first byte of varlena attribute is incorrect for attribute %d", i)));
377
378 len = VARSIZE_ANY(tupdata + off);
379 }
380 else
381 {
382 off = att_nominal_alignby(off, attr->attalignby);
383 len = attr->attlen;
384 }
385
386 if (tupdata_len < off + len)
389 errmsg("unexpected end of tuple data")));
390
391 if (attr->attlen == -1 && do_detoast)
392 attr_data = pg_detoast_datum_copy((varlena *) (tupdata + off));
393 else
394 {
397 memcpy(VARDATA(attr_data), tupdata + off, len);
398 }
399
400 off = att_addlength_pointer(off, attr->attlen,
401 tupdata + off);
402 }
403
406 if (attr_data)
408 }
409
410 if (tupdata_len != off)
413 errmsg("end of tuple reached without looking at all its data")));
414
416
418}
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
varlena * pg_detoast_datum_copy(varlena *datum)
Definition fmgr.c:1806
#define AccessShareLock
Definition lockdefs.h:36
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define RelationGetDescr(relation)
Definition rel.h:540
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
uint8 attalignby
Definition tupdesc.h:80
Form_pg_class rd_rel
Definition rel.h:111
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:175
#define att_nominal_alignby(cur_offset, attalignby)
Definition tupmacs.h:189
static bool att_isnull(int ATT, const bits8 *BITS)
Definition tupmacs.h:26
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition tupmacs.h:209
#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr)
Definition tupmacs.h:161
static bool VARATT_IS_EXTERNAL_ONDISK(const void *PTR)
Definition varatt.h:361
static Size VARSIZE_ANY(const void *PTR)
Definition varatt.h:460
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition varatt.h:354
static bool VARATT_IS_EXTERNAL_INDIRECT(const void *PTR)
Definition varatt.h:368

References AccessShareLock, accumArrayResult(), att_addlength_pointer, att_isnull(), att_nominal_alignby, att_pointer_alignby, CompactAttribute::attalignby, CompactAttribute::attlen, CurrentMemoryContext, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg, ERROR, fb(), HEAP_HASNULL, HEAP_NATTS_MASK, i, initArrayResult(), len, makeArrayResult(), TupleDescData::natts, palloc(), pfree(), pg_detoast_datum_copy(), PointerGetDatum(), RelationData::rd_rel, relation_close(), relation_open(), RelationGetDescr, SET_VARSIZE(), TupleDescCompactAttr(), VARATT_IS_EXTERNAL(), VARATT_IS_EXTERNAL_INDIRECT(), VARATT_IS_EXTERNAL_ONDISK(), VARDATA(), VARHDRSZ, and VARSIZE_ANY().

Referenced by tuple_data_split().