📄 heaptuple.c
字号:
Form_pg_attribute thisatt = att[attnum]; if (hasnulls && att_isnull(attnum, bp)) { values[attnum] = (Datum) 0; isnull[attnum] = true; slow = true; /* can't use attcacheoff anymore */ continue; } isnull[attnum] = false; if (!slow && thisatt->attcacheoff >= 0) off = thisatt->attcacheoff; else { off = att_align(off, thisatt->attalign); if (!slow) thisatt->attcacheoff = off; } values[attnum] = fetchatt(thisatt, tp + off); off = att_addlength(off, thisatt->attlen, tp + off); if (thisatt->attlen <= 0) slow = true; /* can't use attcacheoff anymore */ } /* * If tuple doesn't have all the atts indicated by tupleDesc, read the * rest as null */ for (; attnum < tdesc_natts; attnum++) { values[attnum] = (Datum) 0; isnull[attnum] = true; }}/* ---------------- * heap_deformtuple * * Given a tuple, extract data into values/nulls arrays; this is * the inverse of heap_formtuple. * * Storage for the values/nulls arrays is provided by the caller; * it should be sized according to tupleDesc->natts not tuple->t_natts. * * Note that for pass-by-reference datatypes, the pointer placed * in the Datum will point into the given tuple. * * When all or most of a tuple's fields need to be extracted, * this routine will be significantly quicker than a loop around * heap_getattr; the loop will become O(N^2) as soon as any * noncacheable attribute offsets are involved. * * OLD API with char 'n'/' ' convention for indicating nulls * ---------------- */voidheap_deformtuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, char *nulls){ HeapTupleHeader tup = tuple->t_data; bool hasnulls = HeapTupleHasNulls(tuple); Form_pg_attribute *att = tupleDesc->attrs; int tdesc_natts = tupleDesc->natts; int natts; /* number of atts to extract */ int attnum; char *tp; /* ptr to tuple data */ long off; /* offset in tuple data */ bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ bool slow = false; /* can we use/set attcacheoff? */ natts = tup->t_natts; /* * In inheritance situations, it is possible that the given tuple actually * has more fields than the caller is expecting. Don't run off the end of * the caller's arrays. */ natts = Min(natts, tdesc_natts); tp = (char *) tup + tup->t_hoff; off = 0; for (attnum = 0; attnum < natts; attnum++) { Form_pg_attribute thisatt = att[attnum]; if (hasnulls && att_isnull(attnum, bp)) { values[attnum] = (Datum) 0; nulls[attnum] = 'n'; slow = true; /* can't use attcacheoff anymore */ continue; } nulls[attnum] = ' '; if (!slow && thisatt->attcacheoff >= 0) off = thisatt->attcacheoff; else { off = att_align(off, thisatt->attalign); if (!slow) thisatt->attcacheoff = off; } values[attnum] = fetchatt(thisatt, tp + off); off = att_addlength(off, thisatt->attlen, tp + off); if (thisatt->attlen <= 0) slow = true; /* can't use attcacheoff anymore */ } /* * If tuple doesn't have all the atts indicated by tupleDesc, read the * rest as null */ for (; attnum < tdesc_natts; attnum++) { values[attnum] = (Datum) 0; nulls[attnum] = 'n'; }}/* * slot_deform_tuple * Given a TupleTableSlot, extract data from the slot's physical tuple * into its Datum/isnull arrays. Data is extracted up through the * natts'th column (caller must ensure this is a legal column number). * * This is essentially an incremental version of heap_deform_tuple: * on each call we extract attributes up to the one needed, without * re-computing information about previously extracted attributes. * slot->tts_nvalid is the number of attributes already extracted. */static voidslot_deform_tuple(TupleTableSlot *slot, int natts){ HeapTuple tuple = slot->tts_tuple; TupleDesc tupleDesc = slot->tts_tupleDescriptor; Datum *values = slot->tts_values; bool *isnull = slot->tts_isnull; HeapTupleHeader tup = tuple->t_data; bool hasnulls = HeapTupleHasNulls(tuple); Form_pg_attribute *att = tupleDesc->attrs; int attnum; char *tp; /* ptr to tuple data */ long off; /* offset in tuple data */ bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ bool slow; /* can we use/set attcacheoff? */ /* * Check whether the first call for this tuple, and initialize or restore * loop state. */ attnum = slot->tts_nvalid; if (attnum == 0) { /* Start from the first attribute */ off = 0; slow = false; } else { /* Restore state from previous execution */ off = slot->tts_off; slow = slot->tts_slow; } tp = (char *) tup + tup->t_hoff; for (; attnum < natts; attnum++) { Form_pg_attribute thisatt = att[attnum]; if (hasnulls && att_isnull(attnum, bp)) { values[attnum] = (Datum) 0; isnull[attnum] = true; slow = true; /* can't use attcacheoff anymore */ continue; } isnull[attnum] = false; if (!slow && thisatt->attcacheoff >= 0) off = thisatt->attcacheoff; else { off = att_align(off, thisatt->attalign); if (!slow) thisatt->attcacheoff = off; } values[attnum] = fetchatt(thisatt, tp + off); off = att_addlength(off, thisatt->attlen, tp + off); if (thisatt->attlen <= 0) slow = true; /* can't use attcacheoff anymore */ } /* * Save state for next execution */ slot->tts_nvalid = attnum; slot->tts_off = off; slot->tts_slow = slow;}/* * slot_getattr * This function fetches an attribute of the slot's current tuple. * It is functionally equivalent to heap_getattr, but fetches of * multiple attributes of the same tuple will be optimized better, * because we avoid O(N^2) behavior from multiple calls of * nocachegetattr(), even when attcacheoff isn't usable. * * A difference from raw heap_getattr is that attnums beyond the * slot's tupdesc's last attribute will be considered NULL even * when the physical tuple is longer than the tupdesc. */Datumslot_getattr(TupleTableSlot *slot, int attnum, bool *isnull){ HeapTuple tuple = slot->tts_tuple; TupleDesc tupleDesc = slot->tts_tupleDescriptor; HeapTupleHeader tup; /* * system attributes are handled by heap_getsysattr */ if (attnum <= 0) { if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract system attribute from virtual tuple"); return heap_getsysattr(tuple, attnum, tupleDesc, isnull); } /* * fast path if desired attribute already cached */ if (attnum <= slot->tts_nvalid) { *isnull = slot->tts_isnull[attnum - 1]; return slot->tts_values[attnum - 1]; } /* * return NULL if attnum is out of range according to the tupdesc */ if (attnum > tupleDesc->natts) { *isnull = true; return (Datum) 0; } /* * otherwise we had better have a physical tuple (tts_nvalid should equal * natts in all virtual-tuple cases) */ if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract attribute from empty tuple slot"); /* * return NULL if attnum is out of range according to the tuple * * (We have to check this separately because of various inheritance and * table-alteration scenarios: the tuple could be either longer or shorter * than the tupdesc.) */ tup = tuple->t_data; if (attnum > tup->t_natts) { *isnull = true; return (Datum) 0; } /* * check if target attribute is null: no point in groveling through tuple */ if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits)) { *isnull = true; return (Datum) 0; } /* * If the attribute's column has been dropped, we force a NULL result. * This case should not happen in normal use, but it could happen if we * are executing a plan cached before the column was dropped. */ if (tupleDesc->attrs[attnum - 1]->attisdropped) { *isnull = true; return (Datum) 0; } /* * Extract the attribute, along with any preceding attributes. */ slot_deform_tuple(slot, attnum); /* * The result is acquired from tts_values array. */ *isnull = slot->tts_isnull[attnum - 1]; return slot->tts_values[attnum - 1];}/* * slot_getallattrs * This function forces all the entries of the slot's Datum/isnull * arrays to be valid. The caller may then extract data directly * from those arrays instead of using slot_getattr. */voidslot_getallattrs(TupleTableSlot *slot){ int tdesc_natts = slot->tts_tupleDescriptor->natts; int attnum; HeapTuple tuple; /* Quick out if we have 'em all already */ if (slot->tts_nvalid == tdesc_natts) return; /* * otherwise we had better have a physical tuple (tts_nvalid should equal * natts in all virtual-tuple cases) */ tuple = slot->tts_tuple; if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract attribute from empty tuple slot"); /* * load up any slots available from physical tuple */ attnum = tuple->t_data->t_natts; attnum = Min(attnum, tdesc_natts); slot_deform_tuple(slot, attnum); /* * If tuple doesn't have all the atts indicated by tupleDesc, read the * rest as null */ for (; attnum < tdesc_natts; attnum++) { slot->tts_values[attnum] = (Datum) 0; slot->tts_isnull[attnum] = true; } slot->tts_nvalid = tdesc_natts;}/* * slot_getsomeattrs * This function forces the entries of the slot's Datum/isnull * arrays to be valid at least up through the attnum'th entry. */voidslot_getsomeattrs(TupleTableSlot *slot, int attnum){ HeapTuple tuple; int attno; /* Quick out if we have 'em all already */ if (slot->tts_nvalid >= attnum) return; /* Check for caller error */ if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts) elog(ERROR, "invalid attribute number %d", attnum); /* * otherwise we had better have a physical tuple (tts_nvalid should equal * natts in all virtual-tuple cases) */ tuple = slot->tts_tuple; if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract attribute from empty tuple slot"); /* * load up any slots available from physical tuple */ attno = tuple->t_data->t_natts; attno = Min(attno, attnum); slot_deform_tuple(slot, attno); /* * If tuple doesn't have all the atts indicated by tupleDesc, read the * rest as null */ for (; attno < attnum; attno++) { slot->tts_values[attno] = (Datum) 0; slot->tts_isnull[attno] = true; } slot->tts_nvalid = attnum;}/* * slot_attisnull * Detect whether an attribute of the slot is null, without * actually fetching it. */boolslot_attisnull(TupleTableSlot *slot, int attnum){ HeapTuple tuple = slot->tts_tuple; TupleDesc tupleDesc = slot->tts_tupleDescriptor; /* * system attributes are handled by heap_attisnull */ if (attnum <= 0) { if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract system attribute from virtual tuple"); return heap_attisnull(tuple, attnum); } /* * fast path if desired attribute already cached */ if (attnum <= slot->tts_nvalid) return slot->tts_isnull[attnum - 1]; /* * return NULL if attnum is out of range according to the tupdesc */ if (attnum > tupleDesc->natts) return true; /* * otherwise we had better have a physical tuple (tts_nvalid should equal * natts in all virtual-tuple cases) */ if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract attribute from empty tuple slot"); /* and let the tuple tell it */ return heap_attisnull(tuple, attnum);}/* ---------------- * heap_freetuple * ---------------- */voidheap_freetuple(HeapTuple htup){ if (htup->t_data != NULL) if (htup->t_datamcxt != NULL && (char *) (htup->t_data) != ((char *) htup + HEAPTUPLESIZE)) pfree(htup->t_data); pfree(htup);}/* ---------------- * heap_addheader * * This routine forms a HeapTuple by copying the given structure (tuple * data) and adding a generic header. Note that the tuple data is * presumed to contain no null fields and no varlena fields. * * This routine is really only useful for certain system tables that are * known to be fixed-width and null-free. It is used in some places for * pg_class, but that is a gross hack (it only works because relacl can * be omitted from the tuple entirely in those places). * ---------------- */HeapTupleheap_addheader(int natts, /* max domain index */ bool withoid, /* reserve space for oid */ Size structlen, /* its length */ void *structure) /* pointer to the struct */{ HeapTuple tuple; HeapTupleHeader td; Size len; int hoff; AssertArg(natts > 0); /* header needs no null bitmap */ hoff = offsetof(HeapTupleHeaderData, t_bits); if (withoid) hoff += sizeof(Oid); hoff = MAXALIGN(hoff); len = hoff + structlen; tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len); tuple->t_datamcxt = CurrentMemoryContext; tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE); tuple->t_len = len; ItemPointerSetInvalid(&(tuple->t_self)); tuple->t_tableOid = InvalidOid; /* we don't bother to fill the Datum fields */ td->t_natts = natts; td->t_hoff = hoff; if (withoid) /* else leave infomask = 0 */ td->t_infomask = HEAP_HASOID; memcpy((char *) td + hoff, structure, structlen); return tuple;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -