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

📄 sequence.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	do_setval(relid, next, iscalled);	PG_RETURN_INT64(next);}/* * If we haven't touched the sequence already in this transaction, * we need to acquire AccessShareLock.	We arrange for the lock to * be owned by the top transaction, so that we don't need to do it * more than once per xact. */static voidacquire_share_lock(Relation seqrel, SeqTable seq){	TransactionId thisxid = GetTopTransactionId();	if (seq->xid != thisxid)	{		ResourceOwner currentOwner;		currentOwner = CurrentResourceOwner;		PG_TRY();		{			CurrentResourceOwner = TopTransactionResourceOwner;			LockRelation(seqrel, AccessShareLock);		}		PG_CATCH();		{			/* Ensure CurrentResourceOwner is restored on error */			CurrentResourceOwner = currentOwner;			PG_RE_THROW();		}		PG_END_TRY();		CurrentResourceOwner = currentOwner;		/* Flag that we have a lock in the current xact. */		seq->xid = thisxid;	}}/* * Given a relation OID, open and lock the sequence.  p_elm and p_rel are * output parameters. */static voidinit_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel){	Relation	seqrel;	volatile SeqTable elm;	/*	 * Open the sequence relation.	 */	seqrel = relation_open(relid, NoLock);	if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a sequence",						RelationGetRelationName(seqrel))));	/* Look to see if we already have a seqtable entry for relation */	for (elm = seqtab; elm != NULL; elm = elm->next)	{		if (elm->relid == relid)			break;	}	/*	 * Allocate new seqtable entry if we didn't find one.	 *	 * NOTE: seqtable entries remain in the list for the life of a backend. If	 * the sequence itself is deleted then the entry becomes wasted memory,	 * but it's small enough that this should not matter.	 */	if (elm == NULL)	{		/*		 * Time to make a new seqtable entry.  These entries live as long as		 * the backend does, so we use plain malloc for them.		 */		elm = (SeqTable) malloc(sizeof(SeqTableData));		if (elm == NULL)			ereport(ERROR,					(errcode(ERRCODE_OUT_OF_MEMORY),					 errmsg("out of memory")));		elm->relid = relid;		elm->xid = InvalidTransactionId;		/* increment is set to 0 until we do read_info (see currval) */		elm->last = elm->cached = elm->increment = 0;		elm->next = seqtab;		seqtab = elm;	}	acquire_share_lock(seqrel, elm);	*p_elm = elm;	*p_rel = seqrel;}/* Given an opened relation, lock the page buffer and find the tuple */static Form_pg_sequenceread_info(SeqTable elm, Relation rel, Buffer *buf){	PageHeader	page;	ItemId		lp;	HeapTupleData tuple;	sequence_magic *sm;	Form_pg_sequence seq;	*buf = ReadBuffer(rel, 0);	LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);	page = (PageHeader) BufferGetPage(*buf);	sm = (sequence_magic *) PageGetSpecialPointer(page);	if (sm->magic != SEQ_MAGIC)		elog(ERROR, "bad magic number in sequence \"%s\": %08X",			 RelationGetRelationName(rel), sm->magic);	lp = PageGetItemId(page, FirstOffsetNumber);	Assert(ItemIdIsUsed(lp));	tuple.t_data = (HeapTupleHeader) PageGetItem((Page) page, lp);	seq = (Form_pg_sequence) GETSTRUCT(&tuple);	elm->increment = seq->increment_by;	return seq;}/* * init_params: process the options list of CREATE or ALTER SEQUENCE, * and store the values into appropriate fields of *new. * * If isInit is true, fill any unspecified options with default values; * otherwise, do not change existing options that aren't explicitly overridden. */static voidinit_params(List *options, Form_pg_sequence new, bool isInit){	DefElem    *last_value = NULL;	DefElem    *increment_by = NULL;	DefElem    *max_value = NULL;	DefElem    *min_value = NULL;	DefElem    *cache_value = NULL;	DefElem    *is_cycled = NULL;	ListCell   *option;	foreach(option, options)	{		DefElem    *defel = (DefElem *) lfirst(option);		if (strcmp(defel->defname, "increment") == 0)		{			if (increment_by)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			increment_by = defel;		}		/*		 * start is for a new sequence restart is for alter		 */		else if (strcmp(defel->defname, "start") == 0 ||				 strcmp(defel->defname, "restart") == 0)		{			if (last_value)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			last_value = defel;		}		else if (strcmp(defel->defname, "maxvalue") == 0)		{			if (max_value)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			max_value = defel;		}		else if (strcmp(defel->defname, "minvalue") == 0)		{			if (min_value)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			min_value = defel;		}		else if (strcmp(defel->defname, "cache") == 0)		{			if (cache_value)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			cache_value = defel;		}		else if (strcmp(defel->defname, "cycle") == 0)		{			if (is_cycled)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			is_cycled = defel;		}		else			elog(ERROR, "option \"%s\" not recognized",				 defel->defname);	}	/* INCREMENT BY */	if (increment_by != NULL)	{		new->increment_by = defGetInt64(increment_by);		if (new->increment_by == 0)			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("INCREMENT must not be zero")));	}	else if (isInit)		new->increment_by = 1;	/* CYCLE */	if (is_cycled != NULL)	{		new->is_cycled = intVal(is_cycled->arg);		Assert(new->is_cycled == false || new->is_cycled == true);	}	else if (isInit)		new->is_cycled = false;	/* MAXVALUE (null arg means NO MAXVALUE) */	if (max_value != NULL && max_value->arg)		new->max_value = defGetInt64(max_value);	else if (isInit || max_value != NULL)	{		if (new->increment_by > 0)			new->max_value = SEQ_MAXVALUE;		/* ascending seq */		else			new->max_value = -1;	/* descending seq */	}	/* MINVALUE (null arg means NO MINVALUE) */	if (min_value != NULL && min_value->arg)		new->min_value = defGetInt64(min_value);	else if (isInit || min_value != NULL)	{		if (new->increment_by > 0)			new->min_value = 1; /* ascending seq */		else			new->min_value = SEQ_MINVALUE;		/* descending seq */	}	/* crosscheck min/max */	if (new->min_value >= new->max_value)	{		char		bufm[100],					bufx[100];		snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);		snprintf(bufx, sizeof(bufx), INT64_FORMAT, new->max_value);		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",						bufm, bufx)));	}	/* START WITH */	if (last_value != NULL)	{		new->last_value = defGetInt64(last_value);		new->is_called = false;		new->log_cnt = 1;	}	else if (isInit)	{		if (new->increment_by > 0)			new->last_value = new->min_value;	/* ascending seq */		else			new->last_value = new->max_value;	/* descending seq */		new->is_called = false;		new->log_cnt = 1;	}	/* crosscheck */	if (new->last_value < new->min_value)	{		char		bufs[100],					bufm[100];		snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);		snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("START value (%s) can't be less than MINVALUE (%s)",						bufs, bufm)));	}	if (new->last_value > new->max_value)	{		char		bufs[100],					bufm[100];		snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);		snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),			   errmsg("START value (%s) can't be greater than MAXVALUE (%s)",					  bufs, bufm)));	}	/* CACHE */	if (cache_value != NULL)	{		new->cache_value = defGetInt64(cache_value);		if (new->cache_value <= 0)		{			char		buf[100];			snprintf(buf, sizeof(buf), INT64_FORMAT, new->cache_value);			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("CACHE (%s) must be greater than zero",							buf)));		}	}	else if (isInit)		new->cache_value = 1;}voidseq_redo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	Relation	reln;	Buffer		buffer;	Page		page;	char	   *item;	Size		itemsz;	xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);	sequence_magic *sm;	if (info != XLOG_SEQ_LOG)		elog(PANIC, "seq_redo: unknown op code %u", info);	reln = XLogOpenRelation(xlrec->node);	if (!RelationIsValid(reln))		return;	buffer = XLogReadBuffer(true, reln, 0);	if (!BufferIsValid(buffer))		elog(PANIC, "seq_redo: can't read block 0 of rel %u/%u/%u",			 xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);	page = (Page) BufferGetPage(buffer);	/* Always reinit the page and reinstall the magic number */	/* See comments in DefineSequence */	PageInit((Page) page, BufferGetPageSize(buffer), sizeof(sequence_magic));	sm = (sequence_magic *) PageGetSpecialPointer(page);	sm->magic = SEQ_MAGIC;	item = (char *) xlrec + sizeof(xl_seq_rec);	itemsz = record->xl_len - sizeof(xl_seq_rec);	itemsz = MAXALIGN(itemsz);	if (PageAddItem(page, (Item) item, itemsz,					FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)		elog(PANIC, "seq_redo: failed to add item to page");	PageSetLSN(page, lsn);	PageSetTLI(page, ThisTimeLineID);	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);	WriteBuffer(buffer);}voidseq_desc(char *buf, uint8 xl_info, char *rec){	uint8		info = xl_info & ~XLR_INFO_MASK;	xl_seq_rec *xlrec = (xl_seq_rec *) rec;	if (info == XLOG_SEQ_LOG)		strcat(buf, "log: ");	else	{		strcat(buf, "UNKNOWN");		return;	}	sprintf(buf + strlen(buf), "rel %u/%u/%u",			xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);}

⌨️ 快捷键说明

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