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

📄 bootstrap.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
			attrtypes[i] = AllocateAttribute();		memmove((char *) attrtypes[i],				(char *) boot_reldesc->rd_att->attrs[i],				ATTRIBUTE_TUPLE_SIZE);		{			Form_pg_attribute at = attrtypes[i];			elog(DEBUG4, "create attribute %d name %s len %d num %d type %u",				 i, NameStr(at->attname), at->attlen, at->attnum,				 at->atttypid);		}	}}/* ---------------- *		closerel * ---------------- */voidcloserel(char *name){	if (name)	{		if (boot_reldesc)		{			if (strcmp(RelationGetRelationName(boot_reldesc), name) != 0)				elog(ERROR, "close of %s when %s was expected",					 name, RelationGetRelationName(boot_reldesc));		}		else			elog(ERROR, "close of %s before any relation was opened",				 name);	}	if (boot_reldesc == NULL)		elog(ERROR, "no open relation to close");	else	{		elog(DEBUG4, "close relation %s",			 RelationGetRelationName(boot_reldesc));		heap_close(boot_reldesc, NoLock);		boot_reldesc = NULL;	}}/* ---------------- * DEFINEATTR() * * define a <field,type> pair * if there are n fields in a relation to be created, this routine * will be called n times * ---------------- */voidDefineAttr(char *name, char *type, int attnum){	Oid			typeoid;	if (boot_reldesc != NULL)	{		elog(WARNING, "no open relations allowed with CREATE command");		closerel(NULL);	}	if (attrtypes[attnum] == NULL)		attrtypes[attnum] = AllocateAttribute();	MemSet(attrtypes[attnum], 0, ATTRIBUTE_TUPLE_SIZE);	namestrcpy(&attrtypes[attnum]->attname, name);	elog(DEBUG4, "column %s %s", NameStr(attrtypes[attnum]->attname), type);	attrtypes[attnum]->attnum = attnum + 1;		/* fillatt */	typeoid = gettype(type);	if (Typ != NULL)	{		attrtypes[attnum]->atttypid = Ap->am_oid;		attrtypes[attnum]->attlen = Ap->am_typ.typlen;		attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;		attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;		attrtypes[attnum]->attalign = Ap->am_typ.typalign;		/* if an array type, assume 1-dimensional attribute */		if (Ap->am_typ.typelem != InvalidOid && Ap->am_typ.typlen < 0)			attrtypes[attnum]->attndims = 1;		else			attrtypes[attnum]->attndims = 0;	}	else	{		attrtypes[attnum]->atttypid = TypInfo[typeoid].oid;		attrtypes[attnum]->attlen = TypInfo[typeoid].len;		attrtypes[attnum]->attbyval = TypInfo[typeoid].byval;		attrtypes[attnum]->attstorage = TypInfo[typeoid].storage;		attrtypes[attnum]->attalign = TypInfo[typeoid].align;		/* if an array type, assume 1-dimensional attribute */		if (TypInfo[typeoid].elem != InvalidOid &&			attrtypes[attnum]->attlen < 0)			attrtypes[attnum]->attndims = 1;		else			attrtypes[attnum]->attndims = 0;	}	attrtypes[attnum]->attstattarget = -1;	attrtypes[attnum]->attcacheoff = -1;	attrtypes[attnum]->atttypmod = -1;	attrtypes[attnum]->attislocal = true;	/*	 * Mark as "not null" if type is fixed-width and prior columns are too.	 * This corresponds to case where column can be accessed directly via C	 * struct declaration.	 *	 * oidvector and int2vector are also treated as not-nullable, even though	 * they are no longer fixed-width.	 */#define MARKNOTNULL(att) \	((att)->attlen > 0 || \	 (att)->atttypid == OIDVECTOROID || \	 (att)->atttypid == INT2VECTOROID)	if (MARKNOTNULL(attrtypes[attnum]))	{		int			i;		for (i = 0; i < attnum; i++)		{			if (!MARKNOTNULL(attrtypes[i]))				break;		}		if (i == attnum)			attrtypes[attnum]->attnotnull = true;	}}/* ---------------- *		InsertOneTuple * * If objectid is not zero, it is a specific OID to assign to the tuple. * Otherwise, an OID will be assigned (if necessary) by heap_insert. * ---------------- */voidInsertOneTuple(Oid objectid){	HeapTuple	tuple;	TupleDesc	tupDesc;	int			i;	elog(DEBUG4, "inserting row oid %u, %d columns", objectid, numattr);	tupDesc = CreateTupleDesc(numattr,							  RelationGetForm(boot_reldesc)->relhasoids,							  attrtypes);	tuple = heap_formtuple(tupDesc, values, Blanks);	if (objectid != (Oid) 0)		HeapTupleSetOid(tuple, objectid);	pfree(tupDesc);				/* just free's tupDesc, not the attrtypes */	simple_heap_insert(boot_reldesc, tuple);	heap_freetuple(tuple);	elog(DEBUG4, "row inserted");	/*	 * Reset blanks for next tuple	 */	for (i = 0; i < numattr; i++)		Blanks[i] = ' ';}/* ---------------- *		InsertOneValue * ---------------- */voidInsertOneValue(char *value, int i){	Oid			typoid;	Oid			typioparam;	Oid			typinput;	Oid			typoutput;	char	   *prt;	AssertArg(i >= 0 || i < MAXATTR);	elog(DEBUG4, "inserting column %d value \"%s\"", i, value);	if (Typ != NULL)	{		struct typmap **app;		struct typmap *ap;		elog(DEBUG5, "Typ != NULL");		typoid = boot_reldesc->rd_att->attrs[i]->atttypid;		app = Typ;		while (*app && (*app)->am_oid != typoid)			++app;		ap = *app;		if (ap == NULL)			elog(ERROR, "could not find atttypid %u in Typ list", typoid);		/* XXX this should match getTypeIOParam() */		if (ap->am_typ.typtype == 'c')			typioparam = typoid;		else			typioparam = ap->am_typ.typelem;		typinput = ap->am_typ.typinput;		typoutput = ap->am_typ.typoutput;	}	else	{		int			typeindex;		/* XXX why is typoid determined differently in this path? */		typoid = attrtypes[i]->atttypid;		for (typeindex = 0; typeindex < n_types; typeindex++)		{			if (TypInfo[typeindex].oid == typoid)				break;		}		if (typeindex >= n_types)			elog(ERROR, "type oid %u not found", typoid);		elog(DEBUG5, "Typ == NULL, typeindex = %u", typeindex);		/* XXX there are no composite types in TypInfo */		typioparam = TypInfo[typeindex].elem;		typinput = TypInfo[typeindex].inproc;		typoutput = TypInfo[typeindex].outproc;	}	values[i] = OidFunctionCall3(typinput,								 CStringGetDatum(value),								 ObjectIdGetDatum(typioparam),								 Int32GetDatum(-1));	prt = DatumGetCString(OidFunctionCall1(typoutput,										   values[i]));	elog(DEBUG4, "inserted -> %s", prt);	pfree(prt);}/* ---------------- *		InsertOneNull * ---------------- */voidInsertOneNull(int i){	elog(DEBUG4, "inserting column %d NULL", i);	Assert(i >= 0 || i < MAXATTR);	values[i] = PointerGetDatum(NULL);	Blanks[i] = 'n';}/* ---------------- *		cleanup * ---------------- */static voidcleanup(void){	static int	beenhere = 0;	if (!beenhere)		beenhere = 1;	else	{		elog(FATAL, "cleanup called twice");		proc_exit(1);	}	if (boot_reldesc != NULL)		closerel(NULL);	CommitTransactionCommand();	proc_exit(Warnings ? 1 : 0);}/* ---------------- *		gettype * * NB: this is really ugly; it will return an integer index into TypInfo[], * and not an OID at all, until the first reference to a type not known in * TypInfo[].  At that point it will read and cache pg_type in the Typ array, * and subsequently return a real OID (and set the global pointer Ap to * point at the found row in Typ).	So caller must check whether Typ is * still NULL to determine what the return value is! * ---------------- */static Oidgettype(char *type){	int			i;	Relation	rel;	HeapScanDesc scan;	HeapTuple	tup;	struct typmap **app;	if (Typ != NULL)	{		for (app = Typ; *app != NULL; app++)		{			if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)			{				Ap = *app;				return (*app)->am_oid;			}		}	}	else	{		for (i = 0; i < n_types; i++)		{			if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0)				return i;		}		elog(DEBUG4, "external type: %s", type);		rel = heap_open(TypeRelationId, NoLock);		scan = heap_beginscan(rel, SnapshotNow, 0, NULL);		i = 0;		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)			++i;		heap_endscan(scan);		app = Typ = ALLOC(struct typmap *, i + 1);		while (i-- > 0)			*app++ = ALLOC(struct typmap, 1);		*app = NULL;		scan = heap_beginscan(rel, SnapshotNow, 0, NULL);		app = Typ;		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)		{			(*app)->am_oid = HeapTupleGetOid(tup);			memmove((char *) &(*app++)->am_typ,					(char *) GETSTRUCT(tup),					sizeof((*app)->am_typ));		}		heap_endscan(scan);		heap_close(rel, NoLock);		return gettype(type);	}	elog(ERROR, "unrecognized type \"%s\"", type);	err_out();	/* not reached, here to make compiler happy */	return 0;}/* ---------------- *		AllocateAttribute * ---------------- */static Form_pg_attributeAllocateAttribute(void){	Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_TUPLE_SIZE);	if (!PointerIsValid(attribute))		elog(FATAL, "out of memory");	MemSet(attribute, 0, ATTRIBUTE_TUPLE_SIZE);	return attribute;}/* ---------------- *		MapArrayTypeName * XXX arrays of "basetype" are always "_basetype". *	   this is an evil hack inherited from rel. 3.1. * XXX array dimension is thrown away because we *	   don't support fixed-dimension arrays.  again, *	   sickness from 3.1. * * the string passed in must have a '[' character in it * * the string returned is a pointer to static storage and should NOT * be freed by the CALLER. * ---------------- */char *MapArrayTypeName(char *s){	int			i,				j;	static char newStr[NAMEDATALEN];	/* array type names < NAMEDATALEN long */	if (s == NULL || s[0] == '\0')		return s;	j = 1;	newStr[0] = '_';	for (i = 0; i < NAMEDATALEN - 1 && s[i] != '['; i++, j++)		newStr[j] = s[i];	newStr[j] = '\0';	return newStr;}/* ---------------- *		EnterString *		returns the string table position of the identifier *		passed to it.  We add it to the table if we can't find it. * ---------------- */intEnterString(char *str){	hashnode   *node;	int			len;	len = strlen(str);	node = FindStr(str, len, NULL);	if (node)		return node->strnum;	else	{		node = AddStr(str, len, 0);		return node->strnum;	}}/* ---------------- *		LexIDStr *		when given an idnum into the 'string-table' return the string *		associated with the idnum * ---------------- */char *LexIDStr(int ident_num){	return strtable[ident_num];}/* ---------------- *		CompHash * *		Compute a hash function for a given string.  We look at the first, *		the last, and the middle character of a string to try to get spread *		the strings out.  The function is rather arbitrary, except that we *		are mod'ing by a prime number. * ---------------- */static intCompHash(char *str, int len){	int			result;	result = (NUM * str[0] + NUMSQR * str[len - 1] + NUMCUBE * str[(len - 1) / 2]);	return result % HASHTABLESIZE;}/* ---------------- *		FindStr * *		This routine looks for the specified string in the hash *		table.	It returns a pointer to the hash node found, *		or NULL if the string is not in the table. * ---------------- */static hashnode *FindStr(char *str, int length, hashnode *mderef){	hashnode   *node;	node = hashtable[CompHash(str, length)];	while (node != NULL)	{		/*		 * We must differentiate between string constants that might have the		 * same value as a identifier and the identifier itself.		 */		if (!strcmp(str, strtable[node->strnum]))		{			return node;		/* no need to check */		}		else			node = node->next;	}	/* Couldn't find it in the list */	return NULL;}/* ---------------- *		AddStr * *		This function adds the specified string, along with its associated *		data, to the hash table and the string table.  We return the node *		so that the calling routine can find out the unique id that AddStr *		has assigned to this string. * ---------------- */static hashnode *AddStr(char *str, int strlength, int mderef){	hashnode   *temp,			   *trail,			   *newnode;	int			hashresult;	int			len;	if (++strtable_end >= STRTABLESIZE)		elog(FATAL, "bootstrap string table overflow");	/*	 * Some of the utilites (eg, define type, create relation) assume that the	 * string they're passed is a NAMEDATALEN.  We get array bound read	 * violations from purify if we don't allocate at least NAMEDATALEN bytes	 * for strings of this sort.  Because we're lazy, we allocate at least	 * NAMEDATALEN bytes all the time.	 */	if ((len = strlength + 1) < NAMEDATALEN)		len = NAMEDATALEN;	strtable[strtable_end] = malloc((unsigned) len);	strcpy(strtable[strtable_end], str);	/* Now put a node in the hash table */	newnode = (hashnode *) malloc(sizeof(hashnode) * 1);	newnode->strnum = strtable_end;	newnode->next = NULL;	/* Find out where it goes */	hashresult = CompHash(str, strlength);	if (hashtable[hashresult] == NULL)		hashtable[hashresult] = newnode;	else	{							/* There is something in the list */		trail = hashtable[hashresult];		temp = trail->next;		while (temp != NULL)		{			trail = temp;			temp = temp->next;		}		trail->next = newnode;	}	return newnode;}/* *	index_register() -- record an index that has been set up for building *						later. * *		At bootstrap time, we define a bunch of indices on system catalogs. *		We postpone actually building the indices until just before we're *		finished with initialization, however.	This is because more classes *		and indices may be defined, and we want to be sure that all of them *		are present in the index. */voidindex_register(Oid heap,			   Oid ind,			   IndexInfo *indexInfo){	IndexList  *newind;	MemoryContext oldcxt;	/*	 * XXX mao 10/31/92 -- don't gc index reldescs, associated info at	 * bootstrap time.	we'll declare the indices now, but want to create them	 * later.	 */	if (nogc == NULL)		nogc = AllocSetContextCreate(NULL,									 "BootstrapNoGC",									 ALLOCSET_DEFAULT_MINSIZE,									 ALLOCSET_DEFAULT_INITSIZE,									 ALLOCSET_DEFAULT_MAXSIZE);	oldcxt = MemoryContextSwitchTo(nogc);	newind = (IndexList *) palloc(sizeof(IndexList));	newind->il_heap = heap;	newind->il_ind = ind;	newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));	memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));	/* expressions will likely be null, but may as well copy it */	newind->il_info->ii_Expressions = (List *)		copyObject(indexInfo->ii_Expressions);	newind->il_info->ii_ExpressionsState = NIL;	/* predicate will likely be null, but may as well copy it */	newind->il_info->ii_Predicate = (List *)		copyObject(indexInfo->ii_Predicate);	newind->il_info->ii_PredicateState = NIL;	newind->il_next = ILHead;	ILHead = newind;	MemoryContextSwitchTo(oldcxt);}voidbuild_indices(void){	for (; ILHead != NULL; ILHead = ILHead->il_next)	{		Relation	heap;		Relation	ind;		heap = heap_open(ILHead->il_heap, NoLock);		ind = index_open(ILHead->il_ind);		index_build(heap, ind, ILHead->il_info);		/*		 * In normal processing mode, index_build would close the heap and		 * index, but in bootstrap mode it will not.		 */		/* XXX Probably we ought to close the heap and index here? */	}}

⌨️ 快捷键说明

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