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

📄 heapam.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (lockmode != NoLock)		LockRelation(r, lockmode);	return r;}/* ---------------- *		conditional_relation_open - open with option not to wait * *		As above, but if nowait is true, then throw an error rather than *		waiting when the lock is not immediately obtainable. * ---------------- */Relationconditional_relation_open(Oid relationId, LOCKMODE lockmode, bool nowait){	Relation	r;	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);	/* The relcache does all the real work... */	r = RelationIdGetRelation(relationId);	if (!RelationIsValid(r))		elog(ERROR, "could not open relation with OID %u", relationId);	if (lockmode != NoLock)	{		if (nowait)		{			if (!ConditionalLockRelation(r, lockmode))				ereport(ERROR,						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),						 errmsg("could not obtain lock on relation \"%s\"",								RelationGetRelationName(r))));		}		else			LockRelation(r, lockmode);	}	return r;}/* ---------------- *		relation_openrv - open any relation specified by a RangeVar * *		As above, but the relation is specified by a RangeVar. * ---------------- */Relationrelation_openrv(const RangeVar *relation, LOCKMODE lockmode){	Oid			relOid;	/*	 * Check for shared-cache-inval messages before trying to open the	 * relation.  This is needed to cover the case where the name identifies a	 * rel that has been dropped and recreated since the start of our	 * transaction: if we don't flush the old syscache entry then we'll latch	 * onto that entry and suffer an error when we do LockRelation. Note that	 * relation_open does not need to do this, since a relation's OID never	 * changes.	 *	 * We skip this if asked for NoLock, on the assumption that the caller has	 * already ensured some appropriate lock is held.	 */	if (lockmode != NoLock)		AcceptInvalidationMessages();	/* Look up the appropriate relation using namespace search */	relOid = RangeVarGetRelid(relation, false);	/* Let relation_open do the rest */	return relation_open(relOid, lockmode);}/* ---------------- *		relation_close - close any relation * *		If lockmode is not "NoLock", we first release the specified lock. * *		Note that it is often sensible to hold a lock beyond relation_close; *		in that case, the lock is released automatically at xact end. * ---------------- */voidrelation_close(Relation relation, LOCKMODE lockmode){	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);	if (lockmode != NoLock)		UnlockRelation(relation, lockmode);	/* The relcache does the real work... */	RelationClose(relation);}/* ---------------- *		heap_open - open a heap relation by relation OID * *		This is essentially relation_open plus check that the relation *		is not an index or special relation.  (The caller should also check *		that it's not a view before assuming it has storage.) * ---------------- */Relationheap_open(Oid relationId, LOCKMODE lockmode){	Relation	r;	r = relation_open(relationId, lockmode);	if (r->rd_rel->relkind == RELKIND_INDEX)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is an index",						RelationGetRelationName(r))));	else if (r->rd_rel->relkind == RELKIND_SPECIAL)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is a special relation",						RelationGetRelationName(r))));	else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is a composite type",						RelationGetRelationName(r))));	pgstat_initstats(&r->pgstat_info, r);	return r;}/* ---------------- *		heap_openrv - open a heap relation specified *		by a RangeVar node * *		As above, but relation is specified by a RangeVar. * ---------------- */Relationheap_openrv(const RangeVar *relation, LOCKMODE lockmode){	Relation	r;	r = relation_openrv(relation, lockmode);	if (r->rd_rel->relkind == RELKIND_INDEX)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is an index",						RelationGetRelationName(r))));	else if (r->rd_rel->relkind == RELKIND_SPECIAL)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is a special relation",						RelationGetRelationName(r))));	else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is a composite type",						RelationGetRelationName(r))));	pgstat_initstats(&r->pgstat_info, r);	return r;}/* ---------------- *		heap_beginscan	- begin relation scan * ---------------- */HeapScanDescheap_beginscan(Relation relation, Snapshot snapshot,			   int nkeys, ScanKey key){	HeapScanDesc scan;	/*	 * increment relation ref count while scanning relation	 *	 * This is just to make really sure the relcache entry won't go away while	 * the scan has a pointer to it.  Caller should be holding the rel open	 * anyway, so this is redundant in all normal scenarios...	 */	RelationIncrementReferenceCount(relation);	/*	 * allocate and initialize scan descriptor	 */	scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));	scan->rs_rd = relation;	scan->rs_snapshot = snapshot;	scan->rs_nkeys = nkeys;	/*	 * we do this here instead of in initscan() because heap_rescan also calls	 * initscan() and we don't want to allocate memory again	 */	if (nkeys > 0)		scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);	else		scan->rs_key = NULL;	pgstat_initstats(&scan->rs_pgstat_info, relation);	initscan(scan, key);	return scan;}/* ---------------- *		heap_rescan		- restart a relation scan * ---------------- */voidheap_rescan(HeapScanDesc scan,			ScanKey key){	/*	 * unpin scan buffers	 */	if (BufferIsValid(scan->rs_cbuf))		ReleaseBuffer(scan->rs_cbuf);	/*	 * reinitialize scan descriptor	 */	initscan(scan, key);}/* ---------------- *		heap_endscan	- end relation scan * *		See how to integrate with index scans. *		Check handling if reldesc caching. * ---------------- */voidheap_endscan(HeapScanDesc scan){	/* Note: no locking manipulations needed */	/*	 * unpin scan buffers	 */	if (BufferIsValid(scan->rs_cbuf))		ReleaseBuffer(scan->rs_cbuf);	/*	 * decrement relation reference count and free scan descriptor storage	 */	RelationDecrementReferenceCount(scan->rs_rd);	if (scan->rs_key)		pfree(scan->rs_key);	pfree(scan);}/* ---------------- *		heap_getnext	- retrieve next tuple in scan * *		Fix to work with index relations. *		We don't return the buffer anymore, but you can get it from the *		returned HeapTuple. * ---------------- */#ifdef HEAPDEBUGALL#define HEAPDEBUG_1 \	elog(DEBUG2, "heap_getnext([%s,nkeys=%d],dir=%d) called", \		 RelationGetRelationName(scan->rs_rd), scan->rs_nkeys, (int) direction)#define HEAPDEBUG_2 \	elog(DEBUG2, "heap_getnext returning EOS")#define HEAPDEBUG_3 \	elog(DEBUG2, "heap_getnext returning tuple")#else#define HEAPDEBUG_1#define HEAPDEBUG_2#define HEAPDEBUG_3#endif   /* !defined(HEAPDEBUGALL) */HeapTupleheap_getnext(HeapScanDesc scan, ScanDirection direction){	/* Note: no locking manipulations needed */	HEAPDEBUG_1;				/* heap_getnext( info ) */	/*	 * Note: we depend here on the -1/0/1 encoding of ScanDirection.	 */	heapgettup(scan->rs_rd,			   (int) direction,			   &(scan->rs_ctup),			   &(scan->rs_cbuf),			   scan->rs_snapshot,			   scan->rs_nkeys,			   scan->rs_key,			   scan->rs_nblocks);	if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf))	{		HEAPDEBUG_2;			/* heap_getnext returning EOS */		return NULL;	}	/*	 * if we get here it means we have a new current scan tuple, so point to	 * the proper return buffer and return the tuple.	 */	HEAPDEBUG_3;				/* heap_getnext returning tuple */	if (scan->rs_ctup.t_data != NULL)		pgstat_count_heap_getnext(&scan->rs_pgstat_info);	return ((scan->rs_ctup.t_data == NULL) ? NULL : &(scan->rs_ctup));}/* *	heap_fetch		- retrieve tuple with given tid * * On entry, tuple->t_self is the TID to fetch.  We pin the buffer holding * the tuple, fill in the remaining fields of *tuple, and check the tuple * against the specified snapshot. * * If successful (tuple found and passes snapshot time qual), then *userbuf * is set to the buffer holding the tuple and TRUE is returned.  The caller * must unpin the buffer when done with the tuple. * * If the tuple is not found (ie, item number references a deleted slot), * then tuple->t_data is set to NULL and FALSE is returned. * * If the tuple is found but fails the time qual check, then FALSE is returned * but tuple->t_data is left pointing to the tuple. * * keep_buf determines what is done with the buffer in the FALSE-result cases. * When the caller specifies keep_buf = true, we retain the pin on the buffer * and return it in *userbuf (so the caller must eventually unpin it); when * keep_buf = false, the pin is released and *userbuf is set to InvalidBuffer. * * It is somewhat inconsistent that we ereport() on invalid block number but * return false on invalid item number.  There are a couple of reasons though. * One is that the caller can relatively easily check the block number for * validity, but cannot check the item number without reading the page * himself.  Another is that when we are following a t_ctid link, we can be * reasonably confident that the page number is valid (since VACUUM shouldn't * truncate off the destination page without having killed the referencing * tuple first), but the item number might well not be good. */boolheap_fetch(Relation relation,		   Snapshot snapshot,		   HeapTuple tuple,		   Buffer *userbuf,		   bool keep_buf,		   PgStat_Info *pgstat_info){	/* Assume *userbuf is undefined on entry */	*userbuf = InvalidBuffer;	return heap_release_fetch(relation, snapshot, tuple,							  userbuf, keep_buf, pgstat_info);}/* *	heap_release_fetch		- retrieve tuple with given tid * * This has the same API as heap_fetch except that if *userbuf is not * InvalidBuffer on entry, that buffer will be released before reading * the new page.  This saves a separate ReleaseBuffer step and hence * one entry into the bufmgr when looping through multiple fetches. * Also, if *userbuf is the same buffer that holds the target tuple, * we avoid bufmgr manipulation altogether. */boolheap_release_fetch(Relation relation,				   Snapshot snapshot,				   HeapTuple tuple,				   Buffer *userbuf,				   bool keep_buf,				   PgStat_Info *pgstat_info){	ItemPointer tid = &(tuple->t_self);	ItemId		lp;	Buffer		buffer;	PageHeader	dp;	OffsetNumber offnum;	bool		valid;	/*	 * get the buffer from the relation descriptor. Note that this does a	 * buffer pin, and releases the old *userbuf if not InvalidBuffer.	 */	buffer = ReleaseAndReadBuffer(*userbuf, relation,								  ItemPointerGetBlockNumber(tid));	/*	 * Need share lock on buffer to examine tuple commit status.	 */	LockBuffer(buffer, BUFFER_LOCK_SHARE);	dp = (PageHeader) BufferGetPage(buffer);	/*	 * We'd better check for out-of-range offnum in case of VACUUM since the	 * TID was obtained.	 */	offnum = ItemPointerGetOffsetNumber(tid);	if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))	{		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);		if (keep_buf)			*userbuf = buffer;		else		{			ReleaseBuffer(buffer);			*userbuf = InvalidBuffer;		}		tuple->t_datamcxt = NULL;		tuple->t_data = NULL;		return false;	}	/*	 * get the item line pointer corresponding to the requested tid	 */	lp = PageGetItemId(dp, offnum);	/*	 * Must check for deleted tuple.	 */	if (!ItemIdIsUsed(lp))	{		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);		if (keep_buf)			*userbuf = buffer;		else		{			ReleaseBuffer(buffer);			*userbuf = InvalidBuffer;		}		tuple->t_datamcxt = NULL;		tuple->t_data = NULL;		return false;

⌨️ 快捷键说明

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