+ * recomputeNamespacePath - recompute path derived variables if needed.
+ */
+static void
+recomputeNamespacePath(void)
+{
+ Oid userId = GetUserId();
+ char *rawname;
+ List *namelist;
+ List *oidlist;
+ List *newpath;
+ List *l;
+ 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, "recomputeNamespacePath: 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.)
+ */
+ 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) &&
+ pg_namespace_aclcheck(namespaceId, userId,
+ ACL_USAGE) == ACLCHECK_OK)
+ oidlist = lappendi(oidlist, namespaceId);
+ }
+ }
+ else
+ {
+ /* normal namespace reference */
+ namespaceId = GetSysCacheOid(NAMESPACENAME,
+ CStringGetDatum(curname),
+ 0, 0, 0);
+ if (OidIsValid(namespaceId) &&
+ pg_namespace_aclcheck(namespaceId, userId,
+ ACL_USAGE) == ACLCHECK_OK)
+ oidlist = lappendi(oidlist, namespaceId);
+ }
+ }
+
+ /*
+ * 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.
+ */
+ pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE,
+ namespaceSearchPath);
+
+ if (namespaceSearchPath == NIL)
+ defaultCreationNamespace = InvalidOid;
+ else
+ defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath);
+
+ /* Mark the path valid. */
+ namespaceSearchPathValid = true;
+ namespaceUser = userId;
+
+ /* Clean up. */
+ pfree(rawname);
+ freeList(namelist);
+ freeList(oidlist);
+}
+
+/*