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

📄 heaptuple.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * heaptuple.c *	  This file contains heap tuple accessor and mutator routines, as well *	  as various tuple utilities. * * NOTE: there is massive duplication of code in this module to * support both the convention that a null is marked by a bool TRUE, * and the convention that a null is marked by a char 'n'.	The latter * convention is deprecated but it'll probably be a long time before * we can get rid of it entirely. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.102.2.1 2005/11/22 18:23:03 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "access/tuptoaster.h"#include "catalog/pg_type.h"#include "executor/tuptable.h"/* ---------------------------------------------------------------- *						misc support routines * ---------------------------------------------------------------- *//* * heap_compute_data_size *		Determine size of the data area of a tuple to be constructed */Sizeheap_compute_data_size(TupleDesc tupleDesc,					   Datum *values,					   bool *isnull){	Size		data_length = 0;	int			i;	int			numberOfAttributes = tupleDesc->natts;	Form_pg_attribute *att = tupleDesc->attrs;	for (i = 0; i < numberOfAttributes; i++)	{		if (isnull[i])			continue;		data_length = att_align(data_length, att[i]->attalign);		data_length = att_addlength(data_length, att[i]->attlen, values[i]);	}	return data_length;}/* ---------------- *		ComputeDataSize * * Determine size of the data area of a tuple to be constructed * * OLD API with char 'n'/' ' convention for indicating nulls * ---------------- */static SizeComputeDataSize(TupleDesc tupleDesc,				Datum *values,				char *nulls){	Size		data_length = 0;	int			i;	int			numberOfAttributes = tupleDesc->natts;	Form_pg_attribute *att = tupleDesc->attrs;	for (i = 0; i < numberOfAttributes; i++)	{		if (nulls[i] != ' ')			continue;		data_length = att_align(data_length, att[i]->attalign);		data_length = att_addlength(data_length, att[i]->attlen, values[i]);	}	return data_length;}/* * heap_fill_tuple *		Load data portion of a tuple from values/isnull arrays * * We also fill the null bitmap (if any) and set the infomask bits * that reflect the tuple's data contents. */voidheap_fill_tuple(TupleDesc tupleDesc,				Datum *values, bool *isnull,				char *data, uint16 *infomask, bits8 *bit){	bits8	   *bitP;	int			bitmask;	int			i;	int			numberOfAttributes = tupleDesc->natts;	Form_pg_attribute *att = tupleDesc->attrs;	if (bit != NULL)	{		bitP = &bit[-1];		bitmask = CSIGNBIT;	}	else	{		/* just to keep compiler quiet */		bitP = NULL;		bitmask = 0;	}	*infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);	for (i = 0; i < numberOfAttributes; i++)	{		Size		data_length;		if (bit != NULL)		{			if (bitmask != CSIGNBIT)				bitmask <<= 1;			else			{				bitP += 1;				*bitP = 0x0;				bitmask = 1;			}			if (isnull[i])			{				*infomask |= HEAP_HASNULL;				continue;			}			*bitP |= bitmask;		}		/* XXX we are aligning the pointer itself, not the offset */		data = (char *) att_align((long) data, att[i]->attalign);		if (att[i]->attbyval)		{			/* pass-by-value */			store_att_byval(data, values[i], att[i]->attlen);			data_length = att[i]->attlen;		}		else if (att[i]->attlen == -1)		{			/* varlena */			*infomask |= HEAP_HASVARWIDTH;			if (VARATT_IS_EXTERNAL(values[i]))				*infomask |= HEAP_HASEXTERNAL;			if (VARATT_IS_COMPRESSED(values[i]))				*infomask |= HEAP_HASCOMPRESSED;			data_length = VARATT_SIZE(DatumGetPointer(values[i]));			memcpy(data, DatumGetPointer(values[i]), data_length);		}		else if (att[i]->attlen == -2)		{			/* cstring */			*infomask |= HEAP_HASVARWIDTH;			data_length = strlen(DatumGetCString(values[i])) + 1;			memcpy(data, DatumGetPointer(values[i]), data_length);		}		else		{			/* fixed-length pass-by-reference */			Assert(att[i]->attlen > 0);			data_length = att[i]->attlen;			memcpy(data, DatumGetPointer(values[i]), data_length);		}		data += data_length;	}}/* ---------------- *		DataFill * * Load data portion of a tuple from values/nulls arrays * * OLD API with char 'n'/' ' convention for indicating nulls * ---------------- */static voidDataFill(char *data,		 TupleDesc tupleDesc,		 Datum *values,		 char *nulls,		 uint16 *infomask,		 bits8 *bit){	bits8	   *bitP;	int			bitmask;	int			i;	int			numberOfAttributes = tupleDesc->natts;	Form_pg_attribute *att = tupleDesc->attrs;	if (bit != NULL)	{		bitP = &bit[-1];		bitmask = CSIGNBIT;	}	else	{		/* just to keep compiler quiet */		bitP = NULL;		bitmask = 0;	}	*infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);	for (i = 0; i < numberOfAttributes; i++)	{		Size		data_length;		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;		}		/* XXX we are aligning the pointer itself, not the offset */		data = (char *) att_align((long) data, att[i]->attalign);		if (att[i]->attbyval)		{			/* pass-by-value */			store_att_byval(data, values[i], att[i]->attlen);			data_length = att[i]->attlen;		}		else if (att[i]->attlen == -1)		{			/* varlena */			*infomask |= HEAP_HASVARWIDTH;			if (VARATT_IS_EXTERNAL(values[i]))				*infomask |= HEAP_HASEXTERNAL;			if (VARATT_IS_COMPRESSED(values[i]))				*infomask |= HEAP_HASCOMPRESSED;			data_length = VARATT_SIZE(DatumGetPointer(values[i]));			memcpy(data, DatumGetPointer(values[i]), data_length);		}		else if (att[i]->attlen == -2)		{			/* cstring */			*infomask |= HEAP_HASVARWIDTH;			data_length = strlen(DatumGetCString(values[i])) + 1;			memcpy(data, DatumGetPointer(values[i]), data_length);		}		else		{			/* fixed-length pass-by-reference */			Assert(att[i]->attlen > 0);			data_length = att[i]->attlen;			memcpy(data, DatumGetPointer(values[i]), data_length);		}		data += data_length;	}}/* ---------------------------------------------------------------- *						heap tuple interface * ---------------------------------------------------------------- *//* ---------------- *		heap_attisnull	- returns TRUE iff tuple attribute is not present * ---------------- */boolheap_attisnull(HeapTuple tup, int attnum){	if (attnum > (int) tup->t_data->t_natts)		return true;	if (attnum > 0)	{		if (HeapTupleNoNulls(tup))			return false;		return att_isnull(attnum - 1, tup->t_data->t_bits);	}	switch (attnum)	{		case TableOidAttributeNumber:		case SelfItemPointerAttributeNumber:		case ObjectIdAttributeNumber:		case MinTransactionIdAttributeNumber:		case MinCommandIdAttributeNumber:		case MaxTransactionIdAttributeNumber:		case MaxCommandIdAttributeNumber:			/* these are never null */			break;		default:			elog(ERROR, "invalid attnum: %d", attnum);	}	return false;}/* ---------------- *		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 * *		NOTE: if you need to change this code, see also heap_deform_tuple. * ---------------- */Datumnocachegetattr(HeapTuple tuple,			   int attnum,			   TupleDesc tupleDesc,			   bool *isnull){	HeapTupleHeader tup = tuple->t_data;	Form_pg_attribute *att = tupleDesc->attrs;	char	   *tp;				/* ptr to att in tuple */	bits8	   *bp = tup->t_bits;		/* ptr to null bitmap in tuple */	bool		slow = false;	/* do we have to walk nulls? */	(void) isnull;				/* not used */#ifdef 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-width attributes.	 *	 2: Has a null or a var-width AFTER att.	 *	 3: Has nulls or var-widths BEFORE att.	 * ----------------	 */	if (HeapTupleNoNulls(tuple))	{#ifdef IN_MACRO/* This is handled in the macro */		if (att[attnum]->attcacheoff != -1)		{			return fetchatt(att[attnum],							(char *) tup + tup->t_hoff +							att[attnum]->attcacheoff);		}#endif	}	else	{		/*		 * there's a null somewhere in the tuple		 *		 * check to see if desired att is null		 */#ifdef 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 = true;			else			{				/* check for nulls in any "earlier" bytes */				int			i;				for (i = 0; i < byte; i++)				{					if (bp[i] != 0xFF)					{						slow = true;						break;					}				}			}		}	}	tp = (char *) tup + tup->t_hoff;	/*	 * now check for any non-fixed length attrs before our attribute	 */	if (!slow)	{		if (att[attnum]->attcacheoff != -1)		{			return fetchatt(att[attnum],							tp + att[attnum]->attcacheoff);		}		else if (HeapTupleHasVarWidth(tuple))		{			int			j;			/*			 * In for(), we test <= and not < because we want to see if we can			 * go past it in initializing offsets.			 */			for (j = 0; j <= attnum; j++)			{				if (att[j]->attlen <= 0)				{					slow = true;					break;				}			}		}	}	/*	 * If slow is false, and we got here, we know that we have a tuple with no	 * nulls or var-widths before the target attribute. If possible, we also	 * want to initialize the remainder of the attribute cached offset values.	 */	if (!slow)	{		int			j = 1;		long		off;		/*		 * need to set cache for some atts		 */		att[0]->attcacheoff = 0;		while (j < attnum && att[j]->attcacheoff > 0)			j++;		off = att[j - 1]->attcacheoff + att[j - 1]->attlen;		for (; j <= attnum ||		/* Can we compute more?  We will probably need them */			 (j < tup->t_natts &&			  att[j]->attcacheoff == -1 &&			  (HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) &&			  (HeapTupleAllFixed(tuple) || att[j]->attlen > 0)); j++)		{			off = att_align(off, att[j]->attalign);			att[j]->attcacheoff = off;			off = att_addlength(off, att[j]->attlen, tp + off);		}		return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);	}	else	{		bool		usecache = true;		int			off = 0;		int			i;		/*		 * Now we know that we have to walk the tuple CAREFULLY.		 *		 * Note - This loop is a little tricky.  For each non-null attribute,		 * we have to first account for alignment padding before the attr,		 * then advance over the attr based on its length.	Nulls have no		 * storage and no alignment padding either.  We can use/set		 * attcacheoff until we pass either a null or a var-width attribute.		 */		for (i = 0; i < attnum; i++)		{			if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))			{				usecache = false;				continue;

⌨️ 快捷键说明

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