1 /*-------------------------------------------------------------------------
4 * code to support accessing and searching namespaces
6 * This is separate from pg_namespace.c, which contains the routines that
7 * directly manipulate the pg_namespace system catalog. This module
8 * provides routines associated with defining a "namespace search path"
9 * and implementing search-path-controlled searches.
12 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
16 * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.6 2002/04/06 06:59:21 tgl Exp $
18 *-------------------------------------------------------------------------
22 #include "access/heapam.h"
23 #include "access/xact.h"
24 #include "catalog/catname.h"
25 #include "catalog/heap.h"
26 #include "catalog/namespace.h"
27 #include "catalog/pg_inherits.h"
28 #include "catalog/pg_namespace.h"
29 #include "catalog/pg_proc.h"
30 #include "catalog/pg_shadow.h"
31 #include "miscadmin.h"
32 #include "nodes/makefuncs.h"
33 #include "storage/backendid.h"
34 #include "utils/builtins.h"
35 #include "utils/fmgroids.h"
36 #include "utils/guc.h"
37 #include "utils/catcache.h"
38 #include "utils/lsyscache.h"
39 #include "utils/syscache.h"
43 * The namespace search path is a possibly-empty list of namespace OIDs.
44 * In addition to the explicit list, the TEMP table namespace is always
45 * implicitly searched first (if it's been initialized). Also, the system
46 * catalog namespace is always searched. If the system namespace is
47 * explicitly present in the path then it will be searched in the specified
48 * order; otherwise it will be searched after TEMP tables and *before* the
49 * explicit list. (It might seem that the system namespace should be
50 * implicitly last, but this behavior appears to be required by SQL99.
51 * Also, this provides a way to search the system namespace first without
52 * thereby making it the default creation target namespace.)
54 * The default creation target namespace is kept equal to the first element
55 * of the explicit list, or is the system namespace if the list is empty.
57 * In bootstrap mode or a standalone backend, the default search path is
58 * empty, so that the system namespace is the only one searched or inserted
59 * into. In multiuser mode, the default search path contains the PG_PUBLIC
60 * namespace, preceded by the user's own namespace if one exists.
63 static List *namespaceSearchPath = NIL;
65 /* this flag must be updated correctly when namespaceSearchPath is changed */
66 static bool pathContainsSystemNamespace = false;
68 /* default place to create stuff */
69 static Oid defaultCreationNamespace = PG_CATALOG_NAMESPACE;
72 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
73 * in a particular backend session (this happens when a CREATE TEMP TABLE
74 * command is first executed). Thereafter it's the OID of the temp namespace.
76 static Oid myTempNamespace = InvalidOid;
79 * This is the text equivalent of the search path --- it's the value
80 * of the GUC variable 'search_path'.
82 char *namespace_search_path = NULL;
86 * Deletion ordering constraint item.
88 typedef struct DelConstraint
90 Oid referencer; /* table to delete first */
91 Oid referencee; /* table to delete second */
92 int pred; /* workspace for TopoSortRels */
93 struct DelConstraint *link; /* workspace for TopoSortRels */
98 static Oid GetTempTableNamespace(void);
99 static void RemoveTempRelations(Oid tempNamespaceId);
100 static List *FindTempRelations(Oid tempNamespaceId);
101 static List *FindDeletionConstraints(List *relOids);
102 static List *TopoSortRels(List *relOids, List *constraintList);
103 static void RemoveTempRelationsCallback(void);
108 * Given a RangeVar describing an existing relation,
109 * select the proper namespace and look up the relation OID.
111 * If the relation is not found, return InvalidOid if failOK = true,
112 * otherwise raise an error.
115 RangeVarGetRelid(const RangeVar *relation, bool failOK)
121 * We check the catalog name and then ignore it.
123 if (relation->catalogname)
125 if (strcmp(relation->catalogname, DatabaseName) != 0)
126 elog(ERROR, "Cross-database references are not implemented");
129 if (relation->schemaname)
131 /* use exact schema given */
132 namespaceId = GetSysCacheOid(NAMESPACENAME,
133 CStringGetDatum(relation->schemaname),
135 if (!OidIsValid(namespaceId))
136 elog(ERROR, "Namespace \"%s\" does not exist",
137 relation->schemaname);
138 relId = get_relname_relid(relation->relname, namespaceId);
142 /* search the namespace path */
143 relId = RelnameGetRelid(relation->relname);
146 if (!OidIsValid(relId) && !failOK)
148 if (relation->schemaname)
149 elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
150 relation->schemaname, relation->relname);
152 elog(ERROR, "Relation \"%s\" does not exist",
159 * RangeVarGetCreationNamespace
160 * Given a RangeVar describing a to-be-created relation,
161 * choose which namespace to create it in.
163 * Note: calling this may result in a CommandCounterIncrement operation.
164 * That will happen on the first request for a temp table in any particular
165 * backend run; we will need to either create or clean out the temp schema.
168 RangeVarGetCreationNamespace(const RangeVar *newRelation)
173 * We check the catalog name and then ignore it.
175 if (newRelation->catalogname)
177 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
178 elog(ERROR, "Cross-database references are not implemented");
181 if (newRelation->istemp)
183 /* TEMP tables are created in our backend-local temp namespace */
184 if (newRelation->schemaname)
185 elog(ERROR, "TEMP tables may not specify a namespace");
186 /* Initialize temp namespace if first time through */
187 if (!OidIsValid(myTempNamespace))
188 myTempNamespace = GetTempTableNamespace();
189 return myTempNamespace;
192 if (newRelation->schemaname)
194 /* use exact schema given */
195 namespaceId = GetSysCacheOid(NAMESPACENAME,
196 CStringGetDatum(newRelation->schemaname),
198 if (!OidIsValid(namespaceId))
199 elog(ERROR, "Namespace \"%s\" does not exist",
200 newRelation->schemaname);
204 /* use the default creation namespace */
205 namespaceId = defaultCreationNamespace;
213 * Try to resolve an unqualified relation name.
214 * Returns OID if relation found in search path, else InvalidOid.
217 RelnameGetRelid(const char *relname)
223 * If a TEMP-table namespace has been set up, it is implicitly first
224 * in the search path.
226 if (OidIsValid(myTempNamespace))
228 relid = get_relname_relid(relname, myTempNamespace);
229 if (OidIsValid(relid))
234 * If system namespace is not in path, implicitly search it before path
236 if (!pathContainsSystemNamespace)
238 relid = get_relname_relid(relname, PG_CATALOG_NAMESPACE);
239 if (OidIsValid(relid))
244 * Else search the path
246 foreach(lptr, namespaceSearchPath)
248 Oid namespaceId = (Oid) lfirsti(lptr);
250 relid = get_relname_relid(relname, namespaceId);
251 if (OidIsValid(relid))
255 /* Not found in path */
261 * Try to resolve an unqualified datatype name.
262 * Returns OID if type found in search path, else InvalidOid.
264 * This is essentially the same as RelnameGetRelid, but we never search
265 * the TEMP table namespace --- there is no reason to refer to the types
266 * of temp tables, AFAICS.
269 TypenameGetTypid(const char *typname)
275 * If system namespace is not in path, implicitly search it before path
277 if (!pathContainsSystemNamespace)
279 typid = GetSysCacheOid(TYPENAMENSP,
280 PointerGetDatum(typname),
281 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
283 if (OidIsValid(typid))
288 * Else search the path
290 foreach(lptr, namespaceSearchPath)
292 Oid namespaceId = (Oid) lfirsti(lptr);
294 typid = GetSysCacheOid(TYPENAMENSP,
295 PointerGetDatum(typname),
296 ObjectIdGetDatum(namespaceId),
298 if (OidIsValid(typid))
302 /* Not found in path */
307 * FuncnameGetCandidates
308 * Given a possibly-qualified function name and argument count,
309 * retrieve a list of the possible matches.
311 * We search a single namespace if the function name is qualified, else
312 * all namespaces in the search path. The return list will never contain
313 * multiple entries with identical argument types --- in the multiple-
314 * namespace case, we arrange for entries in earlier namespaces to mask
315 * identical entries in later namespaces.
318 FuncnameGetCandidates(List *names, int nargs)
320 FuncCandidateList resultList = NULL;
322 char *schemaname = NULL;
323 char *funcname = NULL;
328 /* deconstruct the name list */
329 switch (length(names))
332 funcname = strVal(lfirst(names));
335 schemaname = strVal(lfirst(names));
336 funcname = strVal(lsecond(names));
339 catalogname = strVal(lfirst(names));
340 schemaname = strVal(lsecond(names));
341 funcname = strVal(lfirst(lnext(lnext(names))));
343 * We check the catalog name and then ignore it.
345 if (strcmp(catalogname, DatabaseName) != 0)
346 elog(ERROR, "Cross-database references are not implemented");
349 elog(ERROR, "Improper qualified name (too many dotted names)");
355 /* use exact schema given */
356 namespaceId = GetSysCacheOid(NAMESPACENAME,
357 CStringGetDatum(schemaname),
359 if (!OidIsValid(namespaceId))
360 elog(ERROR, "Namespace \"%s\" does not exist",
365 /* flag to indicate we need namespace search */
366 namespaceId = InvalidOid;
369 /* Search syscache by name and nargs only */
370 catlist = SearchSysCacheList(PROCNAME, 2,
371 CStringGetDatum(funcname),
372 Int16GetDatum(nargs),
375 for (i = 0; i < catlist->n_members; i++)
377 HeapTuple proctup = &catlist->members[i]->tuple;
378 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
380 FuncCandidateList newResult;
382 if (OidIsValid(namespaceId))
384 /* Consider only procs in specified namespace */
385 if (procform->pronamespace != namespaceId)
387 /* No need to check args, they must all be different */
391 /* Consider only procs that are in the search path */
392 if (pathContainsSystemNamespace ||
393 procform->pronamespace != PG_CATALOG_NAMESPACE)
397 foreach(nsp, namespaceSearchPath)
400 if (procform->pronamespace == (Oid) lfirsti(nsp))
404 continue; /* proc is not in search path */
408 * Okay, it's in the search path, but does it have the same
409 * arguments as something we already accepted? If so, keep
410 * only the one that appears earlier in the search path.
412 * If we have an ordered list from SearchSysCacheList (the
413 * normal case), then any conflicting proc must immediately
414 * adjoin this one in the list, so we only need to look at
415 * the newest result item. If we have an unordered list,
416 * we have to scan the whole result list.
420 FuncCandidateList prevResult;
422 if (catlist->ordered)
424 if (memcmp(procform->proargtypes, resultList->args,
425 nargs * sizeof(Oid)) == 0)
426 prevResult = resultList;
432 for (prevResult = resultList;
434 prevResult = prevResult->next)
436 if (memcmp(procform->proargtypes, prevResult->args,
437 nargs * sizeof(Oid)) == 0)
443 /* We have a match with a previous result */
444 Assert(pathpos != prevResult->pathpos);
445 if (pathpos > prevResult->pathpos)
446 continue; /* keep previous result */
447 /* replace previous result */
448 prevResult->pathpos = pathpos;
449 prevResult->oid = proctup->t_data->t_oid;
450 continue; /* args are same, of course */
456 * Okay to add it to result list
458 newResult = (FuncCandidateList)
459 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
460 + nargs * sizeof(Oid));
461 newResult->pathpos = pathpos;
462 newResult->oid = proctup->t_data->t_oid;
463 memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
465 newResult->next = resultList;
466 resultList = newResult;
469 ReleaseSysCacheList(catlist);
475 * QualifiedNameGetCreationNamespace
476 * Given a possibly-qualified name for an object (in List-of-Values
477 * format), determine what namespace the object should be created in.
478 * Also extract and return the object name (last component of list).
480 * This is *not* used for tables. Hence, the TEMP table namespace is
481 * never selected as the creation target.
484 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
487 char *schemaname = NULL;
488 char *objname = NULL;
491 /* deconstruct the name list */
492 switch (length(names))
495 objname = strVal(lfirst(names));
498 schemaname = strVal(lfirst(names));
499 objname = strVal(lsecond(names));
502 catalogname = strVal(lfirst(names));
503 schemaname = strVal(lsecond(names));
504 objname = strVal(lfirst(lnext(lnext(names))));
506 * We check the catalog name and then ignore it.
508 if (strcmp(catalogname, DatabaseName) != 0)
509 elog(ERROR, "Cross-database references are not implemented");
512 elog(ERROR, "Improper qualified name (too many dotted names)");
518 /* use exact schema given */
519 namespaceId = GetSysCacheOid(NAMESPACENAME,
520 CStringGetDatum(schemaname),
522 if (!OidIsValid(namespaceId))
523 elog(ERROR, "Namespace \"%s\" does not exist",
528 /* use the default creation namespace */
529 namespaceId = defaultCreationNamespace;
532 *objname_p = objname;
537 * makeRangeVarFromNameList
538 * Utility routine to convert a qualified-name list into RangeVar form.
541 makeRangeVarFromNameList(List *names)
543 RangeVar *rel = makeRangeVar(NULL, NULL);
545 switch (length(names))
548 rel->relname = strVal(lfirst(names));
551 rel->schemaname = strVal(lfirst(names));
552 rel->relname = strVal(lsecond(names));
555 rel->catalogname = strVal(lfirst(names));
556 rel->schemaname = strVal(lsecond(names));
557 rel->relname = strVal(lfirst(lnext(lnext(names))));
560 elog(ERROR, "Improper relation name (too many dotted names)");
568 * isTempNamespace - is the given namespace my temporary-table namespace?
571 isTempNamespace(Oid namespaceId)
573 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
579 * GetTempTableNamespace
580 * Initialize temp table namespace on first use in a particular backend
583 GetTempTableNamespace(void)
585 char namespaceName[NAMEDATALEN];
588 snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
590 namespaceId = GetSysCacheOid(NAMESPACENAME,
591 CStringGetDatum(namespaceName),
593 if (!OidIsValid(namespaceId))
596 * First use of this temp namespace in this database; create it.
597 * The temp namespaces are always owned by the superuser.
599 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
600 /* Advance command counter to make namespace visible */
601 CommandCounterIncrement();
606 * If the namespace already exists, clean it out (in case the
607 * former owner crashed without doing so).
609 RemoveTempRelations(namespaceId);
613 * Register exit callback to clean out temp tables at backend shutdown.
615 on_shmem_exit(RemoveTempRelationsCallback, 0);
621 * Remove all relations in the specified temp namespace.
623 * This is called at backend shutdown (if we made any temp relations).
624 * It is also called when we begin using a pre-existing temp namespace,
625 * in order to clean out any relations that might have been created by
629 RemoveTempRelations(Oid tempNamespaceId)
632 List *constraintList;
635 /* Get a list of relations to delete */
636 tempRelList = FindTempRelations(tempNamespaceId);
638 if (tempRelList == NIL)
639 return; /* nothing to do */
641 /* If more than one, sort them to respect any deletion-order constraints */
642 if (length(tempRelList) > 1)
644 constraintList = FindDeletionConstraints(tempRelList);
645 if (constraintList != NIL)
646 tempRelList = TopoSortRels(tempRelList, constraintList);
649 /* Scan the list and delete all entries */
650 foreach(lptr, tempRelList)
652 Oid reloid = (Oid) lfirsti(lptr);
654 heap_drop_with_catalog(reloid, true);
656 * Advance cmd counter to make catalog changes visible, in case
657 * a later entry depends on this one.
659 CommandCounterIncrement();
664 * Find all relations in the specified temp namespace.
666 * Returns a list of relation OIDs.
669 FindTempRelations(Oid tempNamespaceId)
671 List *tempRelList = NIL;
678 * Scan pg_class to find all the relations in the target namespace.
679 * Ignore indexes, though, on the assumption that they'll go away
680 * when their tables are deleted.
682 ScanKeyEntryInitialize(&key, 0x0,
683 Anum_pg_class_relnamespace,
685 ObjectIdGetDatum(tempNamespaceId));
687 pgclass = heap_openr(RelationRelationName, AccessShareLock);
688 scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
690 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
692 switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
694 case RELKIND_RELATION:
695 case RELKIND_SEQUENCE:
697 tempRelList = lconsi(tuple->t_data->t_oid, tempRelList);
705 heap_close(pgclass, AccessShareLock);
711 * Find deletion-order constraints involving the given relation OIDs.
713 * Returns a list of DelConstraint objects.
716 FindDeletionConstraints(List *relOids)
718 List *constraintList = NIL;
719 Relation inheritsrel;
724 * Scan pg_inherits to find parents and children that are in the list.
726 inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
727 scan = heap_beginscan(inheritsrel, 0, SnapshotNow, 0, NULL);
729 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
731 Oid inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
732 Oid inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
734 if (intMember(inhrelid, relOids) && intMember(inhparent, relOids))
738 item = (DelConstraint *) palloc(sizeof(DelConstraint));
739 item->referencer = inhrelid;
740 item->referencee = inhparent;
741 constraintList = lcons(item, constraintList);
746 heap_close(inheritsrel, AccessShareLock);
748 return constraintList;
752 * TopoSortRels -- topological sort of a list of rels to delete
754 * This is a lot simpler and slower than, for example, the topological sort
755 * algorithm shown in Knuth's Volume 1. However, we are not likely to be
756 * working with more than a few constraints, so the apparent slowness of the
757 * algorithm won't really matter.
760 TopoSortRels(List *relOids, List *constraintList)
762 int queue_size = length(relOids);
764 int *beforeConstraints;
765 DelConstraint **afterConstraints;
766 List *resultList = NIL;
773 /* Allocate workspace */
774 rels = (Oid *) palloc(queue_size * sizeof(Oid));
775 beforeConstraints = (int *) palloc(queue_size * sizeof(int));
776 afterConstraints = (DelConstraint **)
777 palloc(queue_size * sizeof(DelConstraint*));
779 /* Build an array of the target relation OIDs */
781 foreach(lptr, relOids)
783 rels[i++] = (Oid) lfirsti(lptr);
787 * Scan the constraints, and for each rel in the array, generate a
788 * count of the number of constraints that say it must be before
789 * something else, plus a list of the constraints that say it must be
790 * after something else. The count for the j'th rel is stored in
791 * beforeConstraints[j], and the head of its list in
792 * afterConstraints[j]. Each constraint stores its list link in
793 * its link field (note any constraint will be in just one list).
794 * The array index for the before-rel of each constraint is
795 * remembered in the constraint's pred field.
797 MemSet(beforeConstraints, 0, queue_size * sizeof(int));
798 MemSet(afterConstraints, 0, queue_size * sizeof(DelConstraint*));
799 foreach(lptr, constraintList)
801 DelConstraint *constraint = (DelConstraint *) lfirst(lptr);
804 /* Find the referencer rel in the array */
805 rel = constraint->referencer;
806 for (j = queue_size; --j >= 0;)
811 Assert(j >= 0); /* should have found a match */
812 /* Find the referencee rel in the array */
813 rel = constraint->referencee;
814 for (k = queue_size; --k >= 0;)
819 Assert(k >= 0); /* should have found a match */
820 beforeConstraints[j]++; /* referencer must come before */
821 /* add this constraint to list of after-constraints for referencee */
822 constraint->pred = j;
823 constraint->link = afterConstraints[k];
824 afterConstraints[k] = constraint;
826 /*--------------------
827 * Now scan the rels array backwards. At each step, output the
828 * last rel that has no remaining before-constraints, and decrease
829 * the beforeConstraints count of each of the rels it was constrained
830 * against. (This is the right order since we are building the result
831 * list back-to-front.)
832 * i = counter for number of rels left to output
833 * j = search index for rels[]
834 * dc = temp for scanning constraint list for rel j
835 * last = last valid index in rels (avoid redundant searches)
836 *--------------------
838 last = queue_size - 1;
839 for (i = queue_size; --i >= 0;)
843 /* Find next candidate to output */
844 while (rels[last] == InvalidOid)
846 for (j = last; j >= 0; j--)
848 if (rels[j] != InvalidOid && beforeConstraints[j] == 0)
851 /* If no available candidate, topological sort fails */
853 elog(ERROR, "TopoSortRels: failed to find a workable deletion ordering");
854 /* Output candidate, and mark it done by zeroing rels[] entry */
855 resultList = lconsi(rels[j], resultList);
856 rels[j] = InvalidOid;
857 /* Update beforeConstraints counts of its predecessors */
858 for (dc = afterConstraints[j]; dc; dc = dc->link)
859 beforeConstraints[dc->pred]--;
867 * Callback to remove temp relations at backend exit.
870 RemoveTempRelationsCallback(void)
872 if (OidIsValid(myTempNamespace)) /* should always be true */
874 /* Need to ensure we have a usable transaction. */
875 AbortOutOfAnyTransaction();
876 StartTransactionCommand();
878 RemoveTempRelations(myTempNamespace);
880 CommitTransactionCommand();
885 * Routines for handling the GUC variable 'search_path'.
888 /* parse_hook: is proposed value valid? */
890 check_search_path(const char *proposed)
896 /* Need a modifiable copy of string */
897 rawname = pstrdup(proposed);
899 /* Parse string into list of identifiers */
900 if (!SplitIdentifierString(rawname, ',', &namelist))
902 /* syntax error in name list */
909 * If we aren't inside a transaction, we cannot do database access so
910 * cannot verify the individual names. Must accept the list on faith.
911 * (This case can happen, for example, when the postmaster reads a
912 * search_path setting from postgresql.conf.)
914 if (!IsTransactionState())
922 * Verify that all the names are either valid namespace names or "$user".
923 * (We do not require $user to correspond to a valid namespace; should we?)
927 char *curname = (char *) lfirst(l);
929 if (strcmp(curname, "$user") == 0)
931 if (!SearchSysCacheExists(NAMESPACENAME,
932 CStringGetDatum(curname),
947 /* assign_hook: do extra actions needed when assigning to search_path */
949 assign_search_path(const char *newval)
956 MemoryContext oldcxt;
959 * If we aren't inside a transaction, we cannot do database access so
960 * cannot look up the names. In this case, do nothing; the internal
961 * search path will be fixed later by InitializeSearchPath. (We assume
962 * this situation can only happen in the postmaster or early in backend
965 if (!IsTransactionState())
968 /* Need a modifiable copy of string */
969 rawname = pstrdup(newval);
971 /* Parse string into list of identifiers */
972 if (!SplitIdentifierString(rawname, ',', &namelist))
974 /* syntax error in name list */
975 /* this should not happen if GUC checked check_search_path */
976 elog(ERROR, "assign_search_path: invalid list syntax");
980 * Convert the list of names to a list of OIDs. If any names are not
981 * recognizable, just leave them out of the list. (This is our only
982 * reasonable recourse when the already-accepted default is bogus.)
987 char *curname = (char *) lfirst(l);
990 if (strcmp(curname, "$user") == 0)
992 /* $user --- substitute namespace matching user name, if any */
995 tuple = SearchSysCache(SHADOWSYSID,
996 ObjectIdGetDatum(GetSessionUserId()),
998 if (HeapTupleIsValid(tuple))
1002 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1003 namespaceId = GetSysCacheOid(NAMESPACENAME,
1004 CStringGetDatum(uname),
1006 if (OidIsValid(namespaceId))
1007 oidlist = lappendi(oidlist, namespaceId);
1008 ReleaseSysCache(tuple);
1013 /* normal namespace reference */
1014 namespaceId = GetSysCacheOid(NAMESPACENAME,
1015 CStringGetDatum(curname),
1017 if (OidIsValid(namespaceId))
1018 oidlist = lappendi(oidlist, namespaceId);
1023 * Now that we've successfully built the new list of namespace OIDs,
1024 * save it in permanent storage.
1026 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1027 newpath = listCopy(oidlist);
1028 MemoryContextSwitchTo(oldcxt);
1030 /* Now safe to assign to state variable. */
1031 freeList(namespaceSearchPath);
1032 namespaceSearchPath = newpath;
1035 * Update info derived from search path.
1037 pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE,
1038 namespaceSearchPath);
1040 if (namespaceSearchPath == NIL)
1041 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1043 defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath);
1052 * InitializeSearchPath: initialize module during InitPostgres.
1054 * This is called after we are up enough to be able to do catalog lookups.
1057 InitializeSearchPath(void)
1060 * In normal multi-user mode, we want the default search path to be
1061 * '$user,public' (or as much of that as exists, anyway; see the
1062 * error handling in assign_search_path); which is what guc.c has as
1063 * the wired-in default value. But in bootstrap or standalone-backend
1064 * mode, the default search path must be empty so that initdb correctly
1065 * creates everything in PG_CATALOG_NAMESPACE. Accordingly, adjust the
1066 * default setting if we are not running under postmaster. (If a
1067 * non-default setting has been supplied, this will not overwrite it.)
1069 if (!IsUnderPostmaster)
1071 SetConfigOption("search_path", "",
1072 PGC_POSTMASTER, PGC_S_DEFAULT);
1075 * If a search path setting was provided before we were able to execute
1076 * lookups, establish the internal search path now.
1078 if (namespace_search_path && *namespace_search_path &&
1079 namespaceSearchPath == NIL)
1080 assign_search_path(namespace_search_path);