📄 heaptuple.c
字号:
slow = true; } } else { /* not varlena, so safe to use att_align_nominal */ off = att_align_nominal(off, thisatt->attalign); if (!slow) thisatt->attcacheoff = off; } values[attnum] = fetchatt(thisatt, tp + off); off = att_addlength_pointer(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"); if (slot->tts_mintuple) /* internal error */ elog(ERROR, "cannot extract system attribute from minimal 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 > HeapTupleHeaderGetNatts(tup)) { *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 = HeapTupleHeaderGetNatts(tuple->t_data); 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 = HeapTupleHeaderGetNatts(tuple->t_data); 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"); if (slot->tts_mintuple) /* internal error */ elog(ERROR, "cannot extract system attribute from minimal 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){ pfree(htup);}/* * heap_form_minimal_tuple * construct a MinimalTuple from the given values[] and isnull[] arrays, * which are of the length indicated by tupleDescriptor->natts * * This is exactly like heap_form_tuple() except that the result is a * "minimal" tuple lacking a HeapTupleData header as well as room for system * columns. * * The result is allocated in the current memory context. */MinimalTupleheap_form_minimal_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull){ MinimalTuple tuple; /* return tuple */ Size len, data_len; int hoff; bool hasnull = false; Form_pg_attribute *att = tupleDescriptor->attrs; int numberOfAttributes = tupleDescriptor->natts; int i; if (numberOfAttributes > MaxTupleAttributeNumber) ereport(ERROR, (errcode(ERRCODE_TOO_MANY_COLUMNS), errmsg("number of columns (%d) exceeds limit (%d)", numberOfAttributes, MaxTupleAttributeNumber))); /* * Check for nulls and embedded tuples; expand any toasted attributes in * embedded tuples. This preserves the invariant that toasting can only * go one level deep. * * We can skip calling toast_flatten_tuple_attribute() if the attribute * couldn't possibly be of composite type. All composite datums are * varlena and have alignment 'd'; furthermore they aren't arrays. Also, * if an attribute is already toasted, it must have been sent to disk * already and so cannot contain toasted attributes. */ for (i = 0; i < numberOfAttributes; i++) { if (isnull[i]) hasnull = true; else if (att[i]->attlen == -1 && att[i]->attalign == 'd' && att[i]->attndims == 0 && !VARATT_IS_EXTENDED(values[i])) { values[i] = toast_flatten_tuple_attribute(values[i], att[i]->atttypid, att[i]->atttypmod); } } /* * Determine total space needed */ len = offsetof(MinimalTupleData, t_bits); if (hasnull) len += BITMAPLEN(numberOfAttributes); if (tupleDescriptor->tdhasoid) len += sizeof(Oid); hoff = len = MAXALIGN(len); /* align user data safely */ data_len = heap_compute_data_size(tupleDescriptor, values, isnull); len += data_len; /* * Allocate and zero the space needed. */ tuple = (MinimalTuple) palloc0(len); /* * And fill in the information. */ tuple->t_len = len; HeapTupleHeaderSetNatts(tuple, numberOfAttributes); tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET; if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */ tuple->t_infomask = HEAP_HASOID; heap_fill_tuple(tupleDescriptor, values, isnull, (char *) tuple + hoff, data_len, &tuple->t_infomask, (hasnull ? tuple->t_bits : NULL)); return tuple;}/* * heap_free_minimal_tuple */voidheap_free_minimal_tuple(MinimalTuple mtup){ pfree(mtup);}/* * heap_copy_minimal_tuple * copy a MinimalTuple * * The result is allocated in the current memory context. */MinimalTupleheap_copy_minimal_tuple(MinimalTuple mtup){ MinimalTuple result; result = (MinimalTuple) palloc(mtup->t_len); memcpy(result, mtup, mtup->t_len); return result;}/* * heap_tuple_from_minimal_tuple * create a HeapTuple by copying from a MinimalTuple; * system columns are filled with zeroes * * The result is allocated in the current memory context. * The HeapTuple struct, tuple header, and tuple data are all allocated * as a single palloc() block. */HeapTupleheap_tuple_from_minimal_tuple(MinimalTuple mtup){ HeapTuple result; uint32 len = mtup->t_len + MINIMAL_TUPLE_OFFSET; result = (HeapTuple) palloc(HEAPTUPLESIZE + len); result->t_len = len; ItemPointerSetInvalid(&(result->t_self)); result->t_tableOid = InvalidOid; result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE); memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len); memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2)); return result;}/* * minimal_tuple_from_heap_tuple * create a MinimalTuple by copying from a HeapTuple * * The result is allocated in the current memory context. */MinimalTupleminimal_tuple_from_heap_tuple(HeapTuple htup){ MinimalTuple result; uint32 len; Assert(htup->t_len > MINIMAL_TUPLE_OFFSET); len = htup->t_len - MINIMAL_TUPLE_OFFSET; result = (MinimalTuple) palloc(len); memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len); result->t_len = len; return result;}/* ---------------- * 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. Currently it is only used for * pg_attribute tuples. * ---------------- */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_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 */ HeapTupleHeaderSetNatts(td, 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 + -