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

📄 tuptoaster.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
			}			/*			 * Remember the size of this attribute			 */			toast_sizes[i] = VARATT_SIZE(new_value);		}		else		{			/*			 * Not a varlena attribute, plain storage always			 */			toast_action[i] = 'p';		}	}	/* ----------	 * Compress and/or save external until data fits into target length	 *	 *	1: Inline compress attributes with attstorage 'x'	 *	2: Store attributes with attstorage 'x' or 'e' external	 *	3: Inline compress attributes with attstorage 'm'	 *	4: Store attributes with attstorage 'm' external	 * ----------	 */	maxDataLen = offsetof(HeapTupleHeaderData, t_bits);	if (has_nulls)		maxDataLen += BITMAPLEN(numAttrs);	maxDataLen = TOAST_TUPLE_TARGET - MAXALIGN(maxDataLen);	/*	 * Look for attributes with attstorage 'x' to compress	 */	while (MAXALIGN(heap_compute_data_size(tupleDesc,										   toast_values, toast_isnull)) >		   maxDataLen)	{		int			biggest_attno = -1;		int32		biggest_size = MAXALIGN(sizeof(varattrib));		Datum		old_value;		Datum		new_value;		/*		 * Search for the biggest yet uncompressed internal attribute		 */		for (i = 0; i < numAttrs; i++)		{			if (toast_action[i] != ' ')				continue;			if (VARATT_IS_EXTENDED(toast_values[i]))				continue;			if (att[i]->attstorage != 'x')				continue;			if (toast_sizes[i] > biggest_size)			{				biggest_attno = i;				biggest_size = toast_sizes[i];			}		}		if (biggest_attno < 0)			break;		/*		 * Attempt to compress it inline		 */		i = biggest_attno;		old_value = toast_values[i];		new_value = toast_compress_datum(old_value);		if (DatumGetPointer(new_value) != NULL)		{			/* successful compression */			if (toast_free[i])				pfree(DatumGetPointer(old_value));			toast_values[i] = new_value;			toast_free[i] = true;			toast_sizes[i] = VARATT_SIZE(toast_values[i]);			need_change = true;			need_free = true;		}		else		{			/*			 * incompressible data, ignore on subsequent compression passes			 */			toast_action[i] = 'x';		}	}	/*	 * Second we look for attributes of attstorage 'x' or 'e' that are still	 * inline.	 */	while (MAXALIGN(heap_compute_data_size(tupleDesc,										   toast_values, toast_isnull)) >		   maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)	{		int			biggest_attno = -1;		int32		biggest_size = MAXALIGN(sizeof(varattrib));		Datum		old_value;		/*------		 * Search for the biggest yet inlined attribute with		 * attstorage equals 'x' or 'e'		 *------		 */		for (i = 0; i < numAttrs; i++)		{			if (toast_action[i] == 'p')				continue;			if (VARATT_IS_EXTERNAL(toast_values[i]))				continue;			if (att[i]->attstorage != 'x' && att[i]->attstorage != 'e')				continue;			if (toast_sizes[i] > biggest_size)			{				biggest_attno = i;				biggest_size = toast_sizes[i];			}		}		if (biggest_attno < 0)			break;		/*		 * Store this external		 */		i = biggest_attno;		old_value = toast_values[i];		toast_action[i] = 'p';		toast_values[i] = toast_save_datum(rel, toast_values[i]);		if (toast_free[i])			pfree(DatumGetPointer(old_value));		toast_free[i] = true;		toast_sizes[i] = VARATT_SIZE(toast_values[i]);		need_change = true;		need_free = true;	}	/*	 * Round 3 - this time we take attributes with storage 'm' into	 * compression	 */	while (MAXALIGN(heap_compute_data_size(tupleDesc,										   toast_values, toast_isnull)) >		   maxDataLen)	{		int			biggest_attno = -1;		int32		biggest_size = MAXALIGN(sizeof(varattrib));		Datum		old_value;		Datum		new_value;		/*		 * Search for the biggest yet uncompressed internal attribute		 */		for (i = 0; i < numAttrs; i++)		{			if (toast_action[i] != ' ')				continue;			if (VARATT_IS_EXTENDED(toast_values[i]))				continue;			if (att[i]->attstorage != 'm')				continue;			if (toast_sizes[i] > biggest_size)			{				biggest_attno = i;				biggest_size = toast_sizes[i];			}		}		if (biggest_attno < 0)			break;		/*		 * Attempt to compress it inline		 */		i = biggest_attno;		old_value = toast_values[i];		new_value = toast_compress_datum(old_value);		if (DatumGetPointer(new_value) != NULL)		{			/* successful compression */			if (toast_free[i])				pfree(DatumGetPointer(old_value));			toast_values[i] = new_value;			toast_free[i] = true;			toast_sizes[i] = VARATT_SIZE(toast_values[i]);			need_change = true;			need_free = true;		}		else		{			/*			 * incompressible data, ignore on subsequent compression passes			 */			toast_action[i] = 'x';		}	}	/*	 * Finally we store attributes of type 'm' external	 */	while (MAXALIGN(heap_compute_data_size(tupleDesc,										   toast_values, toast_isnull)) >		   maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)	{		int			biggest_attno = -1;		int32		biggest_size = MAXALIGN(sizeof(varattrib));		Datum		old_value;		/*--------		 * Search for the biggest yet inlined attribute with		 * attstorage = 'm'		 *--------		 */		for (i = 0; i < numAttrs; i++)		{			if (toast_action[i] == 'p')				continue;			if (VARATT_IS_EXTERNAL(toast_values[i]))				continue;			if (att[i]->attstorage != 'm')				continue;			if (toast_sizes[i] > biggest_size)			{				biggest_attno = i;				biggest_size = toast_sizes[i];			}		}		if (biggest_attno < 0)			break;		/*		 * Store this external		 */		i = biggest_attno;		old_value = toast_values[i];		toast_action[i] = 'p';		toast_values[i] = toast_save_datum(rel, toast_values[i]);		if (toast_free[i])			pfree(DatumGetPointer(old_value));		toast_free[i] = true;		toast_sizes[i] = VARATT_SIZE(toast_values[i]);		need_change = true;		need_free = true;	}	/*	 * In the case we toasted any values, we need to build a new heap tuple	 * with the changed values.	 */	if (need_change)	{		HeapTupleHeader olddata = newtup->t_data;		HeapTupleHeader new_data;		int32		new_len;		/*		 * Calculate the new size of the tuple.  Header size should not		 * change, but data size might.		 */		new_len = offsetof(HeapTupleHeaderData, t_bits);		if (has_nulls)			new_len += BITMAPLEN(numAttrs);		if (olddata->t_infomask & HEAP_HASOID)			new_len += sizeof(Oid);		new_len = MAXALIGN(new_len);		Assert(new_len == olddata->t_hoff);		new_len += heap_compute_data_size(tupleDesc,										  toast_values, toast_isnull);		/*		 * Allocate and zero the space needed, and fill HeapTupleData fields.		 */		result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_len);		result_tuple->t_len = new_len;		result_tuple->t_self = newtup->t_self;		result_tuple->t_tableOid = newtup->t_tableOid;		result_tuple->t_datamcxt = CurrentMemoryContext;		new_data = (HeapTupleHeader) ((char *) result_tuple + HEAPTUPLESIZE);		result_tuple->t_data = new_data;		/*		 * Put the existing tuple header and the changed values into place		 */		memcpy(new_data, olddata, olddata->t_hoff);		heap_fill_tuple(tupleDesc,						toast_values,						toast_isnull,						(char *) new_data + olddata->t_hoff,						&(new_data->t_infomask),						has_nulls ? new_data->t_bits : NULL);	}	else		result_tuple = newtup;	/*	 * Free allocated temp values	 */	if (need_free)		for (i = 0; i < numAttrs; i++)			if (toast_free[i])				pfree(DatumGetPointer(toast_values[i]));	/*	 * Delete external values from the old tuple	 */	if (need_delold)		for (i = 0; i < numAttrs; i++)			if (toast_delold[i])				toast_delete_datum(rel, toast_oldvalues[i]);	return result_tuple;}/* ---------- * toast_flatten_tuple_attribute - * *	If a Datum is of composite type, "flatten" it to contain no toasted fields. *	This must be invoked on any potentially-composite field that is to be *	inserted into a tuple.	Doing this preserves the invariant that toasting *	goes only one level deep in a tuple. * ---------- */Datumtoast_flatten_tuple_attribute(Datum value,							  Oid typeId, int32 typeMod){	TupleDesc	tupleDesc;	HeapTupleHeader olddata;	HeapTupleHeader new_data;	int32		new_len;	HeapTupleData tmptup;	Form_pg_attribute *att;	int			numAttrs;	int			i;	bool		need_change = false;	bool		has_nulls = false;	Datum		toast_values[MaxTupleAttributeNumber];	bool		toast_isnull[MaxTupleAttributeNumber];	bool		toast_free[MaxTupleAttributeNumber];	/*	 * See if it's a composite type, and get the tupdesc if so.	 */	tupleDesc = lookup_rowtype_tupdesc_noerror(typeId, typeMod, true);	if (tupleDesc == NULL)		return value;			/* not a composite type */	tupleDesc = CreateTupleDescCopy(tupleDesc);	att = tupleDesc->attrs;	numAttrs = tupleDesc->natts;	/*	 * Break down the tuple into fields.	 */	olddata = DatumGetHeapTupleHeader(value);	Assert(typeId == HeapTupleHeaderGetTypeId(olddata));	Assert(typeMod == HeapTupleHeaderGetTypMod(olddata));	/* Build a temporary HeapTuple control structure */	tmptup.t_len = HeapTupleHeaderGetDatumLength(olddata);	ItemPointerSetInvalid(&(tmptup.t_self));	tmptup.t_tableOid = InvalidOid;	tmptup.t_data = olddata;	Assert(numAttrs <= MaxTupleAttributeNumber);	heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);	memset(toast_free, 0, numAttrs * sizeof(bool));	for (i = 0; i < numAttrs; i++)	{		/*		 * Look at non-null varlena attributes		 */		if (toast_isnull[i])			has_nulls = true;		else if (att[i]->attlen == -1)		{			varattrib  *new_value;			new_value = (varattrib *) DatumGetPointer(toast_values[i]);			if (VARATT_IS_EXTENDED(new_value))			{				new_value = heap_tuple_untoast_attr(new_value);				toast_values[i] = PointerGetDatum(new_value);				toast_free[i] = true;				need_change = true;			}		}	}	/*	 * If nothing to untoast, just return the original tuple.	 */	if (!need_change)	{		FreeTupleDesc(tupleDesc);		return value;	}	/*	 * Calculate the new size of the tuple.  Header size should not change,	 * but data size might.	 */	new_len = offsetof(HeapTupleHeaderData, t_bits);	if (has_nulls)		new_len += BITMAPLEN(numAttrs);	if (olddata->t_infomask & HEAP_HASOID)		new_len += sizeof(Oid);	new_len = MAXALIGN(new_len);	Assert(new_len == olddata->t_hoff);	new_len += heap_compute_data_size(tupleDesc, toast_values, toast_isnull);	new_data = (HeapTupleHeader) palloc0(new_len);	/*	 * Put the tuple header and the changed values into place	 */	memcpy(new_data, olddata, olddata->t_hoff);	HeapTupleHeaderSetDatumLength(new_data, new_len);	heap_fill_tuple(tupleDesc,					toast_values,					toast_isnull,					(char *) new_data + olddata->t_hoff,					&(new_data->t_infomask),					has_nulls ? new_data->t_bits : NULL);	/*	 * Free allocated temp values	 */	for (i = 0; i < numAttrs; i++)		if (toast_free[i])			pfree(DatumGetPointer(toast_values[i]));	FreeTupleDesc(tupleDesc);	return PointerGetDatum(new_data);}/* ---------- * toast_compress_datum - * *	Create a compressed version of a varlena datum * *	If we fail (ie, compressed result is actually bigger than original) *	then return NULL.  We must not use compressed data if it'd expand *	the tuple! * ---------- */Datumtoast_compress_datum(Datum value){	varattrib  *tmp;	tmp = (varattrib *) palloc(sizeof(PGLZ_Header) + VARATT_SIZE(value));	pglz_compress(VARATT_DATA(value), VARATT_SIZE(value) - VARHDRSZ,				  (PGLZ_Header *) tmp,				  PGLZ_strategy_default);	if (VARATT_SIZE(tmp) < VARATT_SIZE(value))	{		/* successful compression */		VARATT_SIZEP(tmp) |= VARATT_FLAG_COMPRESSED;		return PointerGetDatum(tmp);	}	else	{		/* incompressible data */		pfree(tmp);		return PointerGetDatum(NULL);	}}/* ---------- * toast_save_datum - * *	Save one single datum into the secondary relation and return *	a varattrib reference for it. * ----------

⌨️ 快捷键说明

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