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

📄 indexcmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	int			overhead = 0;	/* chars needed for label and underscores */	int			availchars;		/* chars available for name(s) */	int			name1chars;		/* chars allocated to name1 */	int			name2chars;		/* chars allocated to name2 */	int			ndx;	name1chars = strlen(name1);	if (name2)	{		name2chars = strlen(name2);		overhead++;				/* allow for separating underscore */	}	else		name2chars = 0;	if (label)		overhead += strlen(label) + 1;	availchars = NAMEDATALEN - 1 - overhead;	Assert(availchars > 0);		/* else caller chose a bad label */	/*	 * If we must truncate,  preferentially truncate the longer name. This	 * logic could be expressed without a loop, but it's simple and obvious as	 * a loop.	 */	while (name1chars + name2chars > availchars)	{		if (name1chars > name2chars)			name1chars--;		else			name2chars--;	}	name1chars = pg_mbcliplen(name1, name1chars, name1chars);	if (name2)		name2chars = pg_mbcliplen(name2, name2chars, name2chars);	/* Now construct the string using the chosen lengths */	name = palloc(name1chars + name2chars + overhead + 1);	memcpy(name, name1, name1chars);	ndx = name1chars;	if (name2)	{		name[ndx++] = '_';		memcpy(name + ndx, name2, name2chars);		ndx += name2chars;	}	if (label)	{		name[ndx++] = '_';		strcpy(name + ndx, label);	}	else		name[ndx] = '\0';	return name;}/* * Select a nonconflicting name for a new relation.  This is ordinarily * used to choose index names (which is why it's here) but it can also * be used for sequences, or any autogenerated relation kind. * * name1, name2, and label are used the same way as for makeObjectName(), * except that the label can't be NULL; digits will be appended to the label * if needed to create a name that is unique within the specified namespace. * * Note: it is theoretically possible to get a collision anyway, if someone * else chooses the same name concurrently.  This is fairly unlikely to be * a problem in practice, especially if one is holding an exclusive lock on * the relation identified by name1.  However, if choosing multiple names * within a single command, you'd better create the new object and do * CommandCounterIncrement before choosing the next one! * * Returns a palloc'd string. */char *ChooseRelationName(const char *name1, const char *name2,				   const char *label, Oid namespace){	int			pass = 0;	char	   *relname = NULL;	char		modlabel[NAMEDATALEN];	/* try the unmodified label first */	StrNCpy(modlabel, label, sizeof(modlabel));	for (;;)	{		relname = makeObjectName(name1, name2, modlabel);		if (!OidIsValid(get_relname_relid(relname, namespace)))			break;		/* found a conflict, so try a new name component */		pfree(relname);		snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);	}	return relname;}/* * relationHasPrimaryKey - * *	See whether an existing relation has a primary key. */static boolrelationHasPrimaryKey(Relation rel){	bool		result = false;	List	   *indexoidlist;	ListCell   *indexoidscan;	/*	 * Get the list of index OIDs for the table from the relcache, and look up	 * each one in the pg_index syscache until we find one marked primary key	 * (hopefully there isn't more than one such).	 */	indexoidlist = RelationGetIndexList(rel);	foreach(indexoidscan, indexoidlist)	{		Oid			indexoid = lfirst_oid(indexoidscan);		HeapTuple	indexTuple;		indexTuple = SearchSysCache(INDEXRELID,									ObjectIdGetDatum(indexoid),									0, 0, 0);		if (!HeapTupleIsValid(indexTuple))		/* should not happen */			elog(ERROR, "cache lookup failed for index %u", indexoid);		result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;		ReleaseSysCache(indexTuple);		if (result)			break;	}	list_free(indexoidlist);	return result;}/* * RemoveIndex *		Deletes an index. */voidRemoveIndex(RangeVar *relation, DropBehavior behavior){	Oid			indOid;	char		relkind;	ObjectAddress object;	indOid = RangeVarGetRelid(relation, false);	relkind = get_rel_relkind(indOid);	if (relkind != RELKIND_INDEX)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not an index",						relation->relname)));	object.classId = RelationRelationId;	object.objectId = indOid;	object.objectSubId = 0;	performDeletion(&object, behavior);}/* * ReindexIndex *		Recreate a specific index. */voidReindexIndex(RangeVar *indexRelation){	Oid			indOid;	HeapTuple	tuple;	indOid = RangeVarGetRelid(indexRelation, false);	tuple = SearchSysCache(RELOID,						   ObjectIdGetDatum(indOid),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		/* shouldn't happen */		elog(ERROR, "cache lookup failed for relation %u", indOid);	if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not an index",						indexRelation->relname)));	/* Check permissions */	if (!pg_class_ownercheck(indOid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   indexRelation->relname);	ReleaseSysCache(tuple);	reindex_index(indOid);}/* * ReindexTable *		Recreate all indexes of a table (and of its toast table, if any) */voidReindexTable(RangeVar *relation){	Oid			heapOid;	HeapTuple	tuple;	heapOid = RangeVarGetRelid(relation, false);	tuple = SearchSysCache(RELOID,						   ObjectIdGetDatum(heapOid),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		/* shouldn't happen */		elog(ERROR, "cache lookup failed for relation %u", heapOid);	if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION &&		((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_TOASTVALUE)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a table",						relation->relname)));	/* Check permissions */	if (!pg_class_ownercheck(heapOid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   relation->relname);	/* Can't reindex shared tables except in standalone mode */	if (((Form_pg_class) GETSTRUCT(tuple))->relisshared && IsUnderPostmaster)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("shared table \"%s\" can only be reindexed in stand-alone mode",						relation->relname)));	ReleaseSysCache(tuple);	if (!reindex_relation(heapOid, true))		ereport(NOTICE,				(errmsg("table \"%s\" has no indexes",						relation->relname)));}/* * ReindexDatabase *		Recreate indexes of a database. * * To reduce the probability of deadlocks, each table is reindexed in a * separate transaction, so we can release the lock on it right away. */voidReindexDatabase(const char *databaseName, bool do_system, bool do_user){	Relation	relationRelation;	HeapScanDesc scan;	HeapTuple	tuple;	MemoryContext private_context;	MemoryContext old;	List	   *relids = NIL;	ListCell   *l;	AssertArg(databaseName);	if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("can only reindex the currently open database")));	if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,					   databaseName);	/*	 * We cannot run inside a user transaction block; if we were inside a	 * transaction, then our commit- and start-transaction-command calls would	 * not have the intended effect!	 */	PreventTransactionChain((void *) databaseName, "REINDEX DATABASE");	/*	 * Create a memory context that will survive forced transaction commits we	 * do below.  Since it is a child of PortalContext, it will go away	 * eventually even if we suffer an error; there's no need for special	 * abort cleanup logic.	 */	private_context = AllocSetContextCreate(PortalContext,											"ReindexDatabase",											ALLOCSET_DEFAULT_MINSIZE,											ALLOCSET_DEFAULT_INITSIZE,											ALLOCSET_DEFAULT_MAXSIZE);	/*	 * We always want to reindex pg_class first.  This ensures that if there	 * is any corruption in pg_class' indexes, they will be fixed before we	 * process any other tables.  This is critical because reindexing itself	 * will try to update pg_class.	 */	if (do_system)	{		old = MemoryContextSwitchTo(private_context);		relids = lappend_oid(relids, RelationRelationId);		MemoryContextSwitchTo(old);	}	/*	 * Scan pg_class to build a list of the relations we need to reindex.	 *	 * We only consider plain relations here (toast rels will be processed	 * indirectly by reindex_relation).	 */	relationRelation = heap_open(RelationRelationId, AccessShareLock);	scan = heap_beginscan(relationRelation, SnapshotNow, 0, NULL);	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);		if (classtuple->relkind != RELKIND_RELATION)			continue;		/* Check user/system classification, and optionally skip */		if (IsSystemClass(classtuple))		{			if (!do_system)				continue;		}		else		{			if (!do_user)				continue;		}		if (IsUnderPostmaster)	/* silently ignore shared tables */		{			if (classtuple->relisshared)				continue;		}		if (HeapTupleGetOid(tuple) == RelationRelationId)			continue;			/* got it already */		old = MemoryContextSwitchTo(private_context);		relids = lappend_oid(relids, HeapTupleGetOid(tuple));		MemoryContextSwitchTo(old);	}	heap_endscan(scan);	heap_close(relationRelation, AccessShareLock);	/* Now reindex each rel in a separate transaction */	CommitTransactionCommand();	foreach(l, relids)	{		Oid			relid = lfirst_oid(l);		StartTransactionCommand();		/* functions in indexes may want a snapshot set */		ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());		if (reindex_relation(relid, true))			ereport(NOTICE,					(errmsg("table \"%s\" was reindexed",							get_rel_name(relid))));		CommitTransactionCommand();	}	StartTransactionCommand();	MemoryContextDelete(private_context);}

⌨️ 快捷键说明

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