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.16 2002/04/30 01:26:25 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 "lib/stringinfo.h"
35 #include "miscadmin.h"
36 #include "nodes/makefuncs.h"
37 #include "storage/backendid.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/catcache.h"
41 #include "utils/fmgroids.h"
42 #include "utils/guc.h"
43 #include "utils/inval.h"
44 #include "utils/lsyscache.h"
45 #include "utils/syscache.h"
49 * The namespace search path is a possibly-empty list of namespace OIDs.
50 * In addition to the explicit list, the TEMP table namespace is always
51 * implicitly searched first (if it's been initialized). Also, the system
52 * catalog namespace is always searched. If the system namespace is
53 * explicitly present in the path then it will be searched in the specified
54 * order; otherwise it will be searched after TEMP tables and *before* the
55 * explicit list. (It might seem that the system namespace should be
56 * implicitly last, but this behavior appears to be required by SQL99.
57 * Also, this provides a way to search the system namespace first without
58 * thereby making it the default creation target namespace.)
60 * The default creation target namespace is kept equal to the first element
61 * of the (explicit) list. If the list is empty, there is no default target.
63 * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
64 * the system namespace is the only one searched or inserted into.
65 * The initdb script is also careful to set search_path to 'pg_catalog' for
66 * its post-bootstrap standalone backend runs. Otherwise the default search
67 * path is determined by GUC. The factory default path contains the PUBLIC
68 * namespace (if it exists), preceded by the user's personal namespace
71 * If namespaceSearchPathValid is false, then namespaceSearchPath (and the
72 * derived variables) need to be recomputed from namespace_search_path.
73 * We mark it invalid upon an assignment to namespace_search_path or receipt
74 * of a syscache invalidation event for pg_namespace. The recomputation
75 * is done during the next lookup attempt.
77 * Any namespaces mentioned in namespace_search_path that are not readable
78 * by the current user ID are simply left out of namespaceSearchPath; so
79 * we have to be willing to recompute the path when current userid changes.
80 * namespaceUser is the userid the path has been computed for.
83 static List *namespaceSearchPath = NIL;
85 static bool namespaceSearchPathValid = true;
87 static Oid namespaceUser = InvalidOid;
89 /* this flag must be updated correctly when namespaceSearchPath is changed */
90 static bool pathContainsSystemNamespace = false;
92 /* default place to create stuff; if InvalidOid, no default */
93 static Oid defaultCreationNamespace = InvalidOid;
96 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
97 * in a particular backend session (this happens when a CREATE TEMP TABLE
98 * command is first executed). Thereafter it's the OID of the temp namespace.
100 static Oid myTempNamespace = InvalidOid;
103 * This is the text equivalent of the search path --- it's the value
104 * of the GUC variable 'search_path'.
106 char *namespace_search_path = NULL;
110 * Deletion ordering constraint item.
112 typedef struct DelConstraint
114 Oid referencer; /* table to delete first */
115 Oid referencee; /* table to delete second */
116 int pred; /* workspace for TopoSortRels */
117 struct DelConstraint *link; /* workspace for TopoSortRels */
121 /* Local functions */
122 static void recomputeNamespacePath(void);
123 static Oid GetTempTableNamespace(void);
124 static void RemoveTempRelations(Oid tempNamespaceId);
125 static List *FindTempRelations(Oid tempNamespaceId);
126 static List *FindDeletionConstraints(List *relOids);
127 static List *TopoSortRels(List *relOids, List *constraintList);
128 static void RemoveTempRelationsCallback(void);
129 static void NamespaceCallback(Datum arg, Oid relid);
134 * Given a RangeVar describing an existing relation,
135 * select the proper namespace and look up the relation OID.
137 * If the relation is not found, return InvalidOid if failOK = true,
138 * otherwise raise an error.
141 RangeVarGetRelid(const RangeVar *relation, bool failOK)
147 * We check the catalog name and then ignore it.
149 if (relation->catalogname)
151 if (strcmp(relation->catalogname, DatabaseName) != 0)
152 elog(ERROR, "Cross-database references are not implemented");
155 if (relation->schemaname)
157 /* use exact schema given */
160 namespaceId = GetSysCacheOid(NAMESPACENAME,
161 CStringGetDatum(relation->schemaname),
163 if (!OidIsValid(namespaceId))
164 elog(ERROR, "Namespace \"%s\" does not exist",
165 relation->schemaname);
166 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
167 if (aclresult != ACLCHECK_OK)
168 aclcheck_error(aclresult, relation->schemaname);
170 relId = get_relname_relid(relation->relname, namespaceId);
174 /* search the namespace path */
175 relId = RelnameGetRelid(relation->relname);
178 if (!OidIsValid(relId) && !failOK)
180 if (relation->schemaname)
181 elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
182 relation->schemaname, relation->relname);
184 elog(ERROR, "Relation \"%s\" does not exist",
191 * RangeVarGetCreationNamespace
192 * Given a RangeVar describing a to-be-created relation,
193 * choose which namespace to create it in.
195 * Note: calling this may result in a CommandCounterIncrement operation.
196 * That will happen on the first request for a temp table in any particular
197 * backend run; we will need to either create or clean out the temp schema.
200 RangeVarGetCreationNamespace(const RangeVar *newRelation)
205 * We check the catalog name and then ignore it.
207 if (newRelation->catalogname)
209 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
210 elog(ERROR, "Cross-database references are not implemented");
213 if (newRelation->istemp)
215 /* TEMP tables are created in our backend-local temp namespace */
216 if (newRelation->schemaname)
217 elog(ERROR, "TEMP tables may not specify a namespace");
218 /* Initialize temp namespace if first time through */
219 if (!OidIsValid(myTempNamespace))
220 myTempNamespace = GetTempTableNamespace();
221 return myTempNamespace;
224 if (newRelation->schemaname)
226 /* use exact schema given */
227 namespaceId = GetSysCacheOid(NAMESPACENAME,
228 CStringGetDatum(newRelation->schemaname),
230 if (!OidIsValid(namespaceId))
231 elog(ERROR, "Namespace \"%s\" does not exist",
232 newRelation->schemaname);
236 /* use the default creation namespace */
237 recomputeNamespacePath();
238 namespaceId = defaultCreationNamespace;
239 if (!OidIsValid(namespaceId))
240 elog(ERROR, "No namespace has been selected to create in");
243 /* Note: callers will check for CREATE rights when appropriate */
250 * Try to resolve an unqualified relation name.
251 * Returns OID if relation found in search path, else InvalidOid.
254 RelnameGetRelid(const char *relname)
259 recomputeNamespacePath();
262 * If a TEMP-table namespace has been set up, it is implicitly first
263 * in the search path. We do not need to check USAGE permission.
265 if (OidIsValid(myTempNamespace))
267 relid = get_relname_relid(relname, myTempNamespace);
268 if (OidIsValid(relid))
273 * If system namespace is not in path, implicitly search it before path.
274 * We do not check USAGE permission.
276 if (!pathContainsSystemNamespace)
278 relid = get_relname_relid(relname, PG_CATALOG_NAMESPACE);
279 if (OidIsValid(relid))
284 * Else search the path
286 foreach(lptr, namespaceSearchPath)
288 Oid namespaceId = (Oid) lfirsti(lptr);
290 relid = get_relname_relid(relname, namespaceId);
291 if (OidIsValid(relid))
295 /* Not found in path */
301 * Try to resolve an unqualified datatype name.
302 * Returns OID if type found in search path, else InvalidOid.
304 * This is essentially the same as RelnameGetRelid, but we never search
305 * the TEMP table namespace --- there is no reason to refer to the types
306 * of temp tables, AFAICS.
309 TypenameGetTypid(const char *typname)
314 recomputeNamespacePath();
317 * If system namespace is not in path, implicitly search it before path
319 if (!pathContainsSystemNamespace)
321 typid = GetSysCacheOid(TYPENAMENSP,
322 PointerGetDatum(typname),
323 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
325 if (OidIsValid(typid))
330 * Else search the path
332 foreach(lptr, namespaceSearchPath)
334 Oid namespaceId = (Oid) lfirsti(lptr);
336 typid = GetSysCacheOid(TYPENAMENSP,
337 PointerGetDatum(typname),
338 ObjectIdGetDatum(namespaceId),
340 if (OidIsValid(typid))
344 /* Not found in path */
349 * OpclassnameGetOpcid
350 * Try to resolve an unqualified index opclass name.
351 * Returns OID if opclass found in search path, else InvalidOid.
353 * This is essentially the same as TypenameGetTypid, but we have to have
354 * an extra argument for the index AM OID.
357 OpclassnameGetOpcid(Oid amid, const char *opcname)
362 recomputeNamespacePath();
365 * If system namespace is not in path, implicitly search it before path
367 if (!pathContainsSystemNamespace)
369 opcid = GetSysCacheOid(CLAAMNAMENSP,
370 ObjectIdGetDatum(amid),
371 PointerGetDatum(opcname),
372 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
374 if (OidIsValid(opcid))
379 * Else search the path
381 foreach(lptr, namespaceSearchPath)
383 Oid namespaceId = (Oid) lfirsti(lptr);
385 opcid = GetSysCacheOid(CLAAMNAMENSP,
386 ObjectIdGetDatum(amid),
387 PointerGetDatum(opcname),
388 ObjectIdGetDatum(namespaceId),
390 if (OidIsValid(opcid))
394 /* Not found in path */
399 * FuncnameGetCandidates
400 * Given a possibly-qualified function name and argument count,
401 * retrieve a list of the possible matches.
403 * If nargs is -1, we return all functions matching the given name,
404 * regardless of argument count.
406 * We search a single namespace if the function name is qualified, else
407 * all namespaces in the search path. The return list will never contain
408 * multiple entries with identical argument lists --- in the multiple-
409 * namespace case, we arrange for entries in earlier namespaces to mask
410 * identical entries in later namespaces.
413 FuncnameGetCandidates(List *names, int nargs)
415 FuncCandidateList resultList = NULL;
417 char *schemaname = NULL;
418 char *funcname = NULL;
423 /* deconstruct the name list */
424 switch (length(names))
427 funcname = strVal(lfirst(names));
430 schemaname = strVal(lfirst(names));
431 funcname = strVal(lsecond(names));
434 catalogname = strVal(lfirst(names));
435 schemaname = strVal(lsecond(names));
436 funcname = strVal(lfirst(lnext(lnext(names))));
438 * We check the catalog name and then ignore it.
440 if (strcmp(catalogname, DatabaseName) != 0)
441 elog(ERROR, "Cross-database references are not implemented");
444 elog(ERROR, "Improper qualified name (too many dotted names)");
450 /* use exact schema given */
453 namespaceId = GetSysCacheOid(NAMESPACENAME,
454 CStringGetDatum(schemaname),
456 if (!OidIsValid(namespaceId))
457 elog(ERROR, "Namespace \"%s\" does not exist",
459 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
460 if (aclresult != ACLCHECK_OK)
461 aclcheck_error(aclresult, schemaname);
465 /* flag to indicate we need namespace search */
466 namespaceId = InvalidOid;
467 recomputeNamespacePath();
470 /* Search syscache by name and (optionally) nargs only */
472 catlist = SearchSysCacheList(PROCNAMENSP, 2,
473 CStringGetDatum(funcname),
474 Int16GetDatum(nargs),
477 catlist = SearchSysCacheList(PROCNAMENSP, 1,
478 CStringGetDatum(funcname),
481 for (i = 0; i < catlist->n_members; i++)
483 HeapTuple proctup = &catlist->members[i]->tuple;
484 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
486 FuncCandidateList newResult;
488 nargs = procform->pronargs;
490 if (OidIsValid(namespaceId))
492 /* Consider only procs in specified namespace */
493 if (procform->pronamespace != namespaceId)
495 /* No need to check args, they must all be different */
499 /* Consider only procs that are in the search path */
500 if (pathContainsSystemNamespace ||
501 !IsSystemNamespace(procform->pronamespace))
505 foreach(nsp, namespaceSearchPath)
508 if (procform->pronamespace == (Oid) lfirsti(nsp))
512 continue; /* proc is not in search path */
516 * Okay, it's in the search path, but does it have the same
517 * arguments as something we already accepted? If so, keep
518 * only the one that appears earlier in the search path.
520 * If we have an ordered list from SearchSysCacheList (the
521 * normal case), then any conflicting proc must immediately
522 * adjoin this one in the list, so we only need to look at
523 * the newest result item. If we have an unordered list,
524 * we have to scan the whole result list.
528 FuncCandidateList prevResult;
530 if (catlist->ordered)
532 if (nargs == resultList->nargs &&
533 memcmp(procform->proargtypes, resultList->args,
534 nargs * sizeof(Oid)) == 0)
535 prevResult = resultList;
541 for (prevResult = resultList;
543 prevResult = prevResult->next)
545 if (nargs == prevResult->nargs &&
546 memcmp(procform->proargtypes, prevResult->args,
547 nargs * sizeof(Oid)) == 0)
553 /* We have a match with a previous result */
554 Assert(pathpos != prevResult->pathpos);
555 if (pathpos > prevResult->pathpos)
556 continue; /* keep previous result */
557 /* replace previous result */
558 prevResult->pathpos = pathpos;
559 prevResult->oid = proctup->t_data->t_oid;
560 continue; /* args are same, of course */
566 * Okay to add it to result list
568 newResult = (FuncCandidateList)
569 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
570 + nargs * sizeof(Oid));
571 newResult->pathpos = pathpos;
572 newResult->oid = proctup->t_data->t_oid;
573 newResult->nargs = nargs;
574 memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
576 newResult->next = resultList;
577 resultList = newResult;
580 ReleaseSysCacheList(catlist);
586 * OpernameGetCandidates
587 * Given a possibly-qualified operator name and operator kind,
588 * retrieve a list of the possible matches.
590 * If oprkind is '\0', we return all operators matching the given name,
591 * regardless of arguments.
593 * We search a single namespace if the operator name is qualified, else
594 * all namespaces in the search path. The return list will never contain
595 * multiple entries with identical argument lists --- in the multiple-
596 * namespace case, we arrange for entries in earlier namespaces to mask
597 * identical entries in later namespaces.
599 * The returned items always have two args[] entries --- one or the other
600 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
603 OpernameGetCandidates(List *names, char oprkind)
605 FuncCandidateList resultList = NULL;
607 char *schemaname = NULL;
608 char *opername = NULL;
613 /* deconstruct the name list */
614 switch (length(names))
617 opername = strVal(lfirst(names));
620 schemaname = strVal(lfirst(names));
621 opername = strVal(lsecond(names));
624 catalogname = strVal(lfirst(names));
625 schemaname = strVal(lsecond(names));
626 opername = strVal(lfirst(lnext(lnext(names))));
628 * We check the catalog name and then ignore it.
630 if (strcmp(catalogname, DatabaseName) != 0)
631 elog(ERROR, "Cross-database references are not implemented");
634 elog(ERROR, "Improper qualified name (too many dotted names)");
640 /* use exact schema given */
643 namespaceId = GetSysCacheOid(NAMESPACENAME,
644 CStringGetDatum(schemaname),
646 if (!OidIsValid(namespaceId))
647 elog(ERROR, "Namespace \"%s\" does not exist",
649 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
650 if (aclresult != ACLCHECK_OK)
651 aclcheck_error(aclresult, schemaname);
655 /* flag to indicate we need namespace search */
656 namespaceId = InvalidOid;
657 recomputeNamespacePath();
660 /* Search syscache by name only */
661 catlist = SearchSysCacheList(OPERNAMENSP, 1,
662 CStringGetDatum(opername),
665 for (i = 0; i < catlist->n_members; i++)
667 HeapTuple opertup = &catlist->members[i]->tuple;
668 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
670 FuncCandidateList newResult;
672 /* Ignore operators of wrong kind, if specific kind requested */
673 if (oprkind && operform->oprkind != oprkind)
676 if (OidIsValid(namespaceId))
678 /* Consider only opers in specified namespace */
679 if (operform->oprnamespace != namespaceId)
681 /* No need to check args, they must all be different */
685 /* Consider only opers that are in the search path */
686 if (pathContainsSystemNamespace ||
687 !IsSystemNamespace(operform->oprnamespace))
691 foreach(nsp, namespaceSearchPath)
694 if (operform->oprnamespace == (Oid) lfirsti(nsp))
698 continue; /* oper is not in search path */
702 * Okay, it's in the search path, but does it have the same
703 * arguments as something we already accepted? If so, keep
704 * only the one that appears earlier in the search path.
706 * If we have an ordered list from SearchSysCacheList (the
707 * normal case), then any conflicting oper must immediately
708 * adjoin this one in the list, so we only need to look at
709 * the newest result item. If we have an unordered list,
710 * we have to scan the whole result list.
714 FuncCandidateList prevResult;
716 if (catlist->ordered)
718 if (operform->oprleft == resultList->args[0] &&
719 operform->oprright == resultList->args[1])
720 prevResult = resultList;
726 for (prevResult = resultList;
728 prevResult = prevResult->next)
730 if (operform->oprleft == prevResult->args[0] &&
731 operform->oprright == prevResult->args[1])
737 /* We have a match with a previous result */
738 Assert(pathpos != prevResult->pathpos);
739 if (pathpos > prevResult->pathpos)
740 continue; /* keep previous result */
741 /* replace previous result */
742 prevResult->pathpos = pathpos;
743 prevResult->oid = opertup->t_data->t_oid;
744 continue; /* args are same, of course */
750 * Okay to add it to result list
752 newResult = (FuncCandidateList)
753 palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
754 newResult->pathpos = pathpos;
755 newResult->oid = opertup->t_data->t_oid;
756 newResult->nargs = 2;
757 newResult->args[0] = operform->oprleft;
758 newResult->args[1] = operform->oprright;
759 newResult->next = resultList;
760 resultList = newResult;
763 ReleaseSysCacheList(catlist);
769 * OpclassGetCandidates
770 * Given an index access method OID, retrieve a list of all the
771 * opclasses for that AM that are visible in the search path.
773 * NOTE: the opcname_tmp field in the returned structs should not be used
774 * by callers, because it points at syscache entries that we release at
775 * the end of this routine. If any callers needed the name information,
776 * we could pstrdup() the names ... but at present it'd be wasteful.
779 OpclassGetCandidates(Oid amid)
781 OpclassCandidateList resultList = NULL;
785 recomputeNamespacePath();
787 /* Search syscache by AM OID only */
788 catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
789 ObjectIdGetDatum(amid),
792 for (i = 0; i < catlist->n_members; i++)
794 HeapTuple opctup = &catlist->members[i]->tuple;
795 Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
797 OpclassCandidateList newResult;
799 /* Consider only opclasses that are in the search path */
800 if (pathContainsSystemNamespace ||
801 !IsSystemNamespace(opcform->opcnamespace))
805 foreach(nsp, namespaceSearchPath)
808 if (opcform->opcnamespace == (Oid) lfirsti(nsp))
812 continue; /* opclass is not in search path */
816 * Okay, it's in the search path, but does it have the same name
817 * as something we already accepted? If so, keep
818 * only the one that appears earlier in the search path.
820 * If we have an ordered list from SearchSysCacheList (the
821 * normal case), then any conflicting opclass must immediately
822 * adjoin this one in the list, so we only need to look at
823 * the newest result item. If we have an unordered list,
824 * we have to scan the whole result list.
828 OpclassCandidateList prevResult;
830 if (catlist->ordered)
832 if (strcmp(NameStr(opcform->opcname),
833 resultList->opcname_tmp) == 0)
834 prevResult = resultList;
840 for (prevResult = resultList;
842 prevResult = prevResult->next)
844 if (strcmp(NameStr(opcform->opcname),
845 prevResult->opcname_tmp) == 0)
851 /* We have a match with a previous result */
852 Assert(pathpos != prevResult->pathpos);
853 if (pathpos > prevResult->pathpos)
854 continue; /* keep previous result */
855 /* replace previous result */
856 prevResult->opcname_tmp = NameStr(opcform->opcname);
857 prevResult->pathpos = pathpos;
858 prevResult->oid = opctup->t_data->t_oid;
859 prevResult->opcintype = opcform->opcintype;
860 prevResult->opcdefault = opcform->opcdefault;
861 prevResult->opckeytype = opcform->opckeytype;
867 * Okay to add it to result list
869 newResult = (OpclassCandidateList)
870 palloc(sizeof(struct _OpclassCandidateList));
871 newResult->opcname_tmp = NameStr(opcform->opcname);
872 newResult->pathpos = pathpos;
873 newResult->oid = opctup->t_data->t_oid;
874 newResult->opcintype = opcform->opcintype;
875 newResult->opcdefault = opcform->opcdefault;
876 newResult->opckeytype = opcform->opckeytype;
877 newResult->next = resultList;
878 resultList = newResult;
881 ReleaseSysCacheList(catlist);
888 * QualifiedNameGetCreationNamespace
889 * Given a possibly-qualified name for an object (in List-of-Values
890 * format), determine what namespace the object should be created in.
891 * Also extract and return the object name (last component of list).
893 * This is *not* used for tables. Hence, the TEMP table namespace is
894 * never selected as the creation target.
897 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
900 char *schemaname = NULL;
901 char *objname = NULL;
904 /* deconstruct the name list */
905 switch (length(names))
908 objname = strVal(lfirst(names));
911 schemaname = strVal(lfirst(names));
912 objname = strVal(lsecond(names));
915 catalogname = strVal(lfirst(names));
916 schemaname = strVal(lsecond(names));
917 objname = strVal(lfirst(lnext(lnext(names))));
919 * We check the catalog name and then ignore it.
921 if (strcmp(catalogname, DatabaseName) != 0)
922 elog(ERROR, "Cross-database references are not implemented");
925 elog(ERROR, "Improper qualified name (too many dotted names)");
931 /* use exact schema given */
932 namespaceId = GetSysCacheOid(NAMESPACENAME,
933 CStringGetDatum(schemaname),
935 if (!OidIsValid(namespaceId))
936 elog(ERROR, "Namespace \"%s\" does not exist",
941 /* use the default creation namespace */
942 recomputeNamespacePath();
943 namespaceId = defaultCreationNamespace;
944 if (!OidIsValid(namespaceId))
945 elog(ERROR, "No namespace has been selected to create in");
948 /* Note: callers will check for CREATE rights when appropriate */
950 *objname_p = objname;
955 * makeRangeVarFromNameList
956 * Utility routine to convert a qualified-name list into RangeVar form.
959 makeRangeVarFromNameList(List *names)
961 RangeVar *rel = makeRangeVar(NULL, NULL);
963 switch (length(names))
966 rel->relname = strVal(lfirst(names));
969 rel->schemaname = strVal(lfirst(names));
970 rel->relname = strVal(lsecond(names));
973 rel->catalogname = strVal(lfirst(names));
974 rel->schemaname = strVal(lsecond(names));
975 rel->relname = strVal(lfirst(lnext(lnext(names))));
978 elog(ERROR, "Improper relation name (too many dotted names)");
987 * Utility routine to convert a qualified-name list into a string.
988 * Used primarily to form error messages.
991 NameListToString(List *names)
993 StringInfoData string;
996 initStringInfo(&string);
1001 appendStringInfoChar(&string, '.');
1002 appendStringInfo(&string, "%s", strVal(lfirst(l)));
1009 * isTempNamespace - is the given namespace my temporary-table namespace?
1012 isTempNamespace(Oid namespaceId)
1014 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1020 * recomputeNamespacePath - recompute path derived variables if needed.
1023 recomputeNamespacePath(void)
1025 Oid userId = GetUserId();
1031 MemoryContext oldcxt;
1034 * Do nothing if path is already valid.
1036 if (namespaceSearchPathValid && namespaceUser == userId)
1039 /* Need a modifiable copy of namespace_search_path string */
1040 rawname = pstrdup(namespace_search_path);
1042 /* Parse string into list of identifiers */
1043 if (!SplitIdentifierString(rawname, ',', &namelist))
1045 /* syntax error in name list */
1046 /* this should not happen if GUC checked check_search_path */
1047 elog(ERROR, "recomputeNamespacePath: invalid list syntax");
1051 * Convert the list of names to a list of OIDs. If any names are not
1052 * recognizable or we don't have read access, just leave them out of
1053 * the list. (We can't raise an error, since the search_path setting
1054 * has already been accepted.)
1057 foreach(l, namelist)
1059 char *curname = (char *) lfirst(l);
1062 if (strcmp(curname, "$user") == 0)
1064 /* $user --- substitute namespace matching user name, if any */
1067 tuple = SearchSysCache(SHADOWSYSID,
1068 ObjectIdGetDatum(userId),
1070 if (HeapTupleIsValid(tuple))
1074 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1075 namespaceId = GetSysCacheOid(NAMESPACENAME,
1076 CStringGetDatum(uname),
1078 ReleaseSysCache(tuple);
1079 if (OidIsValid(namespaceId) &&
1080 pg_namespace_aclcheck(namespaceId, userId,
1081 ACL_USAGE) == ACLCHECK_OK)
1082 oidlist = lappendi(oidlist, namespaceId);
1087 /* normal namespace reference */
1088 namespaceId = GetSysCacheOid(NAMESPACENAME,
1089 CStringGetDatum(curname),
1091 if (OidIsValid(namespaceId) &&
1092 pg_namespace_aclcheck(namespaceId, userId,
1093 ACL_USAGE) == ACLCHECK_OK)
1094 oidlist = lappendi(oidlist, namespaceId);
1099 * Now that we've successfully built the new list of namespace OIDs,
1100 * save it in permanent storage.
1102 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1103 newpath = listCopy(oidlist);
1104 MemoryContextSwitchTo(oldcxt);
1106 /* Now safe to assign to state variable. */
1107 freeList(namespaceSearchPath);
1108 namespaceSearchPath = newpath;
1111 * Update info derived from search path.
1113 pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE,
1114 namespaceSearchPath);
1116 if (namespaceSearchPath == NIL)
1117 defaultCreationNamespace = InvalidOid;
1119 defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath);
1121 /* Mark the path valid. */
1122 namespaceSearchPathValid = true;
1123 namespaceUser = userId;
1132 * GetTempTableNamespace
1133 * Initialize temp table namespace on first use in a particular backend
1136 GetTempTableNamespace(void)
1138 char namespaceName[NAMEDATALEN];
1142 * First, do permission check to see if we are authorized to make
1143 * temp tables. We use a nonstandard error message here since
1144 * "databasename: permission denied" might be a tad cryptic.
1146 * Note we apply the check to the session user, not the currently
1147 * active userid, since we are not going to change our minds about
1148 * temp table availability during the session.
1150 if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
1151 ACL_CREATE_TEMP) != ACLCHECK_OK)
1152 elog(ERROR, "%s: not authorized to create temp tables",
1155 snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
1157 namespaceId = GetSysCacheOid(NAMESPACENAME,
1158 CStringGetDatum(namespaceName),
1160 if (!OidIsValid(namespaceId))
1163 * First use of this temp namespace in this database; create it.
1164 * The temp namespaces are always owned by the superuser. We
1165 * leave their permissions at default --- i.e., no access except to
1166 * superuser --- to ensure that unprivileged users can't peek
1167 * at other backends' temp tables. This works because the places
1168 * that access the temp namespace for my own backend skip permissions
1171 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
1172 /* Advance command counter to make namespace visible */
1173 CommandCounterIncrement();
1178 * If the namespace already exists, clean it out (in case the
1179 * former owner crashed without doing so).
1181 RemoveTempRelations(namespaceId);
1185 * Register exit callback to clean out temp tables at backend shutdown.
1187 on_shmem_exit(RemoveTempRelationsCallback, 0);
1193 * Remove all relations in the specified temp namespace.
1195 * This is called at backend shutdown (if we made any temp relations).
1196 * It is also called when we begin using a pre-existing temp namespace,
1197 * in order to clean out any relations that might have been created by
1198 * a crashed backend.
1201 RemoveTempRelations(Oid tempNamespaceId)
1204 List *constraintList;
1207 /* Get a list of relations to delete */
1208 tempRelList = FindTempRelations(tempNamespaceId);
1210 if (tempRelList == NIL)
1211 return; /* nothing to do */
1213 /* If more than one, sort them to respect any deletion-order constraints */
1214 if (length(tempRelList) > 1)
1216 constraintList = FindDeletionConstraints(tempRelList);
1217 if (constraintList != NIL)
1218 tempRelList = TopoSortRels(tempRelList, constraintList);
1221 /* Scan the list and delete all entries */
1222 foreach(lptr, tempRelList)
1224 Oid reloid = (Oid) lfirsti(lptr);
1226 heap_drop_with_catalog(reloid, true);
1228 * Advance cmd counter to make catalog changes visible, in case
1229 * a later entry depends on this one.
1231 CommandCounterIncrement();
1236 * Find all relations in the specified temp namespace.
1238 * Returns a list of relation OIDs.
1241 FindTempRelations(Oid tempNamespaceId)
1243 List *tempRelList = NIL;
1250 * Scan pg_class to find all the relations in the target namespace.
1251 * Ignore indexes, though, on the assumption that they'll go away
1252 * when their tables are deleted.
1254 ScanKeyEntryInitialize(&key, 0x0,
1255 Anum_pg_class_relnamespace,
1257 ObjectIdGetDatum(tempNamespaceId));
1259 pgclass = heap_openr(RelationRelationName, AccessShareLock);
1260 scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
1262 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1264 switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
1266 case RELKIND_RELATION:
1267 case RELKIND_SEQUENCE:
1269 tempRelList = lconsi(tuple->t_data->t_oid, tempRelList);
1277 heap_close(pgclass, AccessShareLock);
1283 * Find deletion-order constraints involving the given relation OIDs.
1285 * Returns a list of DelConstraint objects.
1288 FindDeletionConstraints(List *relOids)
1290 List *constraintList = NIL;
1291 Relation inheritsrel;
1296 * Scan pg_inherits to find parents and children that are in the list.
1298 inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
1299 scan = heap_beginscan(inheritsrel, 0, SnapshotNow, 0, NULL);
1301 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1303 Oid inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
1304 Oid inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
1306 if (intMember(inhrelid, relOids) && intMember(inhparent, relOids))
1308 DelConstraint *item;
1310 item = (DelConstraint *) palloc(sizeof(DelConstraint));
1311 item->referencer = inhrelid;
1312 item->referencee = inhparent;
1313 constraintList = lcons(item, constraintList);
1318 heap_close(inheritsrel, AccessShareLock);
1320 return constraintList;
1324 * TopoSortRels -- topological sort of a list of rels to delete
1326 * This is a lot simpler and slower than, for example, the topological sort
1327 * algorithm shown in Knuth's Volume 1. However, we are not likely to be
1328 * working with more than a few constraints, so the apparent slowness of the
1329 * algorithm won't really matter.
1332 TopoSortRels(List *relOids, List *constraintList)
1334 int queue_size = length(relOids);
1336 int *beforeConstraints;
1337 DelConstraint **afterConstraints;
1338 List *resultList = NIL;
1345 /* Allocate workspace */
1346 rels = (Oid *) palloc(queue_size * sizeof(Oid));
1347 beforeConstraints = (int *) palloc(queue_size * sizeof(int));
1348 afterConstraints = (DelConstraint **)
1349 palloc(queue_size * sizeof(DelConstraint*));
1351 /* Build an array of the target relation OIDs */
1353 foreach(lptr, relOids)
1355 rels[i++] = (Oid) lfirsti(lptr);
1359 * Scan the constraints, and for each rel in the array, generate a
1360 * count of the number of constraints that say it must be before
1361 * something else, plus a list of the constraints that say it must be
1362 * after something else. The count for the j'th rel is stored in
1363 * beforeConstraints[j], and the head of its list in
1364 * afterConstraints[j]. Each constraint stores its list link in
1365 * its link field (note any constraint will be in just one list).
1366 * The array index for the before-rel of each constraint is
1367 * remembered in the constraint's pred field.
1369 MemSet(beforeConstraints, 0, queue_size * sizeof(int));
1370 MemSet(afterConstraints, 0, queue_size * sizeof(DelConstraint*));
1371 foreach(lptr, constraintList)
1373 DelConstraint *constraint = (DelConstraint *) lfirst(lptr);
1376 /* Find the referencer rel in the array */
1377 rel = constraint->referencer;
1378 for (j = queue_size; --j >= 0;)
1383 Assert(j >= 0); /* should have found a match */
1384 /* Find the referencee rel in the array */
1385 rel = constraint->referencee;
1386 for (k = queue_size; --k >= 0;)
1391 Assert(k >= 0); /* should have found a match */
1392 beforeConstraints[j]++; /* referencer must come before */
1393 /* add this constraint to list of after-constraints for referencee */
1394 constraint->pred = j;
1395 constraint->link = afterConstraints[k];
1396 afterConstraints[k] = constraint;
1398 /*--------------------
1399 * Now scan the rels array backwards. At each step, output the
1400 * last rel that has no remaining before-constraints, and decrease
1401 * the beforeConstraints count of each of the rels it was constrained
1402 * against. (This is the right order since we are building the result
1403 * list back-to-front.)
1404 * i = counter for number of rels left to output
1405 * j = search index for rels[]
1406 * dc = temp for scanning constraint list for rel j
1407 * last = last valid index in rels (avoid redundant searches)
1408 *--------------------
1410 last = queue_size - 1;
1411 for (i = queue_size; --i >= 0;)
1415 /* Find next candidate to output */
1416 while (rels[last] == InvalidOid)
1418 for (j = last; j >= 0; j--)
1420 if (rels[j] != InvalidOid && beforeConstraints[j] == 0)
1423 /* If no available candidate, topological sort fails */
1425 elog(ERROR, "TopoSortRels: failed to find a workable deletion ordering");
1426 /* Output candidate, and mark it done by zeroing rels[] entry */
1427 resultList = lconsi(rels[j], resultList);
1428 rels[j] = InvalidOid;
1429 /* Update beforeConstraints counts of its predecessors */
1430 for (dc = afterConstraints[j]; dc; dc = dc->link)
1431 beforeConstraints[dc->pred]--;
1439 * Callback to remove temp relations at backend exit.
1442 RemoveTempRelationsCallback(void)
1444 if (OidIsValid(myTempNamespace)) /* should always be true */
1446 /* Need to ensure we have a usable transaction. */
1447 AbortOutOfAnyTransaction();
1448 StartTransactionCommand();
1450 RemoveTempRelations(myTempNamespace);
1452 CommitTransactionCommand();
1457 * Routines for handling the GUC variable 'search_path'.
1460 /* parse_hook: is proposed value valid? */
1462 check_search_path(const char *proposed)
1468 /* Need a modifiable copy of string */
1469 rawname = pstrdup(proposed);
1471 /* Parse string into list of identifiers */
1472 if (!SplitIdentifierString(rawname, ',', &namelist))
1474 /* syntax error in name list */
1481 * If we aren't inside a transaction, we cannot do database access so
1482 * cannot verify the individual names. Must accept the list on faith.
1483 * (This case can happen, for example, when the postmaster reads a
1484 * search_path setting from postgresql.conf.)
1486 if (!IsTransactionState())
1494 * Verify that all the names are either valid namespace names or "$user".
1495 * We do not require $user to correspond to a valid namespace.
1496 * We do not check for USAGE rights, either; should we?
1498 foreach(l, namelist)
1500 char *curname = (char *) lfirst(l);
1502 if (strcmp(curname, "$user") == 0)
1504 if (!SearchSysCacheExists(NAMESPACENAME,
1505 CStringGetDatum(curname),
1520 /* assign_hook: do extra actions needed when assigning to search_path */
1522 assign_search_path(const char *newval)
1525 * We mark the path as needing recomputation, but don't do anything until
1526 * it's needed. This avoids trying to do database access during GUC
1529 namespaceSearchPathValid = false;
1533 * InitializeSearchPath: initialize module during InitPostgres.
1535 * This is called after we are up enough to be able to do catalog lookups.
1538 InitializeSearchPath(void)
1540 if (IsBootstrapProcessingMode())
1543 * In bootstrap mode, the search path must be 'pg_catalog' so that
1544 * tables are created in the proper namespace; ignore the GUC setting.
1546 MemoryContext oldcxt;
1548 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1549 namespaceSearchPath = makeListi1(PG_CATALOG_NAMESPACE);
1550 MemoryContextSwitchTo(oldcxt);
1551 pathContainsSystemNamespace = true;
1552 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1553 namespaceSearchPathValid = true;
1554 namespaceUser = GetUserId();
1559 * In normal mode, arrange for a callback on any syscache invalidation
1560 * of pg_namespace rows.
1562 CacheRegisterSyscacheCallback(NAMESPACEOID,
1570 * Syscache inval callback function
1573 NamespaceCallback(Datum arg, Oid relid)
1575 /* Force search path to be recomputed on next use */
1576 namespaceSearchPathValid = false;
1580 * Fetch the active search path, expressed as a List of OIDs.
1582 * NB: caller must treat the list as read-only!
1585 fetch_search_path(void)
1587 recomputeNamespacePath();
1588 return namespaceSearchPath;