⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heaptuple.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
			}			/* If we know the next offset, we can skip the alignment calc */			if (usecache && att[i]->attcacheoff != -1)				off = att[i]->attcacheoff;			else			{				off = att_align(off, att[i]->attalign);				if (usecache)					att[i]->attcacheoff = off;			}			off = att_addlength(off, att[i]->attlen, tp + off);			if (usecache && att[i]->attlen <= 0)				usecache = false;		}		off = att_align(off, att[attnum]->attalign);		return fetchatt(att[attnum], tp + off);	}}/* ---------------- *		heap_getsysattr * *		Fetch the value of a system attribute for a tuple. * * This is a support routine for the heap_getattr macro.  The macro * has already determined that the attnum refers to a system attribute. * ---------------- */Datumheap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull){	Datum		result;	Assert(tup);	/* Currently, no sys attribute ever reads as NULL. */	if (isnull)		*isnull = false;	switch (attnum)	{		case SelfItemPointerAttributeNumber:			/* pass-by-reference datatype */			result = PointerGetDatum(&(tup->t_self));			break;		case ObjectIdAttributeNumber:			result = ObjectIdGetDatum(HeapTupleGetOid(tup));			break;		case MinTransactionIdAttributeNumber:			result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));			break;		case MinCommandIdAttributeNumber:			result = CommandIdGetDatum(HeapTupleHeaderGetCmin(tup->t_data));			break;		case MaxTransactionIdAttributeNumber:			result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));			break;		case MaxCommandIdAttributeNumber:			result = CommandIdGetDatum(HeapTupleHeaderGetCmax(tup->t_data));			break;		case TableOidAttributeNumber:			result = ObjectIdGetDatum(tup->t_tableOid);			break;		default:			elog(ERROR, "invalid attnum: %d", attnum);			result = 0;			/* keep compiler quiet */			break;	}	return result;}/* ---------------- *		heap_copytuple * *		returns a copy of an entire tuple * * The HeapTuple struct, tuple header, and tuple data are all allocated * as a single palloc() block. * ---------------- */HeapTupleheap_copytuple(HeapTuple tuple){	HeapTuple	newTuple;	if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)		return NULL;	newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);	newTuple->t_len = tuple->t_len;	newTuple->t_self = tuple->t_self;	newTuple->t_tableOid = tuple->t_tableOid;	newTuple->t_datamcxt = CurrentMemoryContext;	newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);	memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);	return newTuple;}/* ---------------- *		heap_copytuple_with_tuple * *		copy a tuple into a caller-supplied HeapTuple management struct * ---------------- */voidheap_copytuple_with_tuple(HeapTuple src, HeapTuple dest){	if (!HeapTupleIsValid(src) || src->t_data == NULL)	{		dest->t_data = NULL;		return;	}	dest->t_len = src->t_len;	dest->t_self = src->t_self;	dest->t_tableOid = src->t_tableOid;	dest->t_datamcxt = CurrentMemoryContext;	dest->t_data = (HeapTupleHeader) palloc(src->t_len);	memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);}/* * heap_form_tuple *		construct a tuple from the given values[] and isnull[] arrays, *		which are of the length indicated by tupleDescriptor->natts * * The result is allocated in the current memory context. */HeapTupleheap_form_tuple(TupleDesc tupleDescriptor,				Datum *values,				bool *isnull){	HeapTuple	tuple;			/* return tuple */	HeapTupleHeader td;			/* tuple data */	unsigned long 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(HeapTupleHeaderData, t_bits);	if (hasnull)		len += BITMAPLEN(numberOfAttributes);	if (tupleDescriptor->tdhasoid)		len += sizeof(Oid);	hoff = len = MAXALIGN(len); /* align user data safely */	len += heap_compute_data_size(tupleDescriptor, values, isnull);	/*	 * Allocate and zero the space needed.	Note that the tuple body and	 * HeapTupleData management structure are allocated in one chunk.	 */	tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);	tuple->t_datamcxt = CurrentMemoryContext;	tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);	/*	 * And fill in the information.  Note we fill the Datum fields even though	 * this tuple may never become a Datum.	 */	tuple->t_len = len;	ItemPointerSetInvalid(&(tuple->t_self));	tuple->t_tableOid = InvalidOid;	HeapTupleHeaderSetDatumLength(td, len);	HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);	HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);	td->t_natts = numberOfAttributes;	td->t_hoff = hoff;	if (tupleDescriptor->tdhasoid)		/* else leave infomask = 0 */		td->t_infomask = HEAP_HASOID;	heap_fill_tuple(tupleDescriptor,					values,					isnull,					(char *) td + hoff,					&td->t_infomask,					(hasnull ? td->t_bits : NULL));	return tuple;}/* ---------------- *		heap_formtuple * *		construct a tuple from the given values[] and nulls[] arrays * *		Null attributes are indicated by a 'n' in the appropriate byte *		of nulls[]. Non-null attributes are indicated by a ' ' (space). * * OLD API with char 'n'/' ' convention for indicating nulls * ---------------- */HeapTupleheap_formtuple(TupleDesc tupleDescriptor,			   Datum *values,			   char *nulls){	HeapTuple	tuple;			/* return tuple */	HeapTupleHeader td;			/* tuple data */	unsigned long 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 (nulls[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(HeapTupleHeaderData, t_bits);	if (hasnull)		len += BITMAPLEN(numberOfAttributes);	if (tupleDescriptor->tdhasoid)		len += sizeof(Oid);	hoff = len = MAXALIGN(len); /* align user data safely */	len += ComputeDataSize(tupleDescriptor, values, nulls);	/*	 * Allocate and zero the space needed.	Note that the tuple body and	 * HeapTupleData management structure are allocated in one chunk.	 */	tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);	tuple->t_datamcxt = CurrentMemoryContext;	tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);	/*	 * And fill in the information.  Note we fill the Datum fields even though	 * this tuple may never become a Datum.	 */	tuple->t_len = len;	ItemPointerSetInvalid(&(tuple->t_self));	tuple->t_tableOid = InvalidOid;	HeapTupleHeaderSetDatumLength(td, len);	HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);	HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);	td->t_natts = numberOfAttributes;	td->t_hoff = hoff;	if (tupleDescriptor->tdhasoid)		/* else leave infomask = 0 */		td->t_infomask = HEAP_HASOID;	DataFill((char *) td + hoff,			 tupleDescriptor,			 values,			 nulls,			 &td->t_infomask,			 (hasnull ? td->t_bits : NULL));	return tuple;}/* * heap_modify_tuple *		form a new tuple from an old tuple and a set of replacement values. * * The replValues, replIsnull, and doReplace arrays must be of the length * indicated by tupleDesc->natts.  The new tuple is constructed using the data * from replValues/replIsnull at columns where doReplace is true, and using * the data from the old tuple at columns where doReplace is false. * * The result is allocated in the current memory context. */HeapTupleheap_modify_tuple(HeapTuple tuple,				  TupleDesc tupleDesc,				  Datum *replValues,				  bool *replIsnull,				  bool *doReplace){	int			numberOfAttributes = tupleDesc->natts;	int			attoff;	Datum	   *values;	bool	   *isnull;	HeapTuple	newTuple;	/*	 * allocate and fill values and isnull arrays from either the tuple or the	 * repl information, as appropriate.	 *	 * NOTE: it's debatable whether to use heap_deform_tuple() here or just	 * heap_getattr() only the non-replaced colums.  The latter could win if	 * there are many replaced columns and few non-replaced ones. However,	 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost	 * O(N^2) if there are many non-replaced columns, so it seems better to	 * err on the side of linear cost.	 */	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));	heap_deform_tuple(tuple, tupleDesc, values, isnull);	for (attoff = 0; attoff < numberOfAttributes; attoff++)	{		if (doReplace[attoff])		{			values[attoff] = replValues[attoff];			isnull[attoff] = replIsnull[attoff];		}	}	/*	 * create a new tuple from the values and isnull arrays	 */	newTuple = heap_form_tuple(tupleDesc, values, isnull);	pfree(values);	pfree(isnull);	/*	 * copy the identification info of the old tuple: t_ctid, t_self, and OID	 * (if any)	 */	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;	newTuple->t_self = tuple->t_self;	newTuple->t_tableOid = tuple->t_tableOid;	if (tupleDesc->tdhasoid)		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));	return newTuple;}/* ---------------- *		heap_modifytuple * *		forms a new tuple from an old tuple and a set of replacement values. *		returns a new palloc'ed tuple. * * OLD API with char 'n'/' ' convention for indicating nulls, and * char 'r'/' ' convention for indicating whether to replace columns. * ---------------- */HeapTupleheap_modifytuple(HeapTuple tuple,				 TupleDesc tupleDesc,				 Datum *replValues,				 char *replNulls,				 char *replActions){	int			numberOfAttributes = tupleDesc->natts;	int			attoff;	Datum	   *values;	char	   *nulls;	HeapTuple	newTuple;	/*	 * allocate and fill values and nulls arrays from either the tuple or the	 * repl information, as appropriate.	 *	 * NOTE: it's debatable whether to use heap_deformtuple() here or just	 * heap_getattr() only the non-replaced colums.  The latter could win if	 * there are many replaced columns and few non-replaced ones. However,	 * heap_deformtuple costs only O(N) while the heap_getattr way would cost	 * O(N^2) if there are many non-replaced columns, so it seems better to	 * err on the side of linear cost.	 */	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));	nulls = (char *) palloc(numberOfAttributes * sizeof(char));	heap_deformtuple(tuple, tupleDesc, values, nulls);	for (attoff = 0; attoff < numberOfAttributes; attoff++)	{		if (replActions[attoff] == 'r')		{			values[attoff] = replValues[attoff];			nulls[attoff] = replNulls[attoff];		}		else if (replActions[attoff] != ' ')			elog(ERROR, "unrecognized replace flag: %d",				 (int) replActions[attoff]);	}	/*	 * create a new tuple from the values and nulls arrays	 */	newTuple = heap_formtuple(tupleDesc, values, nulls);	pfree(values);	pfree(nulls);	/*	 * copy the identification info of the old tuple: t_ctid, t_self, and OID	 * (if any)	 */	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;	newTuple->t_self = tuple->t_self;	newTuple->t_tableOid = tuple->t_tableOid;	if (tupleDesc->tdhasoid)		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));	return newTuple;}/* * heap_deform_tuple *		Given a tuple, extract data into values/isnull arrays; this is *		the inverse of heap_form_tuple. * *		Storage for the values/isnull 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. */voidheap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,				  Datum *values, bool *isnull){	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++)	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -