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.12 2002/04/25 02:56:55 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/builtins.h"
39 #include "utils/fmgroids.h"
40 #include "utils/guc.h"
41 #include "utils/catcache.h"
42 #include "utils/lsyscache.h"
43 #include "utils/syscache.h"
47 * The namespace search path is a possibly-empty list of namespace OIDs.
48 * In addition to the explicit list, the TEMP table namespace is always
49 * implicitly searched first (if it's been initialized). Also, the system
50 * catalog namespace is always searched. If the system namespace is
51 * explicitly present in the path then it will be searched in the specified
52 * order; otherwise it will be searched after TEMP tables and *before* the
53 * explicit list. (It might seem that the system namespace should be
54 * implicitly last, but this behavior appears to be required by SQL99.
55 * Also, this provides a way to search the system namespace first without
56 * thereby making it the default creation target namespace.)
58 * The default creation target namespace is kept equal to the first element
59 * of the (explicit) list. If the list is empty, there is no default target.
61 * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
62 * the system namespace is the only one searched or inserted into.
63 * The initdb script is also careful to set search_path to 'pg_catalog' for
64 * its post-bootstrap standalone backend runs. Otherwise the default search
65 * path is determined by GUC. The factory default path contains the PUBLIC
66 * namespace (if it exists), preceded by the user's personal namespace
70 static List *namespaceSearchPath = NIL;
72 /* this flag must be updated correctly when namespaceSearchPath is changed */
73 static bool pathContainsSystemNamespace = false;
75 /* default place to create stuff; if InvalidOid, no default */
76 static Oid defaultCreationNamespace = InvalidOid;
79 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
80 * in a particular backend session (this happens when a CREATE TEMP TABLE
81 * command is first executed). Thereafter it's the OID of the temp namespace.
83 static Oid myTempNamespace = InvalidOid;
86 * This is the text equivalent of the search path --- it's the value
87 * of the GUC variable 'search_path'.
89 char *namespace_search_path = NULL;
93 * Deletion ordering constraint item.
95 typedef struct DelConstraint
97 Oid referencer; /* table to delete first */
98 Oid referencee; /* table to delete second */
99 int pred; /* workspace for TopoSortRels */
100 struct DelConstraint *link; /* workspace for TopoSortRels */
104 /* Local functions */
105 static Oid GetTempTableNamespace(void);
106 static void RemoveTempRelations(Oid tempNamespaceId);
107 static List *FindTempRelations(Oid tempNamespaceId);
108 static List *FindDeletionConstraints(List *relOids);
109 static List *TopoSortRels(List *relOids, List *constraintList);
110 static void RemoveTempRelationsCallback(void);
115 * Given a RangeVar describing an existing relation,
116 * select the proper namespace and look up the relation OID.
118 * If the relation is not found, return InvalidOid if failOK = true,
119 * otherwise raise an error.
122 RangeVarGetRelid(const RangeVar *relation, bool failOK)
128 * We check the catalog name and then ignore it.
130 if (relation->catalogname)
132 if (strcmp(relation->catalogname, DatabaseName) != 0)
133 elog(ERROR, "Cross-database references are not implemented");
136 if (relation->schemaname)
138 /* use exact schema given */
139 namespaceId = GetSysCacheOid(NAMESPACENAME,
140 CStringGetDatum(relation->schemaname),
142 if (!OidIsValid(namespaceId))
143 elog(ERROR, "Namespace \"%s\" does not exist",
144 relation->schemaname);
145 relId = get_relname_relid(relation->relname, namespaceId);
149 /* search the namespace path */
150 relId = RelnameGetRelid(relation->relname);
153 if (!OidIsValid(relId) && !failOK)
155 if (relation->schemaname)
156 elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
157 relation->schemaname, relation->relname);
159 elog(ERROR, "Relation \"%s\" does not exist",
166 * RangeVarGetCreationNamespace
167 * Given a RangeVar describing a to-be-created relation,
168 * choose which namespace to create it in.
170 * Note: calling this may result in a CommandCounterIncrement operation.
171 * That will happen on the first request for a temp table in any particular
172 * backend run; we will need to either create or clean out the temp schema.
175 RangeVarGetCreationNamespace(const RangeVar *newRelation)
180 * We check the catalog name and then ignore it.
182 if (newRelation->catalogname)
184 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
185 elog(ERROR, "Cross-database references are not implemented");
188 if (newRelation->istemp)
190 /* TEMP tables are created in our backend-local temp namespace */
191 if (newRelation->schemaname)
192 elog(ERROR, "TEMP tables may not specify a namespace");
193 /* Initialize temp namespace if first time through */
194 if (!OidIsValid(myTempNamespace))
195 myTempNamespace = GetTempTableNamespace();
196 return myTempNamespace;
199 if (newRelation->schemaname)
201 /* use exact schema given */
202 namespaceId = GetSysCacheOid(NAMESPACENAME,
203 CStringGetDatum(newRelation->schemaname),
205 if (!OidIsValid(namespaceId))
206 elog(ERROR, "Namespace \"%s\" does not exist",
207 newRelation->schemaname);
211 /* use the default creation namespace */
212 namespaceId = defaultCreationNamespace;
213 if (!OidIsValid(namespaceId))
214 elog(ERROR, "No namespace has been selected to create in");
222 * Try to resolve an unqualified relation name.
223 * Returns OID if relation found in search path, else InvalidOid.
226 RelnameGetRelid(const char *relname)
232 * If a TEMP-table namespace has been set up, it is implicitly first
233 * in the search path.
235 if (OidIsValid(myTempNamespace))
237 relid = get_relname_relid(relname, myTempNamespace);
238 if (OidIsValid(relid))
243 * If system namespace is not in path, implicitly search it before path
245 if (!pathContainsSystemNamespace)
247 relid = get_relname_relid(relname, PG_CATALOG_NAMESPACE);
248 if (OidIsValid(relid))
253 * Else search the path
255 foreach(lptr, namespaceSearchPath)
257 Oid namespaceId = (Oid) lfirsti(lptr);
259 relid = get_relname_relid(relname, namespaceId);
260 if (OidIsValid(relid))
264 /* Not found in path */
270 * Try to resolve an unqualified datatype name.
271 * Returns OID if type found in search path, else InvalidOid.
273 * This is essentially the same as RelnameGetRelid, but we never search
274 * the TEMP table namespace --- there is no reason to refer to the types
275 * of temp tables, AFAICS.
278 TypenameGetTypid(const char *typname)
284 * If system namespace is not in path, implicitly search it before path
286 if (!pathContainsSystemNamespace)
288 typid = GetSysCacheOid(TYPENAMENSP,
289 PointerGetDatum(typname),
290 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
292 if (OidIsValid(typid))
297 * Else search the path
299 foreach(lptr, namespaceSearchPath)
301 Oid namespaceId = (Oid) lfirsti(lptr);
303 typid = GetSysCacheOid(TYPENAMENSP,
304 PointerGetDatum(typname),
305 ObjectIdGetDatum(namespaceId),
307 if (OidIsValid(typid))
311 /* Not found in path */
316 * OpclassnameGetOpcid
317 * Try to resolve an unqualified index opclass name.
318 * Returns OID if opclass found in search path, else InvalidOid.
320 * This is essentially the same as TypenameGetTypid, but we have to have
321 * an extra argument for the index AM OID.
324 OpclassnameGetOpcid(Oid amid, const char *opcname)
330 * If system namespace is not in path, implicitly search it before path
332 if (!pathContainsSystemNamespace)
334 opcid = GetSysCacheOid(CLAAMNAMENSP,
335 ObjectIdGetDatum(amid),
336 PointerGetDatum(opcname),
337 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
339 if (OidIsValid(opcid))
344 * Else search the path
346 foreach(lptr, namespaceSearchPath)
348 Oid namespaceId = (Oid) lfirsti(lptr);
350 opcid = GetSysCacheOid(CLAAMNAMENSP,
351 ObjectIdGetDatum(amid),
352 PointerGetDatum(opcname),
353 ObjectIdGetDatum(namespaceId),
355 if (OidIsValid(opcid))
359 /* Not found in path */
364 * FuncnameGetCandidates
365 * Given a possibly-qualified function name and argument count,
366 * retrieve a list of the possible matches.
368 * If nargs is -1, we return all functions matching the given name,
369 * regardless of argument count.
371 * We search a single namespace if the function name is qualified, else
372 * all namespaces in the search path. The return list will never contain
373 * multiple entries with identical argument lists --- in the multiple-
374 * namespace case, we arrange for entries in earlier namespaces to mask
375 * identical entries in later namespaces.
378 FuncnameGetCandidates(List *names, int nargs)
380 FuncCandidateList resultList = NULL;
382 char *schemaname = NULL;
383 char *funcname = NULL;
388 /* deconstruct the name list */
389 switch (length(names))
392 funcname = strVal(lfirst(names));
395 schemaname = strVal(lfirst(names));
396 funcname = strVal(lsecond(names));
399 catalogname = strVal(lfirst(names));
400 schemaname = strVal(lsecond(names));
401 funcname = strVal(lfirst(lnext(lnext(names))));
403 * We check the catalog name and then ignore it.
405 if (strcmp(catalogname, DatabaseName) != 0)
406 elog(ERROR, "Cross-database references are not implemented");
409 elog(ERROR, "Improper qualified name (too many dotted names)");
415 /* use exact schema given */
416 namespaceId = GetSysCacheOid(NAMESPACENAME,
417 CStringGetDatum(schemaname),
419 if (!OidIsValid(namespaceId))
420 elog(ERROR, "Namespace \"%s\" does not exist",
425 /* flag to indicate we need namespace search */
426 namespaceId = InvalidOid;
429 /* Search syscache by name and (optionally) nargs only */
431 catlist = SearchSysCacheList(PROCNAMENSP, 2,
432 CStringGetDatum(funcname),
433 Int16GetDatum(nargs),
436 catlist = SearchSysCacheList(PROCNAMENSP, 1,
437 CStringGetDatum(funcname),
440 for (i = 0; i < catlist->n_members; i++)
442 HeapTuple proctup = &catlist->members[i]->tuple;
443 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
445 FuncCandidateList newResult;
447 nargs = procform->pronargs;
449 if (OidIsValid(namespaceId))
451 /* Consider only procs in specified namespace */
452 if (procform->pronamespace != namespaceId)
454 /* No need to check args, they must all be different */
458 /* Consider only procs that are in the search path */
459 if (pathContainsSystemNamespace ||
460 !IsSystemNamespace(procform->pronamespace))
464 foreach(nsp, namespaceSearchPath)
467 if (procform->pronamespace == (Oid) lfirsti(nsp))
471 continue; /* proc is not in search path */
475 * Okay, it's in the search path, but does it have the same
476 * arguments as something we already accepted? If so, keep
477 * only the one that appears earlier in the search path.
479 * If we have an ordered list from SearchSysCacheList (the
480 * normal case), then any conflicting proc must immediately
481 * adjoin this one in the list, so we only need to look at
482 * the newest result item. If we have an unordered list,
483 * we have to scan the whole result list.
487 FuncCandidateList prevResult;
489 if (catlist->ordered)
491 if (nargs == resultList->nargs &&
492 memcmp(procform->proargtypes, resultList->args,
493 nargs * sizeof(Oid)) == 0)
494 prevResult = resultList;
500 for (prevResult = resultList;
502 prevResult = prevResult->next)
504 if (nargs == prevResult->nargs &&
505 memcmp(procform->proargtypes, prevResult->args,
506 nargs * sizeof(Oid)) == 0)
512 /* We have a match with a previous result */
513 Assert(pathpos != prevResult->pathpos);
514 if (pathpos > prevResult->pathpos)
515 continue; /* keep previous result */
516 /* replace previous result */
517 prevResult->pathpos = pathpos;
518 prevResult->oid = proctup->t_data->t_oid;
519 continue; /* args are same, of course */
525 * Okay to add it to result list
527 newResult = (FuncCandidateList)
528 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
529 + nargs * sizeof(Oid));
530 newResult->pathpos = pathpos;
531 newResult->oid = proctup->t_data->t_oid;
532 newResult->nargs = nargs;
533 memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
535 newResult->next = resultList;
536 resultList = newResult;
539 ReleaseSysCacheList(catlist);
545 * OpernameGetCandidates
546 * Given a possibly-qualified operator name and operator kind,
547 * retrieve a list of the possible matches.
549 * If oprkind is '\0', we return all operators matching the given name,
550 * regardless of arguments.
552 * We search a single namespace if the operator name is qualified, else
553 * all namespaces in the search path. The return list will never contain
554 * multiple entries with identical argument lists --- in the multiple-
555 * namespace case, we arrange for entries in earlier namespaces to mask
556 * identical entries in later namespaces.
558 * The returned items always have two args[] entries --- one or the other
559 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
562 OpernameGetCandidates(List *names, char oprkind)
564 FuncCandidateList resultList = NULL;
566 char *schemaname = NULL;
567 char *opername = NULL;
572 /* deconstruct the name list */
573 switch (length(names))
576 opername = strVal(lfirst(names));
579 schemaname = strVal(lfirst(names));
580 opername = strVal(lsecond(names));
583 catalogname = strVal(lfirst(names));
584 schemaname = strVal(lsecond(names));
585 opername = strVal(lfirst(lnext(lnext(names))));
587 * We check the catalog name and then ignore it.
589 if (strcmp(catalogname, DatabaseName) != 0)
590 elog(ERROR, "Cross-database references are not implemented");
593 elog(ERROR, "Improper qualified name (too many dotted names)");
599 /* use exact schema given */
600 namespaceId = GetSysCacheOid(NAMESPACENAME,
601 CStringGetDatum(schemaname),
603 if (!OidIsValid(namespaceId))
604 elog(ERROR, "Namespace \"%s\" does not exist",
609 /* flag to indicate we need namespace search */
610 namespaceId = InvalidOid;
613 /* Search syscache by name only */
614 catlist = SearchSysCacheList(OPERNAMENSP, 1,
615 CStringGetDatum(opername),
618 for (i = 0; i < catlist->n_members; i++)
620 HeapTuple opertup = &catlist->members[i]->tuple;
621 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
623 FuncCandidateList newResult;
625 /* Ignore operators of wrong kind, if specific kind requested */
626 if (oprkind && operform->oprkind != oprkind)
629 if (OidIsValid(namespaceId))
631 /* Consider only opers in specified namespace */
632 if (operform->oprnamespace != namespaceId)
634 /* No need to check args, they must all be different */
638 /* Consider only opers that are in the search path */
639 if (pathContainsSystemNamespace ||
640 !IsSystemNamespace(operform->oprnamespace))
644 foreach(nsp, namespaceSearchPath)
647 if (operform->oprnamespace == (Oid) lfirsti(nsp))
651 continue; /* oper is not in search path */
655 * Okay, it's in the search path, but does it have the same
656 * arguments as something we already accepted? If so, keep
657 * only the one that appears earlier in the search path.
659 * If we have an ordered list from SearchSysCacheList (the
660 * normal case), then any conflicting oper must immediately
661 * adjoin this one in the list, so we only need to look at
662 * the newest result item. If we have an unordered list,
663 * we have to scan the whole result list.
667 FuncCandidateList prevResult;
669 if (catlist->ordered)
671 if (operform->oprleft == resultList->args[0] &&
672 operform->oprright == resultList->args[1])
673 prevResult = resultList;
679 for (prevResult = resultList;
681 prevResult = prevResult->next)
683 if (operform->oprleft == prevResult->args[0] &&
684 operform->oprright == prevResult->args[1])
690 /* We have a match with a previous result */
691 Assert(pathpos != prevResult->pathpos);
692 if (pathpos > prevResult->pathpos)
693 continue; /* keep previous result */
694 /* replace previous result */
695 prevResult->pathpos = pathpos;
696 prevResult->oid = opertup->t_data->t_oid;
697 continue; /* args are same, of course */
703 * Okay to add it to result list
705 newResult = (FuncCandidateList)
706 palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
707 newResult->pathpos = pathpos;
708 newResult->oid = opertup->t_data->t_oid;
709 newResult->nargs = 2;
710 newResult->args[0] = operform->oprleft;
711 newResult->args[1] = operform->oprright;
712 newResult->next = resultList;
713 resultList = newResult;
716 ReleaseSysCacheList(catlist);
722 * OpclassGetCandidates
723 * Given an index access method OID, retrieve a list of all the
724 * opclasses for that AM that are visible in the search path.
726 * NOTE: the opcname_tmp field in the returned structs should not be used
727 * by callers, because it points at syscache entries that we release at
728 * the end of this routine. If any callers needed the name information,
729 * we could pstrdup() the names ... but at present it'd be wasteful.
732 OpclassGetCandidates(Oid amid)
734 OpclassCandidateList resultList = NULL;
738 /* Search syscache by AM OID only */
739 catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
740 ObjectIdGetDatum(amid),
743 for (i = 0; i < catlist->n_members; i++)
745 HeapTuple opctup = &catlist->members[i]->tuple;
746 Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
748 OpclassCandidateList newResult;
750 /* Consider only opclasses that are in the search path */
751 if (pathContainsSystemNamespace ||
752 !IsSystemNamespace(opcform->opcnamespace))
756 foreach(nsp, namespaceSearchPath)
759 if (opcform->opcnamespace == (Oid) lfirsti(nsp))
763 continue; /* opclass is not in search path */
767 * Okay, it's in the search path, but does it have the same name
768 * as something we already accepted? If so, keep
769 * only the one that appears earlier in the search path.
771 * If we have an ordered list from SearchSysCacheList (the
772 * normal case), then any conflicting opclass must immediately
773 * adjoin this one in the list, so we only need to look at
774 * the newest result item. If we have an unordered list,
775 * we have to scan the whole result list.
779 OpclassCandidateList prevResult;
781 if (catlist->ordered)
783 if (strcmp(NameStr(opcform->opcname),
784 resultList->opcname_tmp) == 0)
785 prevResult = resultList;
791 for (prevResult = resultList;
793 prevResult = prevResult->next)
795 if (strcmp(NameStr(opcform->opcname),
796 prevResult->opcname_tmp) == 0)
802 /* We have a match with a previous result */
803 Assert(pathpos != prevResult->pathpos);
804 if (pathpos > prevResult->pathpos)
805 continue; /* keep previous result */
806 /* replace previous result */
807 prevResult->opcname_tmp = NameStr(opcform->opcname);
808 prevResult->pathpos = pathpos;
809 prevResult->oid = opctup->t_data->t_oid;
810 prevResult->opcintype = opcform->opcintype;
811 prevResult->opcdefault = opcform->opcdefault;
812 prevResult->opckeytype = opcform->opckeytype;
818 * Okay to add it to result list
820 newResult = (OpclassCandidateList)
821 palloc(sizeof(struct _OpclassCandidateList));
822 newResult->opcname_tmp = NameStr(opcform->opcname);
823 newResult->pathpos = pathpos;
824 newResult->oid = opctup->t_data->t_oid;
825 newResult->opcintype = opcform->opcintype;
826 newResult->opcdefault = opcform->opcdefault;
827 newResult->opckeytype = opcform->opckeytype;
828 newResult->next = resultList;
829 resultList = newResult;
832 ReleaseSysCacheList(catlist);
839 * QualifiedNameGetCreationNamespace
840 * Given a possibly-qualified name for an object (in List-of-Values
841 * format), determine what namespace the object should be created in.
842 * Also extract and return the object name (last component of list).
844 * This is *not* used for tables. Hence, the TEMP table namespace is
845 * never selected as the creation target.
848 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
851 char *schemaname = NULL;
852 char *objname = NULL;
855 /* deconstruct the name list */
856 switch (length(names))
859 objname = strVal(lfirst(names));
862 schemaname = strVal(lfirst(names));
863 objname = strVal(lsecond(names));
866 catalogname = strVal(lfirst(names));
867 schemaname = strVal(lsecond(names));
868 objname = strVal(lfirst(lnext(lnext(names))));
870 * We check the catalog name and then ignore it.
872 if (strcmp(catalogname, DatabaseName) != 0)
873 elog(ERROR, "Cross-database references are not implemented");
876 elog(ERROR, "Improper qualified name (too many dotted names)");
882 /* use exact schema given */
883 namespaceId = GetSysCacheOid(NAMESPACENAME,
884 CStringGetDatum(schemaname),
886 if (!OidIsValid(namespaceId))
887 elog(ERROR, "Namespace \"%s\" does not exist",
892 /* use the default creation namespace */
893 namespaceId = defaultCreationNamespace;
894 if (!OidIsValid(namespaceId))
895 elog(ERROR, "No namespace has been selected to create in");
898 *objname_p = objname;
903 * makeRangeVarFromNameList
904 * Utility routine to convert a qualified-name list into RangeVar form.
907 makeRangeVarFromNameList(List *names)
909 RangeVar *rel = makeRangeVar(NULL, NULL);
911 switch (length(names))
914 rel->relname = strVal(lfirst(names));
917 rel->schemaname = strVal(lfirst(names));
918 rel->relname = strVal(lsecond(names));
921 rel->catalogname = strVal(lfirst(names));
922 rel->schemaname = strVal(lsecond(names));
923 rel->relname = strVal(lfirst(lnext(lnext(names))));
926 elog(ERROR, "Improper relation name (too many dotted names)");
935 * Utility routine to convert a qualified-name list into a string.
936 * Used primarily to form error messages.
939 NameListToString(List *names)
941 StringInfoData string;
944 initStringInfo(&string);
949 appendStringInfoChar(&string, '.');
950 appendStringInfo(&string, "%s", strVal(lfirst(l)));
957 * isTempNamespace - is the given namespace my temporary-table namespace?
960 isTempNamespace(Oid namespaceId)
962 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
968 * GetTempTableNamespace
969 * Initialize temp table namespace on first use in a particular backend
972 GetTempTableNamespace(void)
974 char namespaceName[NAMEDATALEN];
977 snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
979 namespaceId = GetSysCacheOid(NAMESPACENAME,
980 CStringGetDatum(namespaceName),
982 if (!OidIsValid(namespaceId))
985 * First use of this temp namespace in this database; create it.
986 * The temp namespaces are always owned by the superuser.
988 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
989 /* Advance command counter to make namespace visible */
990 CommandCounterIncrement();
995 * If the namespace already exists, clean it out (in case the
996 * former owner crashed without doing so).
998 RemoveTempRelations(namespaceId);
1002 * Register exit callback to clean out temp tables at backend shutdown.
1004 on_shmem_exit(RemoveTempRelationsCallback, 0);
1010 * Remove all relations in the specified temp namespace.
1012 * This is called at backend shutdown (if we made any temp relations).
1013 * It is also called when we begin using a pre-existing temp namespace,
1014 * in order to clean out any relations that might have been created by
1015 * a crashed backend.
1018 RemoveTempRelations(Oid tempNamespaceId)
1021 List *constraintList;
1024 /* Get a list of relations to delete */
1025 tempRelList = FindTempRelations(tempNamespaceId);
1027 if (tempRelList == NIL)
1028 return; /* nothing to do */
1030 /* If more than one, sort them to respect any deletion-order constraints */
1031 if (length(tempRelList) > 1)
1033 constraintList = FindDeletionConstraints(tempRelList);
1034 if (constraintList != NIL)
1035 tempRelList = TopoSortRels(tempRelList, constraintList);
1038 /* Scan the list and delete all entries */
1039 foreach(lptr, tempRelList)
1041 Oid reloid = (Oid) lfirsti(lptr);
1043 heap_drop_with_catalog(reloid, true);
1045 * Advance cmd counter to make catalog changes visible, in case
1046 * a later entry depends on this one.
1048 CommandCounterIncrement();
1053 * Find all relations in the specified temp namespace.
1055 * Returns a list of relation OIDs.
1058 FindTempRelations(Oid tempNamespaceId)
1060 List *tempRelList = NIL;
1067 * Scan pg_class to find all the relations in the target namespace.
1068 * Ignore indexes, though, on the assumption that they'll go away
1069 * when their tables are deleted.
1071 ScanKeyEntryInitialize(&key, 0x0,
1072 Anum_pg_class_relnamespace,
1074 ObjectIdGetDatum(tempNamespaceId));
1076 pgclass = heap_openr(RelationRelationName, AccessShareLock);
1077 scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
1079 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1081 switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
1083 case RELKIND_RELATION:
1084 case RELKIND_SEQUENCE:
1086 tempRelList = lconsi(tuple->t_data->t_oid, tempRelList);
1094 heap_close(pgclass, AccessShareLock);
1100 * Find deletion-order constraints involving the given relation OIDs.
1102 * Returns a list of DelConstraint objects.
1105 FindDeletionConstraints(List *relOids)
1107 List *constraintList = NIL;
1108 Relation inheritsrel;
1113 * Scan pg_inherits to find parents and children that are in the list.
1115 inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
1116 scan = heap_beginscan(inheritsrel, 0, SnapshotNow, 0, NULL);
1118 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1120 Oid inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
1121 Oid inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
1123 if (intMember(inhrelid, relOids) && intMember(inhparent, relOids))
1125 DelConstraint *item;
1127 item = (DelConstraint *) palloc(sizeof(DelConstraint));
1128 item->referencer = inhrelid;
1129 item->referencee = inhparent;
1130 constraintList = lcons(item, constraintList);
1135 heap_close(inheritsrel, AccessShareLock);
1137 return constraintList;
1141 * TopoSortRels -- topological sort of a list of rels to delete
1143 * This is a lot simpler and slower than, for example, the topological sort
1144 * algorithm shown in Knuth's Volume 1. However, we are not likely to be
1145 * working with more than a few constraints, so the apparent slowness of the
1146 * algorithm won't really matter.
1149 TopoSortRels(List *relOids, List *constraintList)
1151 int queue_size = length(relOids);
1153 int *beforeConstraints;
1154 DelConstraint **afterConstraints;
1155 List *resultList = NIL;
1162 /* Allocate workspace */
1163 rels = (Oid *) palloc(queue_size * sizeof(Oid));
1164 beforeConstraints = (int *) palloc(queue_size * sizeof(int));
1165 afterConstraints = (DelConstraint **)
1166 palloc(queue_size * sizeof(DelConstraint*));
1168 /* Build an array of the target relation OIDs */
1170 foreach(lptr, relOids)
1172 rels[i++] = (Oid) lfirsti(lptr);
1176 * Scan the constraints, and for each rel in the array, generate a
1177 * count of the number of constraints that say it must be before
1178 * something else, plus a list of the constraints that say it must be
1179 * after something else. The count for the j'th rel is stored in
1180 * beforeConstraints[j], and the head of its list in
1181 * afterConstraints[j]. Each constraint stores its list link in
1182 * its link field (note any constraint will be in just one list).
1183 * The array index for the before-rel of each constraint is
1184 * remembered in the constraint's pred field.
1186 MemSet(beforeConstraints, 0, queue_size * sizeof(int));
1187 MemSet(afterConstraints, 0, queue_size * sizeof(DelConstraint*));
1188 foreach(lptr, constraintList)
1190 DelConstraint *constraint = (DelConstraint *) lfirst(lptr);
1193 /* Find the referencer rel in the array */
1194 rel = constraint->referencer;
1195 for (j = queue_size; --j >= 0;)
1200 Assert(j >= 0); /* should have found a match */
1201 /* Find the referencee rel in the array */
1202 rel = constraint->referencee;
1203 for (k = queue_size; --k >= 0;)
1208 Assert(k >= 0); /* should have found a match */
1209 beforeConstraints[j]++; /* referencer must come before */
1210 /* add this constraint to list of after-constraints for referencee */
1211 constraint->pred = j;
1212 constraint->link = afterConstraints[k];
1213 afterConstraints[k] = constraint;
1215 /*--------------------
1216 * Now scan the rels array backwards. At each step, output the
1217 * last rel that has no remaining before-constraints, and decrease
1218 * the beforeConstraints count of each of the rels it was constrained
1219 * against. (This is the right order since we are building the result
1220 * list back-to-front.)
1221 * i = counter for number of rels left to output
1222 * j = search index for rels[]
1223 * dc = temp for scanning constraint list for rel j
1224 * last = last valid index in rels (avoid redundant searches)
1225 *--------------------
1227 last = queue_size - 1;
1228 for (i = queue_size; --i >= 0;)
1232 /* Find next candidate to output */
1233 while (rels[last] == InvalidOid)
1235 for (j = last; j >= 0; j--)
1237 if (rels[j] != InvalidOid && beforeConstraints[j] == 0)
1240 /* If no available candidate, topological sort fails */
1242 elog(ERROR, "TopoSortRels: failed to find a workable deletion ordering");
1243 /* Output candidate, and mark it done by zeroing rels[] entry */
1244 resultList = lconsi(rels[j], resultList);
1245 rels[j] = InvalidOid;
1246 /* Update beforeConstraints counts of its predecessors */
1247 for (dc = afterConstraints[j]; dc; dc = dc->link)
1248 beforeConstraints[dc->pred]--;
1256 * Callback to remove temp relations at backend exit.
1259 RemoveTempRelationsCallback(void)
1261 if (OidIsValid(myTempNamespace)) /* should always be true */
1263 /* Need to ensure we have a usable transaction. */
1264 AbortOutOfAnyTransaction();
1265 StartTransactionCommand();
1267 RemoveTempRelations(myTempNamespace);
1269 CommitTransactionCommand();
1274 * Routines for handling the GUC variable 'search_path'.
1277 /* parse_hook: is proposed value valid? */
1279 check_search_path(const char *proposed)
1285 /* Need a modifiable copy of string */
1286 rawname = pstrdup(proposed);
1288 /* Parse string into list of identifiers */
1289 if (!SplitIdentifierString(rawname, ',', &namelist))
1291 /* syntax error in name list */
1298 * If we aren't inside a transaction, we cannot do database access so
1299 * cannot verify the individual names. Must accept the list on faith.
1300 * (This case can happen, for example, when the postmaster reads a
1301 * search_path setting from postgresql.conf.)
1303 if (!IsTransactionState())
1311 * Verify that all the names are either valid namespace names or "$user".
1312 * (We do not require $user to correspond to a valid namespace; should we?)
1314 foreach(l, namelist)
1316 char *curname = (char *) lfirst(l);
1318 if (strcmp(curname, "$user") == 0)
1320 if (!SearchSysCacheExists(NAMESPACENAME,
1321 CStringGetDatum(curname),
1336 /* assign_hook: do extra actions needed when assigning to search_path */
1338 assign_search_path(const char *newval)
1345 MemoryContext oldcxt;
1348 * If we aren't inside a transaction, we cannot do database access so
1349 * cannot look up the names. In this case, do nothing; the internal
1350 * search path will be fixed later by InitializeSearchPath. (We assume
1351 * this situation can only happen in the postmaster or early in backend
1354 if (!IsTransactionState())
1357 /* Need a modifiable copy of string */
1358 rawname = pstrdup(newval);
1360 /* Parse string into list of identifiers */
1361 if (!SplitIdentifierString(rawname, ',', &namelist))
1363 /* syntax error in name list */
1364 /* this should not happen if GUC checked check_search_path */
1365 elog(ERROR, "assign_search_path: invalid list syntax");
1369 * Convert the list of names to a list of OIDs. If any names are not
1370 * recognizable, just leave them out of the list. (This is our only
1371 * reasonable recourse when the already-accepted default is bogus.)
1374 foreach(l, namelist)
1376 char *curname = (char *) lfirst(l);
1379 if (strcmp(curname, "$user") == 0)
1381 /* $user --- substitute namespace matching user name, if any */
1384 tuple = SearchSysCache(SHADOWSYSID,
1385 ObjectIdGetDatum(GetSessionUserId()),
1387 if (HeapTupleIsValid(tuple))
1391 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1392 namespaceId = GetSysCacheOid(NAMESPACENAME,
1393 CStringGetDatum(uname),
1395 if (OidIsValid(namespaceId))
1396 oidlist = lappendi(oidlist, namespaceId);
1397 ReleaseSysCache(tuple);
1402 /* normal namespace reference */
1403 namespaceId = GetSysCacheOid(NAMESPACENAME,
1404 CStringGetDatum(curname),
1406 if (OidIsValid(namespaceId))
1407 oidlist = lappendi(oidlist, namespaceId);
1412 * Now that we've successfully built the new list of namespace OIDs,
1413 * save it in permanent storage.
1415 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1416 newpath = listCopy(oidlist);
1417 MemoryContextSwitchTo(oldcxt);
1419 /* Now safe to assign to state variable. */
1420 freeList(namespaceSearchPath);
1421 namespaceSearchPath = newpath;
1424 * Update info derived from search path.
1426 pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE,
1427 namespaceSearchPath);
1429 if (namespaceSearchPath == NIL)
1430 defaultCreationNamespace = InvalidOid;
1432 defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath);
1441 * InitializeSearchPath: initialize module during InitPostgres.
1443 * This is called after we are up enough to be able to do catalog lookups.
1446 InitializeSearchPath(void)
1448 if (IsBootstrapProcessingMode())
1451 * In bootstrap mode, the search path must be 'pg_catalog' so that
1452 * tables are created in the proper namespace; ignore the GUC setting.
1454 MemoryContext oldcxt;
1456 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1457 namespaceSearchPath = makeListi1(PG_CATALOG_NAMESPACE);
1458 MemoryContextSwitchTo(oldcxt);
1459 pathContainsSystemNamespace = true;
1460 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1465 * If a search path setting was provided before we were able to
1466 * execute lookups, establish the internal search path now.
1468 if (namespace_search_path && *namespace_search_path &&
1469 namespaceSearchPath == NIL)
1470 assign_search_path(namespace_search_path);