📄 heaptuple.c
字号:
/*------------------------------------------------------------------------- * * heaptuple.c * This file contains heap tuple accessor and mutator routines, as well * as a few various tuple utilities. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.53.2.1 1999/08/02 05:24:25 scrappy Exp $ * * NOTES * The old interface functions have been converted to macros * and moved to heapam.h * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/pg_type.h"/* Used by heap_getattr() macro, for speed */long heap_sysoffset[] = {/* Only the first one is pass-by-ref, and is handled specially in the macro */ offsetof(HeapTupleHeaderData, t_ctid), offsetof(HeapTupleHeaderData, t_oid), offsetof(HeapTupleHeaderData, t_xmin), offsetof(HeapTupleHeaderData, t_cmin), offsetof(HeapTupleHeaderData, t_xmax), offsetof(HeapTupleHeaderData, t_cmax)};/* ---------------------------------------------------------------- * misc support routines * ---------------------------------------------------------------- *//* ---------------- * ComputeDataSize * ---------------- */SizeComputeDataSize(TupleDesc tupleDesc, Datum *value, char *nulls){ uint32 data_length; int i; int numberOfAttributes = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; for (data_length = 0, i = 0; i < numberOfAttributes; i++) { if (nulls[i] != ' ') continue; data_length = att_align(data_length, att[i]->attlen, att[i]->attalign); data_length = att_addlength(data_length, att[i]->attlen, value[i]); } return data_length;}/* ---------------- * DataFill * ---------------- */voidDataFill(char *data, TupleDesc tupleDesc, Datum *value, char *nulls, uint16 *infomask, bits8 *bit){ bits8 *bitP = 0; int bitmask = 0; uint32 data_length; int i; int numberOfAttributes = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; if (bit != NULL) { bitP = &bit[-1]; bitmask = CSIGNBIT; } *infomask = 0; for (i = 0; i < numberOfAttributes; i++) { if (bit != NULL) { if (bitmask != CSIGNBIT) bitmask <<= 1; else { bitP += 1; *bitP = 0x0; bitmask = 1; } if (nulls[i] == 'n') { *infomask |= HEAP_HASNULL; continue; } *bitP |= bitmask; } data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign); switch (att[i]->attlen) { case -1: *infomask |= HEAP_HASVARLENA; data_length = VARSIZE(DatumGetPointer(value[i])); memmove(data, DatumGetPointer(value[i]), data_length); break; case sizeof(char): *data = att[i]->attbyval ? DatumGetChar(value[i]) : *((char *) value[i]); break; case sizeof(int16): *(short *) data = (att[i]->attbyval ? DatumGetInt16(value[i]) : *((short *) value[i])); break; case sizeof(int32): *(int32 *) data = (att[i]->attbyval ? DatumGetInt32(value[i]) : *((int32 *) value[i])); break; default: memmove(data, DatumGetPointer(value[i]), att[i]->attlen); break; } data = (char *) att_addlength((long) data, att[i]->attlen, value[i]); }}/* ---------------------------------------------------------------- * heap tuple interface * ---------------------------------------------------------------- *//* ---------------- * heap_attisnull - returns 1 iff tuple attribute is not present * ---------------- */intheap_attisnull(HeapTuple tup, int attnum){ if (attnum > (int) tup->t_data->t_natts) return 1; if (HeapTupleNoNulls(tup)) return 0; if (attnum > 0) return att_isnull(attnum - 1, tup->t_data->t_bits); else switch (attnum) { case SelfItemPointerAttributeNumber: case ObjectIdAttributeNumber: case MinTransactionIdAttributeNumber: case MinCommandIdAttributeNumber: case MaxTransactionIdAttributeNumber: case MaxCommandIdAttributeNumber: break; case 0: elog(ERROR, "heap_attisnull: zero attnum disallowed"); default: elog(ERROR, "heap_attisnull: undefined negative attnum"); } return 0;}/* ---------------------------------------------------------------- * system attribute heap tuple support * ---------------------------------------------------------------- *//* ---------------- * heap_sysattrlen * * This routine returns the length of a system attribute. * ---------------- */intheap_sysattrlen(AttrNumber attno){ HeapTupleHeader f = NULL; switch (attno) { case SelfItemPointerAttributeNumber: return sizeof f->t_ctid; case ObjectIdAttributeNumber: return sizeof f->t_oid; case MinTransactionIdAttributeNumber: return sizeof f->t_xmin; case MinCommandIdAttributeNumber: return sizeof f->t_cmin; case MaxTransactionIdAttributeNumber: return sizeof f->t_xmax; case MaxCommandIdAttributeNumber: return sizeof f->t_cmax; default: elog(ERROR, "sysattrlen: System attribute number %d unknown.", attno); return 0; }}/* ---------------- * heap_sysattrbyval * * This routine returns the "by-value" property of a system attribute. * ---------------- */boolheap_sysattrbyval(AttrNumber attno){ bool byval; switch (attno) { case SelfItemPointerAttributeNumber: byval = false; break; case ObjectIdAttributeNumber: byval = true; break; case MinTransactionIdAttributeNumber: byval = true; break; case MinCommandIdAttributeNumber: byval = true; break; case MaxTransactionIdAttributeNumber: byval = true; break; case MaxCommandIdAttributeNumber: byval = true; break; default: byval = true; elog(ERROR, "sysattrbyval: System attribute number %d unknown.", attno); break; } return byval;}#ifdef NOT_USED/* ---------------- * heap_getsysattr * ---------------- */Datumheap_getsysattr(HeapTuple tup, Buffer b, int attnum){ switch (attnum) { case SelfItemPointerAttributeNumber: return (Datum) &tup->t_ctid; case ObjectIdAttributeNumber: return (Datum) (long) tup->t_oid; case MinTransactionIdAttributeNumber: return (Datum) (long) tup->t_xmin; case MinCommandIdAttributeNumber: return (Datum) (long) tup->t_cmin; case MaxTransactionIdAttributeNumber: return (Datum) (long) tup->t_xmax; case MaxCommandIdAttributeNumber: return (Datum) (long) tup->t_cmax; default: elog(ERROR, "heap_getsysattr: undefined attnum %d", attnum); } return (Datum) NULL;}#endif/* ---------------- * nocachegetattr * * This only gets called from fastgetattr() macro, in cases where * we can't use a cacheoffset and the value is not null. * * This caches attribute offsets in the attribute descriptor. * * An alternate way to speed things up would be to cache offsets * with the tuple, but that seems more difficult unless you take * the storage hit of actually putting those offsets into the * tuple you send to disk. Yuck. * * This scheme will be slightly slower than that, but should * perform well for queries which hit large #'s of tuples. After * you cache the offsets once, examining all the other tuples using * the same attribute descriptor will go much quicker. -cim 5/4/91 * ---------------- */Datumnocachegetattr(HeapTuple tuple, int attnum, TupleDesc tupleDesc, bool *isnull){ char *tp; /* ptr to att in tuple */ HeapTupleHeader tup = tuple->t_data; bits8 *bp = tup->t_bits; /* ptr to att in tuple */ Form_pg_attribute *att = tupleDesc->attrs; int slow = 0; /* do we have to walk nulls? */#if IN_MACRO/* This is handled in the macro */ Assert(attnum > 0); if (isnull) *isnull = false;#endif attnum--; /* ---------------- * Three cases: * * 1: No nulls and no variable length attributes. * 2: Has a null or a varlena AFTER att. * 3: Has nulls or varlenas BEFORE att. * ---------------- */ if (HeapTupleNoNulls(tuple)) {#if IN_MACRO/* This is handled in the macro */ if (att[attnum]->attcacheoff != -1) { return (Datum) fetchatt(&(att[attnum]), (char *) tup + tup->t_hoff + att[attnum]->attcacheoff); } else if (attnum == 0) { /* * first attribute is always at position zero */ return (Datum) fetchatt(&(att[0]), (char *) tup + tup->t_hoff); }#endif } else { /* * there's a null somewhere in the tuple */ /* ---------------- * check to see if desired att is null * ---------------- */#if IN_MACRO/* This is handled in the macro */ if (att_isnull(attnum, bp)) { if (isnull) *isnull = true; return (Datum) NULL; }#endif /* ---------------- * Now check to see if any preceding bits are null... * ---------------- */ { int byte = attnum >> 3; int finalbit = attnum & 0x07; /* check for nulls "before" final bit of last byte */ if ((~bp[byte]) & ((1 << finalbit) - 1)) slow = 1; else { /* check for nulls in any "earlier" bytes */ int i; for (i = 0; i < byte; i++) { if (bp[i] != 0xFF) { slow = 1; break; } } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -