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

📄 sequence.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	PG_RETURN_INT64(nextval_internal(relid));}static int64nextval_internal(Oid relid){	SeqTable	elm;	Relation	seqrel;	Buffer		buf;	Page		page;	Form_pg_sequence seq;	int64		incby,				maxv,				minv,				cache,				log,				fetch,				last;	int64		result,				next,				rescnt = 0;	bool		logit = false;	/* open and AccessShareLock sequence */	init_sequence(relid, &elm, &seqrel);	if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied for sequence %s",						RelationGetRelationName(seqrel))));	if (elm->last != elm->cached)		/* some numbers were cached */	{		last_used_seq = elm;		elm->last += elm->increment;		relation_close(seqrel, NoLock);		return elm->last;	}	/* lock page' buffer and read tuple */	seq = read_info(elm, seqrel, &buf);	page = BufferGetPage(buf);	last = next = result = seq->last_value;	incby = seq->increment_by;	maxv = seq->max_value;	minv = seq->min_value;	fetch = cache = seq->cache_value;	log = seq->log_cnt;	if (!seq->is_called)	{		rescnt++;				/* last_value if not called */		fetch--;		log--;	}	/*	 * Decide whether we should emit a WAL log record.	If so, force up the	 * fetch count to grab SEQ_LOG_VALS more values than we actually need to	 * cache.  (These will then be usable without logging.)	 *	 * If this is the first nextval after a checkpoint, we must force a new	 * WAL record to be written anyway, else replay starting from the	 * checkpoint would fail to advance the sequence past the logged values.	 * In this case we may as well fetch extra values.	 */	if (log < fetch)	{		/* forced log to satisfy local demand for values */		fetch = log = fetch + SEQ_LOG_VALS;		logit = true;	}	else	{		XLogRecPtr	redoptr = GetRedoRecPtr();		if (XLByteLE(PageGetLSN(page), redoptr))		{			/* last update of seq was before checkpoint */			fetch = log = fetch + SEQ_LOG_VALS;			logit = true;		}	}	while (fetch)				/* try to fetch cache [+ log ] numbers */	{		/*		 * Check MAXVALUE for ascending sequences and MINVALUE for descending		 * sequences		 */		if (incby > 0)		{			/* ascending sequence */			if ((maxv >= 0 && next > maxv - incby) ||				(maxv < 0 && next + incby > maxv))			{				if (rescnt > 0)					break;		/* stop fetching */				if (!seq->is_cycled)				{					char		buf[100];					snprintf(buf, sizeof(buf), INT64_FORMAT, maxv);					ereport(ERROR,						  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						   errmsg("nextval: reached maximum value of sequence \"%s\" (%s)",								  RelationGetRelationName(seqrel), buf)));				}				next = minv;			}			else				next += incby;		}		else		{			/* descending sequence */			if ((minv < 0 && next < minv - incby) ||				(minv >= 0 && next + incby < minv))			{				if (rescnt > 0)					break;		/* stop fetching */				if (!seq->is_cycled)				{					char		buf[100];					snprintf(buf, sizeof(buf), INT64_FORMAT, minv);					ereport(ERROR,						  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						   errmsg("nextval: reached minimum value of sequence \"%s\" (%s)",								  RelationGetRelationName(seqrel), buf)));				}				next = maxv;			}			else				next += incby;		}		fetch--;		if (rescnt < cache)		{			log--;			rescnt++;			last = next;			if (rescnt == 1)	/* if it's first result - */				result = next;	/* it's what to return */		}	}	log -= fetch;				/* adjust for any unfetched numbers */	Assert(log >= 0);	/* save info in local cache */	elm->last = result;			/* last returned number */	elm->cached = last;			/* last fetched number */	last_used_seq = elm;	START_CRIT_SECTION();	/* XLOG stuff */	if (logit && !seqrel->rd_istemp)	{		xl_seq_rec	xlrec;		XLogRecPtr	recptr;		XLogRecData rdata[2];		xlrec.node = seqrel->rd_node;		rdata[0].data = (char *) &xlrec;		rdata[0].len = sizeof(xl_seq_rec);		rdata[0].buffer = InvalidBuffer;		rdata[0].next = &(rdata[1]);		/* set values that will be saved in xlog */		seq->last_value = next;		seq->is_called = true;		seq->log_cnt = 0;		rdata[1].data = (char *) page + ((PageHeader) page)->pd_upper;		rdata[1].len = ((PageHeader) page)->pd_special -			((PageHeader) page)->pd_upper;		rdata[1].buffer = InvalidBuffer;		rdata[1].next = NULL;		recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);		PageSetLSN(page, recptr);		PageSetTLI(page, ThisTimeLineID);	}	/* update on-disk data */	seq->last_value = last;		/* last fetched number */	seq->is_called = true;	seq->log_cnt = log;			/* how much is logged */	END_CRIT_SECTION();	LockBuffer(buf, BUFFER_LOCK_UNLOCK);	WriteBuffer(buf);	relation_close(seqrel, NoLock);	return result;}Datumcurrval_oid(PG_FUNCTION_ARGS){	Oid			relid = PG_GETARG_OID(0);	int64		result;	SeqTable	elm;	Relation	seqrel;	/* open and AccessShareLock sequence */	init_sequence(relid, &elm, &seqrel);	if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied for sequence %s",						RelationGetRelationName(seqrel))));	if (elm->increment == 0)	/* nextval/read_info were not called */		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("currval of sequence \"%s\" is not yet defined in this session",						RelationGetRelationName(seqrel))));	result = elm->last;	relation_close(seqrel, NoLock);	PG_RETURN_INT64(result);}Datumlastval(PG_FUNCTION_ARGS){	Relation	seqrel;	int64		result;	if (last_used_seq == NULL)		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("lastval is not yet defined in this session")));	/* Someone may have dropped the sequence since the last nextval() */	if (!SearchSysCacheExists(RELOID,							  ObjectIdGetDatum(last_used_seq->relid),							  0, 0, 0))		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("lastval is not yet defined in this session")));	seqrel = relation_open(last_used_seq->relid, NoLock);	acquire_share_lock(seqrel, last_used_seq);	/* nextval() must have already been called for this sequence */	Assert(last_used_seq->increment != 0);	if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied for sequence %s",						RelationGetRelationName(seqrel))));	result = last_used_seq->last;	relation_close(seqrel, NoLock);	PG_RETURN_INT64(result);}/* * Main internal procedure that handles 2 & 3 arg forms of SETVAL. * * Note that the 3 arg version (which sets the is_called flag) is * only for use in pg_dump, and setting the is_called flag may not * work if multiple users are attached to the database and referencing * the sequence (unlikely if pg_dump is restoring it). * * It is necessary to have the 3 arg version so that pg_dump can * restore the state of a sequence exactly during data-only restores - * it is the only way to clear the is_called flag in an existing * sequence. */static voiddo_setval(Oid relid, int64 next, bool iscalled){	SeqTable	elm;	Relation	seqrel;	Buffer		buf;	Form_pg_sequence seq;	/* open and AccessShareLock sequence */	init_sequence(relid, &elm, &seqrel);	if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied for sequence %s",						RelationGetRelationName(seqrel))));	/* lock page' buffer and read tuple */	seq = read_info(elm, seqrel, &buf);	if ((next < seq->min_value) || (next > seq->max_value))	{		char		bufv[100],					bufm[100],					bufx[100];		snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);		snprintf(bufm, sizeof(bufm), INT64_FORMAT, seq->min_value);		snprintf(bufx, sizeof(bufx), INT64_FORMAT, seq->max_value);		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",						bufv, RelationGetRelationName(seqrel),						bufm, bufx)));	}	/* save info in local cache */	elm->last = next;			/* last returned number */	elm->cached = next;			/* last cached number (forget cached values) */	START_CRIT_SECTION();	/* XLOG stuff */	if (!seqrel->rd_istemp)	{		xl_seq_rec	xlrec;		XLogRecPtr	recptr;		XLogRecData rdata[2];		Page		page = BufferGetPage(buf);		xlrec.node = seqrel->rd_node;		rdata[0].data = (char *) &xlrec;		rdata[0].len = sizeof(xl_seq_rec);		rdata[0].buffer = InvalidBuffer;		rdata[0].next = &(rdata[1]);		/* set values that will be saved in xlog */		seq->last_value = next;		seq->is_called = true;		seq->log_cnt = 0;		rdata[1].data = (char *) page + ((PageHeader) page)->pd_upper;		rdata[1].len = ((PageHeader) page)->pd_special -			((PageHeader) page)->pd_upper;		rdata[1].buffer = InvalidBuffer;		rdata[1].next = NULL;		recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);		PageSetLSN(page, recptr);		PageSetTLI(page, ThisTimeLineID);	}	/* save info in sequence relation */	seq->last_value = next;		/* last fetched number */	seq->is_called = iscalled;	seq->log_cnt = (iscalled) ? 0 : 1;	END_CRIT_SECTION();	LockBuffer(buf, BUFFER_LOCK_UNLOCK);	WriteBuffer(buf);	relation_close(seqrel, NoLock);}/* * Implement the 2 arg setval procedure. * See do_setval for discussion. */Datumsetval_oid(PG_FUNCTION_ARGS){	Oid			relid = PG_GETARG_OID(0);	int64		next = PG_GETARG_INT64(1);	do_setval(relid, next, true);	PG_RETURN_INT64(next);}/* * Implement the 3 arg setval procedure. * See do_setval for discussion. */Datumsetval3_oid(PG_FUNCTION_ARGS){	Oid			relid = PG_GETARG_OID(0);	int64		next = PG_GETARG_INT64(1);	bool		iscalled = PG_GETARG_BOOL(2);

⌨️ 快捷键说明

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