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.22 2002/05/20 23:51:41 tgl Exp $
18 *-------------------------------------------------------------------------
22 #include "access/heapam.h"
23 #include "access/xact.h"
24 #include "catalog/catalog.h"
25 #include "catalog/catname.h"
26 #include "catalog/heap.h"
27 #include "catalog/namespace.h"
28 #include "catalog/pg_inherits.h"
29 #include "catalog/pg_namespace.h"
30 #include "catalog/pg_opclass.h"
31 #include "catalog/pg_operator.h"
32 #include "catalog/pg_proc.h"
33 #include "catalog/pg_shadow.h"
34 #include "catalog/pg_type.h"
35 #include "lib/stringinfo.h"
36 #include "miscadmin.h"
37 #include "nodes/makefuncs.h"
38 #include "storage/backendid.h"
39 #include "storage/ipc.h"
40 #include "utils/acl.h"
41 #include "utils/builtins.h"
42 #include "utils/catcache.h"
43 #include "utils/fmgroids.h"
44 #include "utils/guc.h"
45 #include "utils/inval.h"
46 #include "utils/lsyscache.h"
47 #include "utils/syscache.h"
51 * The namespace search path is a possibly-empty list of namespace OIDs.
52 * In addition to the explicit list, several implicitly-searched namespaces
55 * 1. If a "special" namespace has been set by PushSpecialNamespace, it is
56 * always searched first. (This is a hack for CREATE SCHEMA.)
58 * 2. If a TEMP table namespace has been initialized in this session, it
59 * is always searched just after any special namespace.
61 * 3. The system catalog namespace is always searched. If the system
62 * namespace is present in the explicit path then it will be searched in
63 * the specified order; otherwise it will be searched after TEMP tables and
64 * *before* the explicit list. (It might seem that the system namespace
65 * should be implicitly last, but this behavior appears to be required by
66 * SQL99. Also, this provides a way to search the system namespace first
67 * without thereby making it the default creation target namespace.)
69 * The default creation target namespace is normally equal to the first
70 * element of the explicit list, but is the "special" namespace when one
71 * has been set. If the explicit list is empty and there is no special
72 * namespace, there is no default target.
74 * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
75 * the system namespace is the only one searched or inserted into.
76 * The initdb script is also careful to set search_path to 'pg_catalog' for
77 * its post-bootstrap standalone backend runs. Otherwise the default search
78 * path is determined by GUC. The factory default path contains the PUBLIC
79 * namespace (if it exists), preceded by the user's personal namespace
82 * If namespaceSearchPathValid is false, then namespaceSearchPath (and other
83 * derived variables) need to be recomputed from namespace_search_path.
84 * We mark it invalid upon an assignment to namespace_search_path or receipt
85 * of a syscache invalidation event for pg_namespace. The recomputation
86 * is done during the next lookup attempt.
88 * Any namespaces mentioned in namespace_search_path that are not readable
89 * by the current user ID are simply left out of namespaceSearchPath; so
90 * we have to be willing to recompute the path when current userid changes.
91 * namespaceUser is the userid the path has been computed for.
94 static List *namespaceSearchPath = NIL;
96 static Oid namespaceUser = InvalidOid;
98 /* default place to create stuff; if InvalidOid, no default */
99 static Oid defaultCreationNamespace = InvalidOid;
101 /* first explicit member of list; usually same as defaultCreationNamespace */
102 static Oid firstExplicitNamespace = InvalidOid;
104 /* The above four values are valid only if namespaceSearchPathValid */
105 static bool namespaceSearchPathValid = true;
108 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
109 * in a particular backend session (this happens when a CREATE TEMP TABLE
110 * command is first executed). Thereafter it's the OID of the temp namespace.
111 * firstTempTransaction flags whether we've committed creation of the TEMP
114 static Oid myTempNamespace = InvalidOid;
116 static bool firstTempTransaction = false;
119 * "Special" namespace for CREATE SCHEMA. If set, it's the first search
120 * path element, and also the default creation namespace.
122 static Oid mySpecialNamespace = InvalidOid;
125 * This is the text equivalent of the search path --- it's the value
126 * of the GUC variable 'search_path'.
128 char *namespace_search_path = NULL;
132 * Deletion ordering constraint item.
134 typedef struct DelConstraint
136 Oid referencer; /* table to delete first */
137 Oid referencee; /* table to delete second */
138 int pred; /* workspace for TopoSortRels */
139 struct DelConstraint *link; /* workspace for TopoSortRels */
143 /* Local functions */
144 static void recomputeNamespacePath(void);
145 static void InitTempTableNamespace(void);
146 static void RemoveTempRelations(Oid tempNamespaceId);
147 static List *FindTempRelations(Oid tempNamespaceId);
148 static List *FindDeletionConstraints(List *relOids);
149 static List *TopoSortRels(List *relOids, List *constraintList);
150 static void RemoveTempRelationsCallback(void);
151 static void NamespaceCallback(Datum arg, Oid relid);
156 * Given a RangeVar describing an existing relation,
157 * select the proper namespace and look up the relation OID.
159 * If the relation is not found, return InvalidOid if failOK = true,
160 * otherwise raise an error.
163 RangeVarGetRelid(const RangeVar *relation, bool failOK)
169 * We check the catalog name and then ignore it.
171 if (relation->catalogname)
173 if (strcmp(relation->catalogname, DatabaseName) != 0)
174 elog(ERROR, "Cross-database references are not implemented");
177 if (relation->schemaname)
179 /* use exact schema given */
182 namespaceId = GetSysCacheOid(NAMESPACENAME,
183 CStringGetDatum(relation->schemaname),
185 if (!OidIsValid(namespaceId))
186 elog(ERROR, "Namespace \"%s\" does not exist",
187 relation->schemaname);
188 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
189 if (aclresult != ACLCHECK_OK)
190 aclcheck_error(aclresult, relation->schemaname);
192 relId = get_relname_relid(relation->relname, namespaceId);
196 /* search the namespace path */
197 relId = RelnameGetRelid(relation->relname);
200 if (!OidIsValid(relId) && !failOK)
202 if (relation->schemaname)
203 elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
204 relation->schemaname, relation->relname);
206 elog(ERROR, "Relation \"%s\" does not exist",
213 * RangeVarGetCreationNamespace
214 * Given a RangeVar describing a to-be-created relation,
215 * choose which namespace to create it in.
217 * Note: calling this may result in a CommandCounterIncrement operation.
218 * That will happen on the first request for a temp table in any particular
219 * backend run; we will need to either create or clean out the temp schema.
222 RangeVarGetCreationNamespace(const RangeVar *newRelation)
227 * We check the catalog name and then ignore it.
229 if (newRelation->catalogname)
231 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
232 elog(ERROR, "Cross-database references are not implemented");
235 if (newRelation->istemp)
237 /* TEMP tables are created in our backend-local temp namespace */
238 if (newRelation->schemaname)
239 elog(ERROR, "TEMP tables may not specify a namespace");
240 /* Initialize temp namespace if first time through */
241 if (!OidIsValid(myTempNamespace))
242 InitTempTableNamespace();
243 return myTempNamespace;
246 if (newRelation->schemaname)
248 /* use exact schema given */
249 namespaceId = GetSysCacheOid(NAMESPACENAME,
250 CStringGetDatum(newRelation->schemaname),
252 if (!OidIsValid(namespaceId))
253 elog(ERROR, "Namespace \"%s\" does not exist",
254 newRelation->schemaname);
258 /* use the default creation namespace */
259 recomputeNamespacePath();
260 namespaceId = defaultCreationNamespace;
261 if (!OidIsValid(namespaceId))
262 elog(ERROR, "No namespace has been selected to create in");
265 /* Note: callers will check for CREATE rights when appropriate */
272 * Try to resolve an unqualified relation name.
273 * Returns OID if relation found in search path, else InvalidOid.
276 RelnameGetRelid(const char *relname)
281 recomputeNamespacePath();
283 foreach(lptr, namespaceSearchPath)
285 Oid namespaceId = (Oid) lfirsti(lptr);
287 relid = get_relname_relid(relname, namespaceId);
288 if (OidIsValid(relid))
292 /* Not found in path */
298 * Determine whether a relation (identified by OID) is visible in the
299 * current search path. Visible means "would be found by searching
300 * for the unqualified relation name".
303 RelationIsVisible(Oid relid)
306 Form_pg_class relform;
310 reltup = SearchSysCache(RELOID,
311 ObjectIdGetDatum(relid),
313 if (!HeapTupleIsValid(reltup))
314 elog(ERROR, "Cache lookup failed for relation %u", relid);
315 relform = (Form_pg_class) GETSTRUCT(reltup);
317 recomputeNamespacePath();
320 * Quick check: if it ain't in the path at all, it ain't visible.
321 * Items in the system namespace are surely in the path and so we
322 * needn't even do intMember() for them.
324 relnamespace = relform->relnamespace;
325 if (relnamespace != PG_CATALOG_NAMESPACE &&
326 !intMember(relnamespace, namespaceSearchPath))
331 * If it is in the path, it might still not be visible; it could be
332 * hidden by another relation of the same name earlier in the path.
333 * So we must do a slow check to see if this rel would be found by
336 char *relname = NameStr(relform->relname);
338 visible = (RelnameGetRelid(relname) == relid);
341 ReleaseSysCache(reltup);
349 * Try to resolve an unqualified datatype name.
350 * Returns OID if type found in search path, else InvalidOid.
352 * This is essentially the same as RelnameGetRelid.
355 TypenameGetTypid(const char *typname)
360 recomputeNamespacePath();
362 foreach(lptr, namespaceSearchPath)
364 Oid namespaceId = (Oid) lfirsti(lptr);
366 typid = GetSysCacheOid(TYPENAMENSP,
367 PointerGetDatum(typname),
368 ObjectIdGetDatum(namespaceId),
370 if (OidIsValid(typid))
374 /* Not found in path */
380 * Determine whether a type (identified by OID) is visible in the
381 * current search path. Visible means "would be found by searching
382 * for the unqualified type name".
385 TypeIsVisible(Oid typid)
388 Form_pg_type typform;
392 typtup = SearchSysCache(TYPEOID,
393 ObjectIdGetDatum(typid),
395 if (!HeapTupleIsValid(typtup))
396 elog(ERROR, "Cache lookup failed for type %u", typid);
397 typform = (Form_pg_type) GETSTRUCT(typtup);
399 recomputeNamespacePath();
402 * Quick check: if it ain't in the path at all, it ain't visible.
403 * Items in the system namespace are surely in the path and so we
404 * needn't even do intMember() for them.
406 typnamespace = typform->typnamespace;
407 if (typnamespace != PG_CATALOG_NAMESPACE &&
408 !intMember(typnamespace, namespaceSearchPath))
413 * If it is in the path, it might still not be visible; it could be
414 * hidden by another type of the same name earlier in the path.
415 * So we must do a slow check to see if this type would be found by
418 char *typname = NameStr(typform->typname);
420 visible = (TypenameGetTypid(typname) == typid);
423 ReleaseSysCache(typtup);
430 * FuncnameGetCandidates
431 * Given a possibly-qualified function name and argument count,
432 * retrieve a list of the possible matches.
434 * If nargs is -1, we return all functions matching the given name,
435 * regardless of argument count.
437 * We search a single namespace if the function name is qualified, else
438 * all namespaces in the search path. The return list will never contain
439 * multiple entries with identical argument lists --- in the multiple-
440 * namespace case, we arrange for entries in earlier namespaces to mask
441 * identical entries in later namespaces.
444 FuncnameGetCandidates(List *names, int nargs)
446 FuncCandidateList resultList = NULL;
448 char *schemaname = NULL;
449 char *funcname = NULL;
454 /* deconstruct the name list */
455 switch (length(names))
458 funcname = strVal(lfirst(names));
461 schemaname = strVal(lfirst(names));
462 funcname = strVal(lsecond(names));
465 catalogname = strVal(lfirst(names));
466 schemaname = strVal(lsecond(names));
467 funcname = strVal(lfirst(lnext(lnext(names))));
469 * We check the catalog name and then ignore it.
471 if (strcmp(catalogname, DatabaseName) != 0)
472 elog(ERROR, "Cross-database references are not implemented");
475 elog(ERROR, "Improper qualified name (too many dotted names): %s",
476 NameListToString(names));
482 /* use exact schema given */
485 namespaceId = GetSysCacheOid(NAMESPACENAME,
486 CStringGetDatum(schemaname),
488 if (!OidIsValid(namespaceId))
489 elog(ERROR, "Namespace \"%s\" does not exist",
491 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
492 if (aclresult != ACLCHECK_OK)
493 aclcheck_error(aclresult, schemaname);
497 /* flag to indicate we need namespace search */
498 namespaceId = InvalidOid;
499 recomputeNamespacePath();
502 /* Search syscache by name and (optionally) nargs only */
504 catlist = SearchSysCacheList(PROCNAMENSP, 2,
505 CStringGetDatum(funcname),
506 Int16GetDatum(nargs),
509 catlist = SearchSysCacheList(PROCNAMENSP, 1,
510 CStringGetDatum(funcname),
513 for (i = 0; i < catlist->n_members; i++)
515 HeapTuple proctup = &catlist->members[i]->tuple;
516 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
518 FuncCandidateList newResult;
520 nargs = procform->pronargs;
522 if (OidIsValid(namespaceId))
524 /* Consider only procs in specified namespace */
525 if (procform->pronamespace != namespaceId)
527 /* No need to check args, they must all be different */
531 /* Consider only procs that are in the search path */
534 foreach(nsp, namespaceSearchPath)
536 if (procform->pronamespace == (Oid) lfirsti(nsp))
541 continue; /* proc is not in search path */
544 * Okay, it's in the search path, but does it have the same
545 * arguments as something we already accepted? If so, keep
546 * only the one that appears earlier in the search path.
548 * If we have an ordered list from SearchSysCacheList (the
549 * normal case), then any conflicting proc must immediately
550 * adjoin this one in the list, so we only need to look at
551 * the newest result item. If we have an unordered list,
552 * we have to scan the whole result list.
556 FuncCandidateList prevResult;
558 if (catlist->ordered)
560 if (nargs == resultList->nargs &&
561 memcmp(procform->proargtypes, resultList->args,
562 nargs * sizeof(Oid)) == 0)
563 prevResult = resultList;
569 for (prevResult = resultList;
571 prevResult = prevResult->next)
573 if (nargs == prevResult->nargs &&
574 memcmp(procform->proargtypes, prevResult->args,
575 nargs * sizeof(Oid)) == 0)
581 /* We have a match with a previous result */
582 Assert(pathpos != prevResult->pathpos);
583 if (pathpos > prevResult->pathpos)
584 continue; /* keep previous result */
585 /* replace previous result */
586 prevResult->pathpos = pathpos;
587 prevResult->oid = proctup->t_data->t_oid;
588 continue; /* args are same, of course */
594 * Okay to add it to result list
596 newResult = (FuncCandidateList)
597 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
598 + nargs * sizeof(Oid));
599 newResult->pathpos = pathpos;
600 newResult->oid = proctup->t_data->t_oid;
601 newResult->nargs = nargs;
602 memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
604 newResult->next = resultList;
605 resultList = newResult;
608 ReleaseSysCacheList(catlist);
615 * Determine whether a function (identified by OID) is visible in the
616 * current search path. Visible means "would be found by searching
617 * for the unqualified function name with exact argument matches".
620 FunctionIsVisible(Oid funcid)
623 Form_pg_proc procform;
627 proctup = SearchSysCache(PROCOID,
628 ObjectIdGetDatum(funcid),
630 if (!HeapTupleIsValid(proctup))
631 elog(ERROR, "Cache lookup failed for procedure %u", funcid);
632 procform = (Form_pg_proc) GETSTRUCT(proctup);
634 recomputeNamespacePath();
637 * Quick check: if it ain't in the path at all, it ain't visible.
638 * Items in the system namespace are surely in the path and so we
639 * needn't even do intMember() for them.
641 pronamespace = procform->pronamespace;
642 if (pronamespace != PG_CATALOG_NAMESPACE &&
643 !intMember(pronamespace, namespaceSearchPath))
648 * If it is in the path, it might still not be visible; it could be
649 * hidden by another proc of the same name and arguments earlier
650 * in the path. So we must do a slow check to see if this is the
651 * same proc that would be found by FuncnameGetCandidates.
653 char *proname = NameStr(procform->proname);
654 int nargs = procform->pronargs;
655 FuncCandidateList clist;
659 clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
661 for (; clist; clist = clist->next)
663 if (memcmp(clist->args, procform->proargtypes,
664 nargs * sizeof(Oid)) == 0)
666 /* Found the expected entry; is it the right proc? */
667 visible = (clist->oid == funcid);
673 ReleaseSysCache(proctup);
680 * OpernameGetCandidates
681 * Given a possibly-qualified operator name and operator kind,
682 * retrieve a list of the possible matches.
684 * If oprkind is '\0', we return all operators matching the given name,
685 * regardless of arguments.
687 * We search a single namespace if the operator name is qualified, else
688 * all namespaces in the search path. The return list will never contain
689 * multiple entries with identical argument lists --- in the multiple-
690 * namespace case, we arrange for entries in earlier namespaces to mask
691 * identical entries in later namespaces.
693 * The returned items always have two args[] entries --- one or the other
694 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
697 OpernameGetCandidates(List *names, char oprkind)
699 FuncCandidateList resultList = NULL;
701 char *schemaname = NULL;
702 char *opername = NULL;
707 /* deconstruct the name list */
708 switch (length(names))
711 opername = strVal(lfirst(names));
714 schemaname = strVal(lfirst(names));
715 opername = strVal(lsecond(names));
718 catalogname = strVal(lfirst(names));
719 schemaname = strVal(lsecond(names));
720 opername = strVal(lfirst(lnext(lnext(names))));
722 * We check the catalog name and then ignore it.
724 if (strcmp(catalogname, DatabaseName) != 0)
725 elog(ERROR, "Cross-database references are not implemented");
728 elog(ERROR, "Improper qualified name (too many dotted names): %s",
729 NameListToString(names));
735 /* use exact schema given */
738 namespaceId = GetSysCacheOid(NAMESPACENAME,
739 CStringGetDatum(schemaname),
741 if (!OidIsValid(namespaceId))
742 elog(ERROR, "Namespace \"%s\" does not exist",
744 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
745 if (aclresult != ACLCHECK_OK)
746 aclcheck_error(aclresult, schemaname);
750 /* flag to indicate we need namespace search */
751 namespaceId = InvalidOid;
752 recomputeNamespacePath();
755 /* Search syscache by name only */
756 catlist = SearchSysCacheList(OPERNAMENSP, 1,
757 CStringGetDatum(opername),
760 for (i = 0; i < catlist->n_members; i++)
762 HeapTuple opertup = &catlist->members[i]->tuple;
763 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
765 FuncCandidateList newResult;
767 /* Ignore operators of wrong kind, if specific kind requested */
768 if (oprkind && operform->oprkind != oprkind)
771 if (OidIsValid(namespaceId))
773 /* Consider only opers in specified namespace */
774 if (operform->oprnamespace != namespaceId)
776 /* No need to check args, they must all be different */
780 /* Consider only opers that are in the search path */
783 foreach(nsp, namespaceSearchPath)
785 if (operform->oprnamespace == (Oid) lfirsti(nsp))
790 continue; /* oper is not in search path */
793 * Okay, it's in the search path, but does it have the same
794 * arguments as something we already accepted? If so, keep
795 * only the one that appears earlier in the search path.
797 * If we have an ordered list from SearchSysCacheList (the
798 * normal case), then any conflicting oper must immediately
799 * adjoin this one in the list, so we only need to look at
800 * the newest result item. If we have an unordered list,
801 * we have to scan the whole result list.
805 FuncCandidateList prevResult;
807 if (catlist->ordered)
809 if (operform->oprleft == resultList->args[0] &&
810 operform->oprright == resultList->args[1])
811 prevResult = resultList;
817 for (prevResult = resultList;
819 prevResult = prevResult->next)
821 if (operform->oprleft == prevResult->args[0] &&
822 operform->oprright == prevResult->args[1])
828 /* We have a match with a previous result */
829 Assert(pathpos != prevResult->pathpos);
830 if (pathpos > prevResult->pathpos)
831 continue; /* keep previous result */
832 /* replace previous result */
833 prevResult->pathpos = pathpos;
834 prevResult->oid = opertup->t_data->t_oid;
835 continue; /* args are same, of course */
841 * Okay to add it to result list
843 newResult = (FuncCandidateList)
844 palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
845 newResult->pathpos = pathpos;
846 newResult->oid = opertup->t_data->t_oid;
847 newResult->nargs = 2;
848 newResult->args[0] = operform->oprleft;
849 newResult->args[1] = operform->oprright;
850 newResult->next = resultList;
851 resultList = newResult;
854 ReleaseSysCacheList(catlist);
861 * Determine whether an operator (identified by OID) is visible in the
862 * current search path. Visible means "would be found by searching
863 * for the unqualified operator name with exact argument matches".
866 OperatorIsVisible(Oid oprid)
869 Form_pg_operator oprform;
873 oprtup = SearchSysCache(OPEROID,
874 ObjectIdGetDatum(oprid),
876 if (!HeapTupleIsValid(oprtup))
877 elog(ERROR, "Cache lookup failed for operator %u", oprid);
878 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
880 recomputeNamespacePath();
883 * Quick check: if it ain't in the path at all, it ain't visible.
884 * Items in the system namespace are surely in the path and so we
885 * needn't even do intMember() for them.
887 oprnamespace = oprform->oprnamespace;
888 if (oprnamespace != PG_CATALOG_NAMESPACE &&
889 !intMember(oprnamespace, namespaceSearchPath))
894 * If it is in the path, it might still not be visible; it could be
895 * hidden by another operator of the same name and arguments earlier
896 * in the path. So we must do a slow check to see if this is the
897 * same operator that would be found by OpernameGetCandidates.
899 char *oprname = NameStr(oprform->oprname);
900 FuncCandidateList clist;
904 clist = OpernameGetCandidates(makeList1(makeString(oprname)),
907 for (; clist; clist = clist->next)
909 if (clist->args[0] == oprform->oprleft &&
910 clist->args[1] == oprform->oprright)
912 /* Found the expected entry; is it the right op? */
913 visible = (clist->oid == oprid);
919 ReleaseSysCache(oprtup);
926 * OpclassGetCandidates
927 * Given an index access method OID, retrieve a list of all the
928 * opclasses for that AM that are visible in the search path.
930 * NOTE: the opcname_tmp field in the returned structs should not be used
931 * by callers, because it points at syscache entries that we release at
932 * the end of this routine. If any callers needed the name information,
933 * we could pstrdup() the names ... but at present it'd be wasteful.
936 OpclassGetCandidates(Oid amid)
938 OpclassCandidateList resultList = NULL;
942 /* Search syscache by AM OID only */
943 catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
944 ObjectIdGetDatum(amid),
947 recomputeNamespacePath();
949 for (i = 0; i < catlist->n_members; i++)
951 HeapTuple opctup = &catlist->members[i]->tuple;
952 Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
954 OpclassCandidateList newResult;
957 /* Consider only opclasses that are in the search path */
958 foreach(nsp, namespaceSearchPath)
960 if (opcform->opcnamespace == (Oid) lfirsti(nsp))
965 continue; /* opclass is not in search path */
968 * Okay, it's in the search path, but does it have the same name
969 * as something we already accepted? If so, keep
970 * only the one that appears earlier in the search path.
972 * If we have an ordered list from SearchSysCacheList (the
973 * normal case), then any conflicting opclass must immediately
974 * adjoin this one in the list, so we only need to look at
975 * the newest result item. If we have an unordered list,
976 * we have to scan the whole result list.
980 OpclassCandidateList prevResult;
982 if (catlist->ordered)
984 if (strcmp(NameStr(opcform->opcname),
985 resultList->opcname_tmp) == 0)
986 prevResult = resultList;
992 for (prevResult = resultList;
994 prevResult = prevResult->next)
996 if (strcmp(NameStr(opcform->opcname),
997 prevResult->opcname_tmp) == 0)
1003 /* We have a match with a previous result */
1004 Assert(pathpos != prevResult->pathpos);
1005 if (pathpos > prevResult->pathpos)
1006 continue; /* keep previous result */
1007 /* replace previous result */
1008 prevResult->opcname_tmp = NameStr(opcform->opcname);
1009 prevResult->pathpos = pathpos;
1010 prevResult->oid = opctup->t_data->t_oid;
1011 prevResult->opcintype = opcform->opcintype;
1012 prevResult->opcdefault = opcform->opcdefault;
1013 prevResult->opckeytype = opcform->opckeytype;
1019 * Okay to add it to result list
1021 newResult = (OpclassCandidateList)
1022 palloc(sizeof(struct _OpclassCandidateList));
1023 newResult->opcname_tmp = NameStr(opcform->opcname);
1024 newResult->pathpos = pathpos;
1025 newResult->oid = opctup->t_data->t_oid;
1026 newResult->opcintype = opcform->opcintype;
1027 newResult->opcdefault = opcform->opcdefault;
1028 newResult->opckeytype = opcform->opckeytype;
1029 newResult->next = resultList;
1030 resultList = newResult;
1033 ReleaseSysCacheList(catlist);
1039 * OpclassnameGetOpcid
1040 * Try to resolve an unqualified index opclass name.
1041 * Returns OID if opclass found in search path, else InvalidOid.
1043 * This is essentially the same as TypenameGetTypid, but we have to have
1044 * an extra argument for the index AM OID.
1047 OpclassnameGetOpcid(Oid amid, const char *opcname)
1052 recomputeNamespacePath();
1054 foreach(lptr, namespaceSearchPath)
1056 Oid namespaceId = (Oid) lfirsti(lptr);
1058 opcid = GetSysCacheOid(CLAAMNAMENSP,
1059 ObjectIdGetDatum(amid),
1060 PointerGetDatum(opcname),
1061 ObjectIdGetDatum(namespaceId),
1063 if (OidIsValid(opcid))
1067 /* Not found in path */
1073 * Determine whether an opclass (identified by OID) is visible in the
1074 * current search path. Visible means "would be found by searching
1075 * for the unqualified opclass name".
1078 OpclassIsVisible(Oid opcid)
1081 Form_pg_opclass opcform;
1085 opctup = SearchSysCache(CLAOID,
1086 ObjectIdGetDatum(opcid),
1088 if (!HeapTupleIsValid(opctup))
1089 elog(ERROR, "Cache lookup failed for opclass %u", opcid);
1090 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1092 recomputeNamespacePath();
1095 * Quick check: if it ain't in the path at all, it ain't visible.
1096 * Items in the system namespace are surely in the path and so we
1097 * needn't even do intMember() for them.
1099 opcnamespace = opcform->opcnamespace;
1100 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1101 !intMember(opcnamespace, namespaceSearchPath))
1106 * If it is in the path, it might still not be visible; it could be
1107 * hidden by another opclass of the same name earlier in the path.
1108 * So we must do a slow check to see if this opclass would be found by
1109 * OpclassnameGetOpcid.
1111 char *opcname = NameStr(opcform->opcname);
1113 visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
1116 ReleaseSysCache(opctup);
1123 * QualifiedNameGetCreationNamespace
1124 * Given a possibly-qualified name for an object (in List-of-Values
1125 * format), determine what namespace the object should be created in.
1126 * Also extract and return the object name (last component of list).
1128 * This is *not* used for tables. Hence, the TEMP table namespace is
1129 * never selected as the creation target.
1132 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1135 char *schemaname = NULL;
1136 char *objname = NULL;
1139 /* deconstruct the name list */
1140 switch (length(names))
1143 objname = strVal(lfirst(names));
1146 schemaname = strVal(lfirst(names));
1147 objname = strVal(lsecond(names));
1150 catalogname = strVal(lfirst(names));
1151 schemaname = strVal(lsecond(names));
1152 objname = strVal(lfirst(lnext(lnext(names))));
1154 * We check the catalog name and then ignore it.
1156 if (strcmp(catalogname, DatabaseName) != 0)
1157 elog(ERROR, "Cross-database references are not implemented");
1160 elog(ERROR, "Improper qualified name (too many dotted names): %s",
1161 NameListToString(names));
1167 /* use exact schema given */
1168 namespaceId = GetSysCacheOid(NAMESPACENAME,
1169 CStringGetDatum(schemaname),
1171 if (!OidIsValid(namespaceId))
1172 elog(ERROR, "Namespace \"%s\" does not exist",
1177 /* use the default creation namespace */
1178 recomputeNamespacePath();
1179 namespaceId = defaultCreationNamespace;
1180 if (!OidIsValid(namespaceId))
1181 elog(ERROR, "No namespace has been selected to create in");
1184 /* Note: callers will check for CREATE rights when appropriate */
1186 *objname_p = objname;
1191 * makeRangeVarFromNameList
1192 * Utility routine to convert a qualified-name list into RangeVar form.
1195 makeRangeVarFromNameList(List *names)
1197 RangeVar *rel = makeRangeVar(NULL, NULL);
1199 switch (length(names))
1202 rel->relname = strVal(lfirst(names));
1205 rel->schemaname = strVal(lfirst(names));
1206 rel->relname = strVal(lsecond(names));
1209 rel->catalogname = strVal(lfirst(names));
1210 rel->schemaname = strVal(lsecond(names));
1211 rel->relname = strVal(lfirst(lnext(lnext(names))));
1214 elog(ERROR, "Improper relation name (too many dotted names)");
1223 * Utility routine to convert a qualified-name list into a string.
1224 * Used primarily to form error messages.
1227 NameListToString(List *names)
1229 StringInfoData string;
1232 initStringInfo(&string);
1237 appendStringInfoChar(&string, '.');
1238 appendStringInfo(&string, "%s", strVal(lfirst(l)));
1245 * isTempNamespace - is the given namespace my temporary-table namespace?
1248 isTempNamespace(Oid namespaceId)
1250 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1256 * PushSpecialNamespace - push a "special" namespace onto the front of the
1259 * This is a slightly messy hack intended only for support of CREATE SCHEMA.
1260 * Although the API is defined to allow a stack of pushed namespaces, we
1261 * presently only support one at a time.
1263 * The pushed namespace will be removed from the search path at end of
1264 * transaction, whether commit or abort.
1267 PushSpecialNamespace(Oid namespaceId)
1269 Assert(!OidIsValid(mySpecialNamespace));
1270 mySpecialNamespace = namespaceId;
1271 namespaceSearchPathValid = false;
1275 * PopSpecialNamespace - remove previously pushed special namespace.
1278 PopSpecialNamespace(Oid namespaceId)
1280 Assert(mySpecialNamespace == namespaceId);
1281 mySpecialNamespace = InvalidOid;
1282 namespaceSearchPathValid = false;
1287 * recomputeNamespacePath - recompute path derived variables if needed.
1290 recomputeNamespacePath(void)
1292 Oid userId = GetUserId();
1299 MemoryContext oldcxt;
1302 * Do nothing if path is already valid.
1304 if (namespaceSearchPathValid && namespaceUser == userId)
1307 /* Need a modifiable copy of namespace_search_path string */
1308 rawname = pstrdup(namespace_search_path);
1310 /* Parse string into list of identifiers */
1311 if (!SplitIdentifierString(rawname, ',', &namelist))
1313 /* syntax error in name list */
1314 /* this should not happen if GUC checked check_search_path */
1315 elog(ERROR, "recomputeNamespacePath: invalid list syntax");
1319 * Convert the list of names to a list of OIDs. If any names are not
1320 * recognizable or we don't have read access, just leave them out of
1321 * the list. (We can't raise an error, since the search_path setting
1322 * has already been accepted.) Don't make duplicate entries, either.
1325 foreach(l, namelist)
1327 char *curname = (char *) lfirst(l);
1330 if (strcmp(curname, "$user") == 0)
1332 /* $user --- substitute namespace matching user name, if any */
1335 tuple = SearchSysCache(SHADOWSYSID,
1336 ObjectIdGetDatum(userId),
1338 if (HeapTupleIsValid(tuple))
1342 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1343 namespaceId = GetSysCacheOid(NAMESPACENAME,
1344 CStringGetDatum(uname),
1346 ReleaseSysCache(tuple);
1347 if (OidIsValid(namespaceId) &&
1348 !intMember(namespaceId, oidlist) &&
1349 pg_namespace_aclcheck(namespaceId, userId,
1350 ACL_USAGE) == ACLCHECK_OK)
1351 oidlist = lappendi(oidlist, namespaceId);
1356 /* normal namespace reference */
1357 namespaceId = GetSysCacheOid(NAMESPACENAME,
1358 CStringGetDatum(curname),
1360 if (OidIsValid(namespaceId) &&
1361 !intMember(namespaceId, oidlist) &&
1362 pg_namespace_aclcheck(namespaceId, userId,
1363 ACL_USAGE) == ACLCHECK_OK)
1364 oidlist = lappendi(oidlist, namespaceId);
1369 * Remember the first member of the explicit list.
1372 firstNS = InvalidOid;
1374 firstNS = (Oid) lfirsti(oidlist);
1377 * Add any implicitly-searched namespaces to the list. Note these
1378 * go on the front, not the back; also notice that we do not check
1379 * USAGE permissions for these.
1381 if (!intMember(PG_CATALOG_NAMESPACE, oidlist))
1382 oidlist = lconsi(PG_CATALOG_NAMESPACE, oidlist);
1384 if (OidIsValid(myTempNamespace) &&
1385 !intMember(myTempNamespace, oidlist))
1386 oidlist = lconsi(myTempNamespace, oidlist);
1388 if (OidIsValid(mySpecialNamespace) &&
1389 !intMember(mySpecialNamespace, oidlist))
1390 oidlist = lconsi(mySpecialNamespace, oidlist);
1393 * Now that we've successfully built the new list of namespace OIDs,
1394 * save it in permanent storage.
1396 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1397 newpath = listCopy(oidlist);
1398 MemoryContextSwitchTo(oldcxt);
1400 /* Now safe to assign to state variable. */
1401 freeList(namespaceSearchPath);
1402 namespaceSearchPath = newpath;
1405 * Update info derived from search path.
1407 firstExplicitNamespace = firstNS;
1408 if (OidIsValid(mySpecialNamespace))
1409 defaultCreationNamespace = mySpecialNamespace;
1411 defaultCreationNamespace = firstNS;
1413 /* Mark the path valid. */
1414 namespaceSearchPathValid = true;
1415 namespaceUser = userId;
1424 * InitTempTableNamespace
1425 * Initialize temp table namespace on first use in a particular backend
1428 InitTempTableNamespace(void)
1430 char namespaceName[NAMEDATALEN];
1434 * First, do permission check to see if we are authorized to make
1435 * temp tables. We use a nonstandard error message here since
1436 * "databasename: permission denied" might be a tad cryptic.
1438 * Note we apply the check to the session user, not the currently
1439 * active userid, since we are not going to change our minds about
1440 * temp table availability during the session.
1442 if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
1443 ACL_CREATE_TEMP) != ACLCHECK_OK)
1444 elog(ERROR, "%s: not authorized to create temp tables",
1447 snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
1449 namespaceId = GetSysCacheOid(NAMESPACENAME,
1450 CStringGetDatum(namespaceName),
1452 if (!OidIsValid(namespaceId))
1455 * First use of this temp namespace in this database; create it.
1456 * The temp namespaces are always owned by the superuser. We
1457 * leave their permissions at default --- i.e., no access except to
1458 * superuser --- to ensure that unprivileged users can't peek
1459 * at other backends' temp tables. This works because the places
1460 * that access the temp namespace for my own backend skip permissions
1463 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
1464 /* Advance command counter to make namespace visible */
1465 CommandCounterIncrement();
1470 * If the namespace already exists, clean it out (in case the
1471 * former owner crashed without doing so).
1473 RemoveTempRelations(namespaceId);
1477 * Okay, we've prepared the temp namespace ... but it's not committed
1478 * yet, so all our work could be undone by transaction rollback. Set
1479 * flag for AtEOXact_Namespace to know what to do.
1481 myTempNamespace = namespaceId;
1483 firstTempTransaction = true;
1485 namespaceSearchPathValid = false; /* need to rebuild list */
1489 * End-of-transaction cleanup for namespaces.
1492 AtEOXact_Namespace(bool isCommit)
1495 * If we abort the transaction in which a temp namespace was selected,
1496 * we'll have to do any creation or cleanout work over again. So,
1497 * just forget the namespace entirely until next time. On the other
1498 * hand, if we commit then register an exit callback to clean out the
1499 * temp tables at backend shutdown. (We only want to register the
1500 * callback once per session, so this is a good place to do it.)
1502 if (firstTempTransaction)
1505 on_shmem_exit(RemoveTempRelationsCallback, 0);
1508 myTempNamespace = InvalidOid;
1509 namespaceSearchPathValid = false; /* need to rebuild list */
1511 firstTempTransaction = false;
1514 * Clean up if someone failed to do PopSpecialNamespace
1516 if (OidIsValid(mySpecialNamespace))
1518 mySpecialNamespace = InvalidOid;
1519 namespaceSearchPathValid = false; /* need to rebuild list */
1524 * Remove all relations in the specified temp namespace.
1526 * This is called at backend shutdown (if we made any temp relations).
1527 * It is also called when we begin using a pre-existing temp namespace,
1528 * in order to clean out any relations that might have been created by
1529 * a crashed backend.
1532 RemoveTempRelations(Oid tempNamespaceId)
1535 List *constraintList;
1538 /* Get a list of relations to delete */
1539 tempRelList = FindTempRelations(tempNamespaceId);
1541 if (tempRelList == NIL)
1542 return; /* nothing to do */
1544 /* If more than one, sort them to respect any deletion-order constraints */
1545 if (length(tempRelList) > 1)
1547 constraintList = FindDeletionConstraints(tempRelList);
1548 if (constraintList != NIL)
1549 tempRelList = TopoSortRels(tempRelList, constraintList);
1552 /* Scan the list and delete all entries */
1553 foreach(lptr, tempRelList)
1555 Oid reloid = (Oid) lfirsti(lptr);
1557 heap_drop_with_catalog(reloid, true);
1559 * Advance cmd counter to make catalog changes visible, in case
1560 * a later entry depends on this one.
1562 CommandCounterIncrement();
1567 * Find all relations in the specified temp namespace.
1569 * Returns a list of relation OIDs.
1572 FindTempRelations(Oid tempNamespaceId)
1574 List *tempRelList = NIL;
1581 * Scan pg_class to find all the relations in the target namespace.
1582 * Ignore indexes, though, on the assumption that they'll go away
1583 * when their tables are deleted.
1585 ScanKeyEntryInitialize(&key, 0x0,
1586 Anum_pg_class_relnamespace,
1588 ObjectIdGetDatum(tempNamespaceId));
1590 pgclass = heap_openr(RelationRelationName, AccessShareLock);
1591 scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
1593 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1595 switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
1597 case RELKIND_RELATION:
1598 case RELKIND_SEQUENCE:
1600 tempRelList = lconsi(tuple->t_data->t_oid, tempRelList);
1608 heap_close(pgclass, AccessShareLock);
1614 * Find deletion-order constraints involving the given relation OIDs.
1616 * Returns a list of DelConstraint objects.
1619 FindDeletionConstraints(List *relOids)
1621 List *constraintList = NIL;
1622 Relation inheritsrel;
1627 * Scan pg_inherits to find parents and children that are in the list.
1629 inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
1630 scan = heap_beginscan(inheritsrel, SnapshotNow, 0, NULL);
1632 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1634 Oid inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
1635 Oid inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
1637 if (intMember(inhrelid, relOids) && intMember(inhparent, relOids))
1639 DelConstraint *item;
1641 item = (DelConstraint *) palloc(sizeof(DelConstraint));
1642 item->referencer = inhrelid;
1643 item->referencee = inhparent;
1644 constraintList = lcons(item, constraintList);
1649 heap_close(inheritsrel, AccessShareLock);
1651 return constraintList;
1655 * TopoSortRels -- topological sort of a list of rels to delete
1657 * This is a lot simpler and slower than, for example, the topological sort
1658 * algorithm shown in Knuth's Volume 1. However, we are not likely to be
1659 * working with more than a few constraints, so the apparent slowness of the
1660 * algorithm won't really matter.
1663 TopoSortRels(List *relOids, List *constraintList)
1665 int queue_size = length(relOids);
1667 int *beforeConstraints;
1668 DelConstraint **afterConstraints;
1669 List *resultList = NIL;
1676 /* Allocate workspace */
1677 rels = (Oid *) palloc(queue_size * sizeof(Oid));
1678 beforeConstraints = (int *) palloc(queue_size * sizeof(int));
1679 afterConstraints = (DelConstraint **)
1680 palloc(queue_size * sizeof(DelConstraint*));
1682 /* Build an array of the target relation OIDs */
1684 foreach(lptr, relOids)
1686 rels[i++] = (Oid) lfirsti(lptr);
1690 * Scan the constraints, and for each rel in the array, generate a
1691 * count of the number of constraints that say it must be before
1692 * something else, plus a list of the constraints that say it must be
1693 * after something else. The count for the j'th rel is stored in
1694 * beforeConstraints[j], and the head of its list in
1695 * afterConstraints[j]. Each constraint stores its list link in
1696 * its link field (note any constraint will be in just one list).
1697 * The array index for the before-rel of each constraint is
1698 * remembered in the constraint's pred field.
1700 MemSet(beforeConstraints, 0, queue_size * sizeof(int));
1701 MemSet(afterConstraints, 0, queue_size * sizeof(DelConstraint*));
1702 foreach(lptr, constraintList)
1704 DelConstraint *constraint = (DelConstraint *) lfirst(lptr);
1707 /* Find the referencer rel in the array */
1708 rel = constraint->referencer;
1709 for (j = queue_size; --j >= 0;)
1714 Assert(j >= 0); /* should have found a match */
1715 /* Find the referencee rel in the array */
1716 rel = constraint->referencee;
1717 for (k = queue_size; --k >= 0;)
1722 Assert(k >= 0); /* should have found a match */
1723 beforeConstraints[j]++; /* referencer must come before */
1724 /* add this constraint to list of after-constraints for referencee */
1725 constraint->pred = j;
1726 constraint->link = afterConstraints[k];
1727 afterConstraints[k] = constraint;
1729 /*--------------------
1730 * Now scan the rels array backwards. At each step, output the
1731 * last rel that has no remaining before-constraints, and decrease
1732 * the beforeConstraints count of each of the rels it was constrained
1733 * against. (This is the right order since we are building the result
1734 * list back-to-front.)
1735 * i = counter for number of rels left to output
1736 * j = search index for rels[]
1737 * dc = temp for scanning constraint list for rel j
1738 * last = last valid index in rels (avoid redundant searches)
1739 *--------------------
1741 last = queue_size - 1;
1742 for (i = queue_size; --i >= 0;)
1746 /* Find next candidate to output */
1747 while (rels[last] == InvalidOid)
1749 for (j = last; j >= 0; j--)
1751 if (rels[j] != InvalidOid && beforeConstraints[j] == 0)
1754 /* If no available candidate, topological sort fails */
1756 elog(ERROR, "TopoSortRels: failed to find a workable deletion ordering");
1757 /* Output candidate, and mark it done by zeroing rels[] entry */
1758 resultList = lconsi(rels[j], resultList);
1759 rels[j] = InvalidOid;
1760 /* Update beforeConstraints counts of its predecessors */
1761 for (dc = afterConstraints[j]; dc; dc = dc->link)
1762 beforeConstraints[dc->pred]--;
1770 * Callback to remove temp relations at backend exit.
1773 RemoveTempRelationsCallback(void)
1775 if (OidIsValid(myTempNamespace)) /* should always be true */
1777 /* Need to ensure we have a usable transaction. */
1778 AbortOutOfAnyTransaction();
1779 StartTransactionCommand();
1781 RemoveTempRelations(myTempNamespace);
1783 CommitTransactionCommand();
1789 * Routines for handling the GUC variable 'search_path'.
1792 /* assign_hook: validate new search_path, do extra actions as needed */
1794 assign_search_path(const char *newval, bool doit, bool interactive)
1800 /* Need a modifiable copy of string */
1801 rawname = pstrdup(newval);
1803 /* Parse string into list of identifiers */
1804 if (!SplitIdentifierString(rawname, ',', &namelist))
1806 /* syntax error in name list */
1813 * If we aren't inside a transaction, we cannot do database access so
1814 * cannot verify the individual names. Must accept the list on faith.
1816 if (interactive && IsTransactionState())
1819 * Verify that all the names are either valid namespace names or
1820 * "$user". We do not require $user to correspond to a valid
1821 * namespace. We do not check for USAGE rights, either; should we?
1823 foreach(l, namelist)
1825 char *curname = (char *) lfirst(l);
1827 if (strcmp(curname, "$user") == 0)
1829 if (!SearchSysCacheExists(NAMESPACENAME,
1830 CStringGetDatum(curname),
1832 elog(ERROR, "Namespace \"%s\" does not exist", curname);
1840 * We mark the path as needing recomputation, but don't do anything until
1841 * it's needed. This avoids trying to do database access during GUC
1845 namespaceSearchPathValid = false;
1851 * InitializeSearchPath: initialize module during InitPostgres.
1853 * This is called after we are up enough to be able to do catalog lookups.
1856 InitializeSearchPath(void)
1858 if (IsBootstrapProcessingMode())
1861 * In bootstrap mode, the search path must be 'pg_catalog' so that
1862 * tables are created in the proper namespace; ignore the GUC setting.
1864 MemoryContext oldcxt;
1866 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1867 namespaceSearchPath = makeListi1(PG_CATALOG_NAMESPACE);
1868 MemoryContextSwitchTo(oldcxt);
1869 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1870 firstExplicitNamespace = PG_CATALOG_NAMESPACE;
1871 namespaceSearchPathValid = true;
1872 namespaceUser = GetUserId();
1877 * In normal mode, arrange for a callback on any syscache invalidation
1878 * of pg_namespace rows.
1880 CacheRegisterSyscacheCallback(NAMESPACEOID,
1883 /* Force search path to be recomputed on next use */
1884 namespaceSearchPathValid = false;
1890 * Syscache inval callback function
1893 NamespaceCallback(Datum arg, Oid relid)
1895 /* Force search path to be recomputed on next use */
1896 namespaceSearchPathValid = false;
1900 * Fetch the active search path, expressed as a List of OIDs.
1902 * The returned list includes the implicitly-prepended namespaces only if
1903 * includeImplicit is true.
1905 * NB: caller must treat the list as read-only!
1908 fetch_search_path(bool includeImplicit)
1912 recomputeNamespacePath();
1914 result = namespaceSearchPath;
1915 if (!includeImplicit)
1917 while (result && (Oid) lfirsti(result) != firstExplicitNamespace)
1918 result = lnext(result);