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

📄 inv_api.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
	ScanKeyInit(&skey[1],				Anum_pg_largeobject_pageno,				BTGreaterEqualStrategyNumber, F_INT4GE,				Int32GetDatum(pageno));	sd = index_beginscan(lo_heap_r, lo_index_r,						 obj_desc->snapshot, 2, skey);	while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)	{		Form_pg_largeobject data;		bytea	   *datafield;		bool		pfreeit;		if (HeapTupleHasNulls(tuple))	/* paranoia */			elog(ERROR, "null field found in pg_largeobject");		data = (Form_pg_largeobject) GETSTRUCT(tuple);		/*		 * We assume the indexscan will deliver pages in order.  However,		 * there may be missing pages if the LO contains unwritten "holes". We		 * want missing sections to read out as zeroes.		 */		pageoff = ((uint32) data->pageno) * LOBLKSIZE;		if (pageoff > obj_desc->offset)		{			n = pageoff - obj_desc->offset;			n = (n <= (nbytes - nread)) ? n : (nbytes - nread);			MemSet(buf + nread, 0, n);			nread += n;			obj_desc->offset += n;		}		if (nread < nbytes)		{			Assert(obj_desc->offset >= pageoff);			off = (int) (obj_desc->offset - pageoff);			Assert(off >= 0 && off < LOBLKSIZE);			datafield = &(data->data);	/* see note at top of file */			pfreeit = false;			if (VARATT_IS_EXTENDED(datafield))			{				datafield = (bytea *)					heap_tuple_untoast_attr((struct varlena *) datafield);				pfreeit = true;			}			len = getbytealen(datafield);			if (len > off)			{				n = len - off;				n = (n <= (nbytes - nread)) ? n : (nbytes - nread);				memcpy(buf + nread, VARDATA(datafield) + off, n);				nread += n;				obj_desc->offset += n;			}			if (pfreeit)				pfree(datafield);		}		if (nread >= nbytes)			break;	}	index_endscan(sd);	return nread;}intinv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes){	int			nwritten = 0;	int			n;	int			off;	int			len;	int32		pageno = (int32) (obj_desc->offset / LOBLKSIZE);	ScanKeyData skey[2];	IndexScanDesc sd;	HeapTuple	oldtuple;	Form_pg_largeobject olddata;	bool		neednextpage;	bytea	   *datafield;	bool		pfreeit;	struct	{		bytea		hdr;		char		data[LOBLKSIZE];	/* make struct big enough */		int32		align_it;	/* ensure struct is aligned well enough */	}			workbuf;	char	   *workb = VARDATA(&workbuf.hdr);	HeapTuple	newtup;	Datum		values[Natts_pg_largeobject];	char		nulls[Natts_pg_largeobject];	char		replace[Natts_pg_largeobject];	CatalogIndexState indstate;	Assert(PointerIsValid(obj_desc));	Assert(buf != NULL);	/* enforce writability because snapshot is probably wrong otherwise */	if ((obj_desc->flags & IFS_WRLOCK) == 0)		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("large object %u was not opened for writing",						obj_desc->id)));	if (nbytes <= 0)		return 0;	open_lo_relation();	indstate = CatalogOpenIndexes(lo_heap_r);	ScanKeyInit(&skey[0],				Anum_pg_largeobject_loid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(obj_desc->id));	ScanKeyInit(&skey[1],				Anum_pg_largeobject_pageno,				BTGreaterEqualStrategyNumber, F_INT4GE,				Int32GetDatum(pageno));	sd = index_beginscan(lo_heap_r, lo_index_r,						 obj_desc->snapshot, 2, skey);	oldtuple = NULL;	olddata = NULL;	neednextpage = true;	while (nwritten < nbytes)	{		/*		 * If possible, get next pre-existing page of the LO.  We assume the		 * indexscan will deliver these in order --- but there may be holes.		 */		if (neednextpage)		{			if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)			{				if (HeapTupleHasNulls(oldtuple))		/* paranoia */					elog(ERROR, "null field found in pg_largeobject");				olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);				Assert(olddata->pageno >= pageno);			}			neednextpage = false;		}		/*		 * If we have a pre-existing page, see if it is the page we want to		 * write, or a later one.		 */		if (olddata != NULL && olddata->pageno == pageno)		{			/*			 * Update an existing page with fresh data.			 *			 * First, load old data into workbuf			 */			datafield = &(olddata->data);		/* see note at top of file */			pfreeit = false;			if (VARATT_IS_EXTENDED(datafield))			{				datafield = (bytea *)					heap_tuple_untoast_attr((struct varlena *) datafield);				pfreeit = true;			}			len = getbytealen(datafield);			Assert(len <= LOBLKSIZE);			memcpy(workb, VARDATA(datafield), len);			if (pfreeit)				pfree(datafield);			/*			 * Fill any hole			 */			off = (int) (obj_desc->offset % LOBLKSIZE);			if (off > len)				MemSet(workb + len, 0, off - len);			/*			 * Insert appropriate portion of new data			 */			n = LOBLKSIZE - off;			n = (n <= (nbytes - nwritten)) ? n : (nbytes - nwritten);			memcpy(workb + off, buf + nwritten, n);			nwritten += n;			obj_desc->offset += n;			off += n;			/* compute valid length of new page */			len = (len >= off) ? len : off;			SET_VARSIZE(&workbuf.hdr, len + VARHDRSZ);			/*			 * Form and insert updated tuple			 */			memset(values, 0, sizeof(values));			memset(nulls, ' ', sizeof(nulls));			memset(replace, ' ', sizeof(replace));			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);			replace[Anum_pg_largeobject_data - 1] = 'r';			newtup = heap_modifytuple(oldtuple, RelationGetDescr(lo_heap_r),									  values, nulls, replace);			simple_heap_update(lo_heap_r, &newtup->t_self, newtup);			CatalogIndexInsert(indstate, newtup);			heap_freetuple(newtup);			/*			 * We're done with this old page.			 */			oldtuple = NULL;			olddata = NULL;			neednextpage = true;		}		else		{			/*			 * Write a brand new page.			 *			 * First, fill any hole			 */			off = (int) (obj_desc->offset % LOBLKSIZE);			if (off > 0)				MemSet(workb, 0, off);			/*			 * Insert appropriate portion of new data			 */			n = LOBLKSIZE - off;			n = (n <= (nbytes - nwritten)) ? n : (nbytes - nwritten);			memcpy(workb + off, buf + nwritten, n);			nwritten += n;			obj_desc->offset += n;			/* compute valid length of new page */			len = off + n;			SET_VARSIZE(&workbuf.hdr, len + VARHDRSZ);			/*			 * Form and insert updated tuple			 */			memset(values, 0, sizeof(values));			memset(nulls, ' ', sizeof(nulls));			values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);			values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);			newtup = heap_formtuple(lo_heap_r->rd_att, values, nulls);			simple_heap_insert(lo_heap_r, newtup);			CatalogIndexInsert(indstate, newtup);			heap_freetuple(newtup);		}		pageno++;	}	index_endscan(sd);	CatalogCloseIndexes(indstate);	/*	 * Advance command counter so that my tuple updates will be seen by later	 * large-object operations in this transaction.	 */	CommandCounterIncrement();	return nwritten;}voidinv_truncate(LargeObjectDesc *obj_desc, int len){	int32		pageno = (int32) (len / LOBLKSIZE);	int			off;	ScanKeyData skey[2];	IndexScanDesc sd;	HeapTuple	oldtuple;	Form_pg_largeobject olddata;	struct	{		bytea		hdr;		char		data[LOBLKSIZE];	/* make struct big enough */		int32		align_it;	/* ensure struct is aligned well enough */	}			workbuf;	char	   *workb = VARDATA(&workbuf.hdr);	HeapTuple	newtup;	Datum		values[Natts_pg_largeobject];	char		nulls[Natts_pg_largeobject];	char		replace[Natts_pg_largeobject];	CatalogIndexState indstate;	Assert(PointerIsValid(obj_desc));	/* enforce writability because snapshot is probably wrong otherwise */	if ((obj_desc->flags & IFS_WRLOCK) == 0)		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("large object %u was not opened for writing",						obj_desc->id)));	open_lo_relation();	indstate = CatalogOpenIndexes(lo_heap_r);	ScanKeyInit(&skey[0],				Anum_pg_largeobject_loid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(obj_desc->id));	ScanKeyInit(&skey[1],				Anum_pg_largeobject_pageno,				BTGreaterEqualStrategyNumber, F_INT4GE,				Int32GetDatum(pageno));	sd = index_beginscan(lo_heap_r, lo_index_r,						 obj_desc->snapshot, 2, skey);	/*	 * If possible, get the page the truncation point is in. The truncation	 * point may be beyond the end of the LO or in a hole.	 */	olddata = NULL;	if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)	{		if (HeapTupleHasNulls(oldtuple))		/* paranoia */			elog(ERROR, "null field found in pg_largeobject");		olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);		Assert(olddata->pageno >= pageno);	}	/*	 * If we found the page of the truncation point we need to truncate the	 * data in it.	Otherwise if we're in a hole, we need to create a page to	 * mark the end of data.	 */	if (olddata != NULL && olddata->pageno == pageno)	{		/* First, load old data into workbuf */		bytea	   *datafield = &(olddata->data);		/* see note at top of														 * file */		bool		pfreeit = false;		int			pagelen;		if (VARATT_IS_EXTENDED(datafield))		{			datafield = (bytea *)				heap_tuple_untoast_attr((struct varlena *) datafield);			pfreeit = true;		}		pagelen = getbytealen(datafield);		Assert(pagelen <= LOBLKSIZE);		memcpy(workb, VARDATA(datafield), pagelen);		if (pfreeit)			pfree(datafield);		/*		 * Fill any hole		 */		off = len % LOBLKSIZE;		if (off > pagelen)			MemSet(workb + pagelen, 0, off - pagelen);		/* compute length of new page */		SET_VARSIZE(&workbuf.hdr, off + VARHDRSZ);		/*		 * Form and insert updated tuple		 */		memset(values, 0, sizeof(values));		memset(nulls, ' ', sizeof(nulls));		memset(replace, ' ', sizeof(replace));		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);		replace[Anum_pg_largeobject_data - 1] = 'r';		newtup = heap_modifytuple(oldtuple, RelationGetDescr(lo_heap_r),								  values, nulls, replace);		simple_heap_update(lo_heap_r, &newtup->t_self, newtup);		CatalogIndexInsert(indstate, newtup);		heap_freetuple(newtup);	}	else	{		/*		 * If the first page we found was after the truncation point, we're in		 * a hole that we'll fill, but we need to delete the later page.		 */		if (olddata != NULL && olddata->pageno > pageno)			simple_heap_delete(lo_heap_r, &oldtuple->t_self);		/*		 * Write a brand new page.		 *		 * Fill the hole up to the truncation point		 */		off = len % LOBLKSIZE;		if (off > 0)			MemSet(workb, 0, off);		/* compute length of new page */		SET_VARSIZE(&workbuf.hdr, off + VARHDRSZ);		/*		 * Form and insert new tuple		 */		memset(values, 0, sizeof(values));		memset(nulls, ' ', sizeof(nulls));		values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);		values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);		newtup = heap_formtuple(lo_heap_r->rd_att, values, nulls);		simple_heap_insert(lo_heap_r, newtup);		CatalogIndexInsert(indstate, newtup);		heap_freetuple(newtup);	}	/*	 * Delete any pages after the truncation point	 */	while ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)	{		simple_heap_delete(lo_heap_r, &oldtuple->t_self);	}	index_endscan(sd);	CatalogCloseIndexes(indstate);	/*	 * Advance command counter so that tuple updates will be seen by later	 * large-object operations in this transaction.	 */	CommandCounterIncrement();}

⌨️ 快捷键说明

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