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

📄 namespace.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
		proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);		if (OidIsValid(proc))			return proc;	}	/* Not found in path */	return InvalidOid;}/* * recomputeNamespacePath - recompute path derived variables if needed. */static voidrecomputeNamespacePath(void){	AclId		userId = GetUserId();	char	   *rawname;	List	   *namelist;	List	   *oidlist;	List	   *newpath;	List	   *l;	Oid			firstNS;	MemoryContext oldcxt;	/*	 * Do nothing if path is already valid.	 */	if (namespaceSearchPathValid && namespaceUser == userId)		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(SHADOWSYSID,								   ObjectIdGetDatum(userId),								   0, 0, 0);			if (HeapTupleIsValid(tuple))			{				char	   *uname;				uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);				namespaceId = GetSysCacheOid(NAMESPACENAME,											 CStringGetDatum(uname),											 0, 0, 0);				ReleaseSysCache(tuple);				if (OidIsValid(namespaceId) &&					!oidMember(namespaceId, oidlist) &&					pg_namespace_aclcheck(namespaceId, userId,										  ACL_USAGE) == ACLCHECK_OK)					oidlist = lappendo(oidlist, namespaceId);			}		}		else		{			/* normal namespace reference */			namespaceId = GetSysCacheOid(NAMESPACENAME,										 CStringGetDatum(curname),										 0, 0, 0);			if (OidIsValid(namespaceId) &&				!oidMember(namespaceId, oidlist) &&				pg_namespace_aclcheck(namespaceId, userId,									  ACL_USAGE) == ACLCHECK_OK)				oidlist = lappendo(oidlist, namespaceId);		}	}	/*	 * Remember the first member of the explicit list.	 */	if (oidlist == NIL)		firstNS = InvalidOid;	else		firstNS = lfirsto(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 (!oidMember(PG_CATALOG_NAMESPACE, oidlist))		oidlist = lconso(PG_CATALOG_NAMESPACE, oidlist);	if (OidIsValid(myTempNamespace) &&		!oidMember(myTempNamespace, oidlist))		oidlist = lconso(myTempNamespace, oidlist);	if (OidIsValid(mySpecialNamespace) &&		!oidMember(mySpecialNamespace, oidlist))		oidlist = lconso(mySpecialNamespace, oidlist);	/*	 * Now that we've successfully built the new list of namespace OIDs,	 * save it in permanent storage.	 */	oldcxt = MemoryContextSwitchTo(TopMemoryContext);	newpath = listCopy(oidlist);	MemoryContextSwitchTo(oldcxt);	/* Now safe to assign to state variable. */	freeList(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 = userId;	/* Clean up. */	pfree(rawname);	freeList(namelist);	freeList(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 we apply the check to the session user, not the currently active	 * userid, since we are not going to change our minds about temp table	 * availability during the session.	 */	if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),							 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_USESYSID);		/* 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;	firstTempTransaction = true;	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 (firstTempTransaction)	{		if (isCommit)			on_shmem_exit(RemoveTempRelationsCallback, 0);		else		{			myTempNamespace = InvalidOid;			namespaceSearchPathValid = false;	/* need to rebuild list */		}		firstTempTransaction = false;	}	/*	 * Clean up if someone failed to do PopSpecialNamespace	 */	if (OidIsValid(mySpecialNamespace))	{		mySpecialNamespace = 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 = get_system_catalog_relid(NamespaceRelationName);	object.objectId = tempNamespaceId;	object.objectSubId = 0;	deleteWhatDependsOn(&object, false);}/* * Callback to remove temp relations at backend exit. */static voidRemoveTempRelationsCallback(void){	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, bool interactive){	char	   *rawname;	List	   *namelist;	List	   *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);		freeList(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 (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?		 */		foreach(l, namelist)		{			char	   *curname = (char *) lfirst(l);			if (strcmp(curname, "$user") == 0)				continue;			if (!SearchSysCacheExists(NAMESPACENAME,									  CStringGetDatum(curname),									  0, 0, 0))				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_SCHEMA),					   errmsg("schema \"%s\" does not exist", curname)));		}	}	pfree(rawname);	freeList(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 = makeListo1(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, expressed as a List of OIDs. * * The returned list includes the implicitly-prepended namespaces only if * includeImplicit is true. * * NB: caller must treat the list as read-only! */List *fetch_search_path(bool includeImplicit){	List	   *result;	recomputeNamespacePath();	result = namespaceSearchPath;	if (!includeImplicit)	{		while (result && lfirsto(result) != firstExplicitNamespace)			result = lnext(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 + -