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

📄 namespace.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (namespaceSearchPathValid && namespaceUser == roleid)		return;	/* Need a modifiable copy of namespace_search_path string */	rawname = pstrdup(namespace_search_path);	/* Parse string into list of identifiers */	if (!SplitIdentifierString(rawname, ',', &namelist))	{		/* syntax error in name list */		/* this should not happen if GUC checked check_search_path */		elog(ERROR, "invalid list syntax");	}	/*	 * Convert the list of names to a list of OIDs.  If any names are not	 * recognizable or we don't have read access, just leave them out of the	 * list.  (We can't raise an error, since the search_path setting has	 * already been accepted.)	Don't make duplicate entries, either.	 */	oidlist = NIL;	foreach(l, namelist)	{		char	   *curname = (char *) lfirst(l);		Oid			namespaceId;		if (strcmp(curname, "$user") == 0)		{			/* $user --- substitute namespace matching user name, if any */			HeapTuple	tuple;			tuple = SearchSysCache(AUTHOID,								   ObjectIdGetDatum(roleid),								   0, 0, 0);			if (HeapTupleIsValid(tuple))			{				char	   *rname;				rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);				namespaceId = GetSysCacheOid(NAMESPACENAME,											 CStringGetDatum(rname),											 0, 0, 0);				ReleaseSysCache(tuple);				if (OidIsValid(namespaceId) &&					!list_member_oid(oidlist, namespaceId) &&					pg_namespace_aclcheck(namespaceId, roleid,										  ACL_USAGE) == ACLCHECK_OK)					oidlist = lappend_oid(oidlist, namespaceId);			}		}		else		{			/* normal namespace reference */			namespaceId = GetSysCacheOid(NAMESPACENAME,										 CStringGetDatum(curname),										 0, 0, 0);			if (OidIsValid(namespaceId) &&				!list_member_oid(oidlist, namespaceId) &&				pg_namespace_aclcheck(namespaceId, roleid,									  ACL_USAGE) == ACLCHECK_OK)				oidlist = lappend_oid(oidlist, namespaceId);		}	}	/*	 * Remember the first member of the explicit list.	 */	if (oidlist == NIL)		firstNS = InvalidOid;	else		firstNS = linitial_oid(oidlist);	/*	 * Add any implicitly-searched namespaces to the list.	Note these go on	 * the front, not the back; also notice that we do not check USAGE	 * permissions for these.	 */	if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))		oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);	if (OidIsValid(myTempNamespace) &&		!list_member_oid(oidlist, myTempNamespace))		oidlist = lcons_oid(myTempNamespace, oidlist);	if (OidIsValid(mySpecialNamespace) &&		!list_member_oid(oidlist, mySpecialNamespace))		oidlist = lcons_oid(mySpecialNamespace, oidlist);	/*	 * Now that we've successfully built the new list of namespace OIDs, save	 * it in permanent storage.	 */	oldcxt = MemoryContextSwitchTo(TopMemoryContext);	newpath = list_copy(oidlist);	MemoryContextSwitchTo(oldcxt);	/* Now safe to assign to state variable. */	list_free(namespaceSearchPath);	namespaceSearchPath = newpath;	/*	 * Update info derived from search path.	 */	firstExplicitNamespace = firstNS;	if (OidIsValid(mySpecialNamespace))		defaultCreationNamespace = mySpecialNamespace;	else		defaultCreationNamespace = firstNS;	/* Mark the path valid. */	namespaceSearchPathValid = true;	namespaceUser = roleid;	/* Clean up. */	pfree(rawname);	list_free(namelist);	list_free(oidlist);}/* * InitTempTableNamespace *		Initialize temp table namespace on first use in a particular backend */static voidInitTempTableNamespace(void){	char		namespaceName[NAMEDATALEN];	Oid			namespaceId;	/*	 * First, do permission check to see if we are authorized to make temp	 * tables.	We use a nonstandard error message here since "databasename:	 * permission denied" might be a tad cryptic.	 *	 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;	 * that's necessary since current user ID could change during the session.	 * But there's no need to make the namespace in the first place until a	 * temp table creation request is made by someone with appropriate rights.	 */	if (pg_database_aclcheck(MyDatabaseId, GetUserId(),							 ACL_CREATE_TEMP) != ACLCHECK_OK)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied to create temporary tables in database \"%s\"",						get_database_name(MyDatabaseId))));	snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);	namespaceId = GetSysCacheOid(NAMESPACENAME,								 CStringGetDatum(namespaceName),								 0, 0, 0);	if (!OidIsValid(namespaceId))	{		/*		 * First use of this temp namespace in this database; create it. The		 * temp namespaces are always owned by the superuser.  We leave their		 * permissions at default --- i.e., no access except to superuser ---		 * to ensure that unprivileged users can't peek at other backends'		 * temp tables.  This works because the places that access the temp		 * namespace for my own backend skip permissions checks on it.		 */		namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);		/* Advance command counter to make namespace visible */		CommandCounterIncrement();	}	else	{		/*		 * If the namespace already exists, clean it out (in case the former		 * owner crashed without doing so).		 */		RemoveTempRelations(namespaceId);	}	/*	 * Okay, we've prepared the temp namespace ... but it's not committed yet,	 * so all our work could be undone by transaction rollback.  Set flag for	 * AtEOXact_Namespace to know what to do.	 */	myTempNamespace = namespaceId;	/* It should not be done already. */	AssertState(myTempNamespaceSubID == InvalidSubTransactionId);	myTempNamespaceSubID = GetCurrentSubTransactionId();	namespaceSearchPathValid = false;	/* need to rebuild list */}/* * End-of-transaction cleanup for namespaces. */voidAtEOXact_Namespace(bool isCommit){	/*	 * If we abort the transaction in which a temp namespace was selected,	 * we'll have to do any creation or cleanout work over again.  So, just	 * forget the namespace entirely until next time.  On the other hand, if	 * we commit then register an exit callback to clean out the temp tables	 * at backend shutdown.  (We only want to register the callback once per	 * session, so this is a good place to do it.)	 */	if (myTempNamespaceSubID != InvalidSubTransactionId)	{		if (isCommit)			on_shmem_exit(RemoveTempRelationsCallback, 0);		else		{			myTempNamespace = InvalidOid;			namespaceSearchPathValid = false;	/* need to rebuild list */		}		myTempNamespaceSubID = InvalidSubTransactionId;	}	/*	 * Clean up if someone failed to do PopSpecialNamespace	 */	if (OidIsValid(mySpecialNamespace))	{		mySpecialNamespace = InvalidOid;		namespaceSearchPathValid = false;		/* need to rebuild list */	}}/* * AtEOSubXact_Namespace * * At subtransaction commit, propagate the temp-namespace-creation * flag to the parent subtransaction. * * At subtransaction abort, forget the flag if we set it up. */voidAtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,					  SubTransactionId parentSubid){	if (myTempNamespaceSubID == mySubid)	{		if (isCommit)			myTempNamespaceSubID = parentSubid;		else		{			myTempNamespaceSubID = InvalidSubTransactionId;			/* TEMP namespace creation failed, so reset state */			myTempNamespace = InvalidOid;			namespaceSearchPathValid = false;	/* need to rebuild list */		}	}}/* * Remove all relations in the specified temp namespace. * * This is called at backend shutdown (if we made any temp relations). * It is also called when we begin using a pre-existing temp namespace, * in order to clean out any relations that might have been created by * a crashed backend. */static voidRemoveTempRelations(Oid tempNamespaceId){	ObjectAddress object;	/*	 * We want to get rid of everything in the target namespace, but not the	 * namespace itself (deleting it only to recreate it later would be a	 * waste of cycles).  We do this by finding everything that has a	 * dependency on the namespace.	 */	object.classId = NamespaceRelationId;	object.objectId = tempNamespaceId;	object.objectSubId = 0;	deleteWhatDependsOn(&object, false);}/* * Callback to remove temp relations at backend exit. */static voidRemoveTempRelationsCallback(int code, Datum arg){	if (OidIsValid(myTempNamespace))	/* should always be true */	{		/* Need to ensure we have a usable transaction. */		AbortOutOfAnyTransaction();		StartTransactionCommand();		RemoveTempRelations(myTempNamespace);		CommitTransactionCommand();	}}/* * Routines for handling the GUC variable 'search_path'. *//* assign_hook: validate new search_path, do extra actions as needed */const char *assign_search_path(const char *newval, bool doit, GucSource source){	char	   *rawname;	List	   *namelist;	ListCell   *l;	/* Need a modifiable copy of string */	rawname = pstrdup(newval);	/* Parse string into list of identifiers */	if (!SplitIdentifierString(rawname, ',', &namelist))	{		/* syntax error in name list */		pfree(rawname);		list_free(namelist);		return NULL;	}	/*	 * If we aren't inside a transaction, we cannot do database access so	 * cannot verify the individual names.	Must accept the list on faith.	 */	if (source >= PGC_S_INTERACTIVE && IsTransactionState())	{		/*		 * Verify that all the names are either valid namespace names or		 * "$user".  We do not require $user to correspond to a valid		 * namespace.  We do not check for USAGE rights, either; should we?		 *		 * When source == PGC_S_TEST, we are checking the argument of an ALTER		 * DATABASE SET or ALTER USER SET command.	It could be that the		 * intended use of the search path is for some other database, so we		 * should not error out if it mentions schemas not present in the		 * current database.  We reduce the message to NOTICE instead.		 */		foreach(l, namelist)		{			char	   *curname = (char *) lfirst(l);			if (strcmp(curname, "$user") == 0)				continue;			if (!SearchSysCacheExists(NAMESPACENAME,									  CStringGetDatum(curname),									  0, 0, 0))				ereport((source == PGC_S_TEST) ? NOTICE : ERROR,						(errcode(ERRCODE_UNDEFINED_SCHEMA),						 errmsg("schema \"%s\" does not exist", curname)));		}	}	pfree(rawname);	list_free(namelist);	/*	 * We mark the path as needing recomputation, but don't do anything until	 * it's needed.  This avoids trying to do database access during GUC	 * initialization.	 */	if (doit)		namespaceSearchPathValid = false;	return newval;}/* * InitializeSearchPath: initialize module during InitPostgres. * * This is called after we are up enough to be able to do catalog lookups. */voidInitializeSearchPath(void){	if (IsBootstrapProcessingMode())	{		/*		 * In bootstrap mode, the search path must be 'pg_catalog' so that		 * tables are created in the proper namespace; ignore the GUC setting.		 */		MemoryContext oldcxt;		oldcxt = MemoryContextSwitchTo(TopMemoryContext);		namespaceSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);		MemoryContextSwitchTo(oldcxt);		defaultCreationNamespace = PG_CATALOG_NAMESPACE;		firstExplicitNamespace = PG_CATALOG_NAMESPACE;		namespaceSearchPathValid = true;		namespaceUser = GetUserId();	}	else	{		/*		 * In normal mode, arrange for a callback on any syscache invalidation		 * of pg_namespace rows.		 */		CacheRegisterSyscacheCallback(NAMESPACEOID,									  NamespaceCallback,									  (Datum) 0);		/* Force search path to be recomputed on next use */		namespaceSearchPathValid = false;	}}/* * NamespaceCallback *		Syscache inval callback function */static voidNamespaceCallback(Datum arg, Oid relid){	/* Force search path to be recomputed on next use */	namespaceSearchPathValid = false;}/* * Fetch the active search path. The return value is a palloc'ed list * of OIDs; the caller is responsible for freeing this storage as * appropriate. * * The returned list includes the implicitly-prepended namespaces only if * includeImplicit is true. */List *fetch_search_path(bool includeImplicit){	List	   *result;	recomputeNamespacePath();	result = list_copy(namespaceSearchPath);	if (!includeImplicit)	{		while (result && linitial_oid(result) != firstExplicitNamespace)			result = list_delete_first(result);	}	return result;}/* * Export the FooIsVisible functions as SQL-callable functions. */Datumpg_table_is_visible(PG_FUNCTION_ARGS){	Oid			oid = PG_GETARG_OID(0);	PG_RETURN_BOOL(RelationIsVisible(oid));}Datumpg_type_is_visible(PG_FUNCTION_ARGS){	Oid			oid = PG_GETARG_OID(0);	PG_RETURN_BOOL(TypeIsVisible(oid));}Datumpg_function_is_visible(PG_FUNCTION_ARGS){	Oid			oid = PG_GETARG_OID(0);	PG_RETURN_BOOL(FunctionIsVisible(oid));}Datumpg_operator_is_visible(PG_FUNCTION_ARGS){	Oid			oid = PG_GETARG_OID(0);	PG_RETURN_BOOL(OperatorIsVisible(oid));}Datumpg_opclass_is_visible(PG_FUNCTION_ARGS){	Oid			oid = PG_GETARG_OID(0);	PG_RETURN_BOOL(OpclassIsVisible(oid));}Datumpg_conversion_is_visible(PG_FUNCTION_ARGS){	Oid			oid = PG_GETARG_OID(0);	PG_RETURN_BOOL(ConversionIsVisible(oid));}

⌨️ 快捷键说明

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