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.5 2002/04/01 03:34:25 tgl Exp $
18 *-------------------------------------------------------------------------
22 #include "access/heapam.h"
23 #include "access/xact.h"
24 #include "catalog/catname.h"
25 #include "catalog/heap.h"
26 #include "catalog/namespace.h"
27 #include "catalog/pg_inherits.h"
28 #include "catalog/pg_namespace.h"
29 #include "catalog/pg_shadow.h"
30 #include "miscadmin.h"
31 #include "nodes/makefuncs.h"
32 #include "storage/backendid.h"
33 #include "utils/builtins.h"
34 #include "utils/fmgroids.h"
35 #include "utils/guc.h"
36 #include "utils/lsyscache.h"
37 #include "utils/syscache.h"
41 * The namespace search path is a possibly-empty list of namespace OIDs.
42 * In addition to the explicit list, the TEMP table namespace is always
43 * implicitly searched first (if it's been initialized). Also, the system
44 * catalog namespace is always searched. If the system namespace is
45 * explicitly present in the path then it will be searched in the specified
46 * order; otherwise it will be searched after TEMP tables and *before* the
47 * explicit list. (It might seem that the system namespace should be
48 * implicitly last, but this behavior appears to be required by SQL99.
49 * Also, this provides a way to search the system namespace first without
50 * thereby making it the default creation target namespace.)
52 * The default creation target namespace is kept equal to the first element
53 * of the explicit list, or is the system namespace if the list is empty.
55 * In bootstrap mode or a standalone backend, the default search path is
56 * empty, so that the system namespace is the only one searched or inserted
57 * into. In multiuser mode, the default search path contains the PG_PUBLIC
58 * namespace, preceded by the user's own namespace if one exists.
61 static List *namespaceSearchPath = NIL;
63 /* this flag must be updated correctly when namespaceSearchPath is changed */
64 static bool pathContainsSystemNamespace = false;
66 /* default place to create stuff */
67 static Oid defaultCreationNamespace = PG_CATALOG_NAMESPACE;
70 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
71 * in a particular backend session (this happens when a CREATE TEMP TABLE
72 * command is first executed). Thereafter it's the OID of the temp namespace.
74 static Oid myTempNamespace = InvalidOid;
77 * This is the text equivalent of the search path --- it's the value
78 * of the GUC variable 'search_path'.
80 char *namespace_search_path = NULL;
84 * Deletion ordering constraint item.
86 typedef struct DelConstraint
88 Oid referencer; /* table to delete first */
89 Oid referencee; /* table to delete second */
90 int pred; /* workspace for TopoSortRels */
91 struct DelConstraint *link; /* workspace for TopoSortRels */
96 static Oid GetTempTableNamespace(void);
97 static void RemoveTempRelations(Oid tempNamespaceId);
98 static List *FindTempRelations(Oid tempNamespaceId);
99 static List *FindDeletionConstraints(List *relOids);
100 static List *TopoSortRels(List *relOids, List *constraintList);
101 static void RemoveTempRelationsCallback(void);
106 * Given a RangeVar describing an existing relation,
107 * select the proper namespace and look up the relation OID.
109 * If the relation is not found, return InvalidOid if failOK = true,
110 * otherwise raise an error.
113 RangeVarGetRelid(const RangeVar *relation, bool failOK)
119 * We check the catalog name and then ignore it.
121 if (relation->catalogname)
123 if (strcmp(relation->catalogname, DatabaseName) != 0)
124 elog(ERROR, "Cross-database references are not implemented");
127 if (relation->schemaname)
129 /* use exact schema given */
130 namespaceId = GetSysCacheOid(NAMESPACENAME,
131 CStringGetDatum(relation->schemaname),
133 if (!OidIsValid(namespaceId))
134 elog(ERROR, "Namespace \"%s\" does not exist",
135 relation->schemaname);
136 relId = get_relname_relid(relation->relname, namespaceId);
140 /* search the namespace path */
141 relId = RelnameGetRelid(relation->relname);
144 if (!OidIsValid(relId) && !failOK)
146 if (relation->schemaname)
147 elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
148 relation->schemaname, relation->relname);
150 elog(ERROR, "Relation \"%s\" does not exist",
157 * RangeVarGetCreationNamespace
158 * Given a RangeVar describing a to-be-created relation,
159 * choose which namespace to create it in.
161 * Note: calling this may result in a CommandCounterIncrement operation.
162 * That will happen on the first request for a temp table in any particular
163 * backend run; we will need to either create or clean out the temp schema.
166 RangeVarGetCreationNamespace(const RangeVar *newRelation)
171 * We check the catalog name and then ignore it.
173 if (newRelation->catalogname)
175 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
176 elog(ERROR, "Cross-database references are not implemented");
179 if (newRelation->istemp)
181 /* TEMP tables are created in our backend-local temp namespace */
182 if (newRelation->schemaname)
183 elog(ERROR, "TEMP tables may not specify a namespace");
184 /* Initialize temp namespace if first time through */
185 if (!OidIsValid(myTempNamespace))
186 myTempNamespace = GetTempTableNamespace();
187 return myTempNamespace;
190 if (newRelation->schemaname)
192 /* use exact schema given */
193 namespaceId = GetSysCacheOid(NAMESPACENAME,
194 CStringGetDatum(newRelation->schemaname),
196 if (!OidIsValid(namespaceId))
197 elog(ERROR, "Namespace \"%s\" does not exist",
198 newRelation->schemaname);
202 /* use the default creation namespace */
203 namespaceId = defaultCreationNamespace;
211 * Try to resolve an unqualified relation name.
212 * Returns OID if relation found in search path, else InvalidOid.
215 RelnameGetRelid(const char *relname)
221 * If a TEMP-table namespace has been set up, it is implicitly first
222 * in the search path.
224 if (OidIsValid(myTempNamespace))
226 relid = get_relname_relid(relname, myTempNamespace);
227 if (OidIsValid(relid))
232 * If system namespace is not in path, implicitly search it before path
234 if (!pathContainsSystemNamespace)
236 relid = get_relname_relid(relname, PG_CATALOG_NAMESPACE);
237 if (OidIsValid(relid))
242 * Else search the path
244 foreach(lptr, namespaceSearchPath)
246 Oid namespaceId = (Oid) lfirsti(lptr);
248 relid = get_relname_relid(relname, namespaceId);
249 if (OidIsValid(relid))
253 /* Not found in path */
259 * Try to resolve an unqualified datatype name.
260 * Returns OID if type found in search path, else InvalidOid.
262 * This is essentially the same as RelnameGetRelid, but we never search
263 * the TEMP table namespace --- there is no reason to refer to the types
264 * of temp tables, AFAICS.
267 TypenameGetTypid(const char *typname)
273 * If system namespace is not in path, implicitly search it before path
275 if (!pathContainsSystemNamespace)
277 typid = GetSysCacheOid(TYPENAMENSP,
278 PointerGetDatum(typname),
279 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
281 if (OidIsValid(typid))
286 * Else search the path
288 foreach(lptr, namespaceSearchPath)
290 Oid namespaceId = (Oid) lfirsti(lptr);
292 typid = GetSysCacheOid(TYPENAMENSP,
293 PointerGetDatum(typname),
294 ObjectIdGetDatum(namespaceId),
296 if (OidIsValid(typid))
300 /* Not found in path */
305 * QualifiedNameGetCreationNamespace
306 * Given a possibly-qualified name for an object (in List-of-Values
307 * format), determine what namespace the object should be created in.
308 * Also extract and return the object name (last component of list).
310 * This is *not* used for tables. Hence, the TEMP table namespace is
311 * never selected as the creation target.
314 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
317 char *schemaname = NULL;
318 char *objname = NULL;
321 /* deconstruct the name list */
322 switch (length(names))
325 objname = strVal(lfirst(names));
328 schemaname = strVal(lfirst(names));
329 objname = strVal(lsecond(names));
332 catalogname = strVal(lfirst(names));
333 schemaname = strVal(lsecond(names));
334 objname = strVal(lfirst(lnext(lnext(names))));
336 * We check the catalog name and then ignore it.
338 if (strcmp(catalogname, DatabaseName) != 0)
339 elog(ERROR, "Cross-database references are not implemented");
342 elog(ERROR, "Improper qualified name (too many dotted names)");
348 /* use exact schema given */
349 namespaceId = GetSysCacheOid(NAMESPACENAME,
350 CStringGetDatum(schemaname),
352 if (!OidIsValid(namespaceId))
353 elog(ERROR, "Namespace \"%s\" does not exist",
358 /* use the default creation namespace */
359 namespaceId = defaultCreationNamespace;
362 *objname_p = objname;
367 * makeRangeVarFromNameList
368 * Utility routine to convert a qualified-name list into RangeVar form.
371 makeRangeVarFromNameList(List *names)
373 RangeVar *rel = makeRangeVar(NULL, NULL);
375 switch (length(names))
378 rel->relname = strVal(lfirst(names));
381 rel->schemaname = strVal(lfirst(names));
382 rel->relname = strVal(lsecond(names));
385 rel->catalogname = strVal(lfirst(names));
386 rel->schemaname = strVal(lsecond(names));
387 rel->relname = strVal(lfirst(lnext(lnext(names))));
390 elog(ERROR, "Improper relation name (too many dotted names)");
398 * isTempNamespace - is the given namespace my temporary-table namespace?
401 isTempNamespace(Oid namespaceId)
403 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
409 * GetTempTableNamespace
410 * Initialize temp table namespace on first use in a particular backend
413 GetTempTableNamespace(void)
415 char namespaceName[NAMEDATALEN];
418 snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
420 namespaceId = GetSysCacheOid(NAMESPACENAME,
421 CStringGetDatum(namespaceName),
423 if (!OidIsValid(namespaceId))
426 * First use of this temp namespace in this database; create it.
427 * The temp namespaces are always owned by the superuser.
429 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
430 /* Advance command counter to make namespace visible */
431 CommandCounterIncrement();
436 * If the namespace already exists, clean it out (in case the
437 * former owner crashed without doing so).
439 RemoveTempRelations(namespaceId);
443 * Register exit callback to clean out temp tables at backend shutdown.
445 on_shmem_exit(RemoveTempRelationsCallback, 0);
451 * Remove all relations in the specified temp namespace.
453 * This is called at backend shutdown (if we made any temp relations).
454 * It is also called when we begin using a pre-existing temp namespace,
455 * in order to clean out any relations that might have been created by
459 RemoveTempRelations(Oid tempNamespaceId)
462 List *constraintList;
465 /* Get a list of relations to delete */
466 tempRelList = FindTempRelations(tempNamespaceId);
468 if (tempRelList == NIL)
469 return; /* nothing to do */
471 /* If more than one, sort them to respect any deletion-order constraints */
472 if (length(tempRelList) > 1)
474 constraintList = FindDeletionConstraints(tempRelList);
475 if (constraintList != NIL)
476 tempRelList = TopoSortRels(tempRelList, constraintList);
479 /* Scan the list and delete all entries */
480 foreach(lptr, tempRelList)
482 Oid reloid = (Oid) lfirsti(lptr);
484 heap_drop_with_catalog(reloid, true);
486 * Advance cmd counter to make catalog changes visible, in case
487 * a later entry depends on this one.
489 CommandCounterIncrement();
494 * Find all relations in the specified temp namespace.
496 * Returns a list of relation OIDs.
499 FindTempRelations(Oid tempNamespaceId)
501 List *tempRelList = NIL;
508 * Scan pg_class to find all the relations in the target namespace.
509 * Ignore indexes, though, on the assumption that they'll go away
510 * when their tables are deleted.
512 ScanKeyEntryInitialize(&key, 0x0,
513 Anum_pg_class_relnamespace,
515 ObjectIdGetDatum(tempNamespaceId));
517 pgclass = heap_openr(RelationRelationName, AccessShareLock);
518 scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
520 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
522 switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
524 case RELKIND_RELATION:
525 case RELKIND_SEQUENCE:
527 tempRelList = lconsi(tuple->t_data->t_oid, tempRelList);
535 heap_close(pgclass, AccessShareLock);
541 * Find deletion-order constraints involving the given relation OIDs.
543 * Returns a list of DelConstraint objects.
546 FindDeletionConstraints(List *relOids)
548 List *constraintList = NIL;
549 Relation inheritsrel;
554 * Scan pg_inherits to find parents and children that are in the list.
556 inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
557 scan = heap_beginscan(inheritsrel, 0, SnapshotNow, 0, NULL);
559 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
561 Oid inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
562 Oid inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
564 if (intMember(inhrelid, relOids) && intMember(inhparent, relOids))
568 item = (DelConstraint *) palloc(sizeof(DelConstraint));
569 item->referencer = inhrelid;
570 item->referencee = inhparent;
571 constraintList = lcons(item, constraintList);
576 heap_close(inheritsrel, AccessShareLock);
578 return constraintList;
582 * TopoSortRels -- topological sort of a list of rels to delete
584 * This is a lot simpler and slower than, for example, the topological sort
585 * algorithm shown in Knuth's Volume 1. However, we are not likely to be
586 * working with more than a few constraints, so the apparent slowness of the
587 * algorithm won't really matter.
590 TopoSortRels(List *relOids, List *constraintList)
592 int queue_size = length(relOids);
594 int *beforeConstraints;
595 DelConstraint **afterConstraints;
596 List *resultList = NIL;
603 /* Allocate workspace */
604 rels = (Oid *) palloc(queue_size * sizeof(Oid));
605 beforeConstraints = (int *) palloc(queue_size * sizeof(int));
606 afterConstraints = (DelConstraint **)
607 palloc(queue_size * sizeof(DelConstraint*));
609 /* Build an array of the target relation OIDs */
611 foreach(lptr, relOids)
613 rels[i++] = (Oid) lfirsti(lptr);
617 * Scan the constraints, and for each rel in the array, generate a
618 * count of the number of constraints that say it must be before
619 * something else, plus a list of the constraints that say it must be
620 * after something else. The count for the j'th rel is stored in
621 * beforeConstraints[j], and the head of its list in
622 * afterConstraints[j]. Each constraint stores its list link in
623 * its link field (note any constraint will be in just one list).
624 * The array index for the before-rel of each constraint is
625 * remembered in the constraint's pred field.
627 MemSet(beforeConstraints, 0, queue_size * sizeof(int));
628 MemSet(afterConstraints, 0, queue_size * sizeof(DelConstraint*));
629 foreach(lptr, constraintList)
631 DelConstraint *constraint = (DelConstraint *) lfirst(lptr);
634 /* Find the referencer rel in the array */
635 rel = constraint->referencer;
636 for (j = queue_size; --j >= 0;)
641 Assert(j >= 0); /* should have found a match */
642 /* Find the referencee rel in the array */
643 rel = constraint->referencee;
644 for (k = queue_size; --k >= 0;)
649 Assert(k >= 0); /* should have found a match */
650 beforeConstraints[j]++; /* referencer must come before */
651 /* add this constraint to list of after-constraints for referencee */
652 constraint->pred = j;
653 constraint->link = afterConstraints[k];
654 afterConstraints[k] = constraint;
656 /*--------------------
657 * Now scan the rels array backwards. At each step, output the
658 * last rel that has no remaining before-constraints, and decrease
659 * the beforeConstraints count of each of the rels it was constrained
660 * against. (This is the right order since we are building the result
661 * list back-to-front.)
662 * i = counter for number of rels left to output
663 * j = search index for rels[]
664 * dc = temp for scanning constraint list for rel j
665 * last = last valid index in rels (avoid redundant searches)
666 *--------------------
668 last = queue_size - 1;
669 for (i = queue_size; --i >= 0;)
673 /* Find next candidate to output */
674 while (rels[last] == InvalidOid)
676 for (j = last; j >= 0; j--)
678 if (rels[j] != InvalidOid && beforeConstraints[j] == 0)
681 /* If no available candidate, topological sort fails */
683 elog(ERROR, "TopoSortRels: failed to find a workable deletion ordering");
684 /* Output candidate, and mark it done by zeroing rels[] entry */
685 resultList = lconsi(rels[j], resultList);
686 rels[j] = InvalidOid;
687 /* Update beforeConstraints counts of its predecessors */
688 for (dc = afterConstraints[j]; dc; dc = dc->link)
689 beforeConstraints[dc->pred]--;
697 * Callback to remove temp relations at backend exit.
700 RemoveTempRelationsCallback(void)
702 if (OidIsValid(myTempNamespace)) /* should always be true */
704 /* Need to ensure we have a usable transaction. */
705 AbortOutOfAnyTransaction();
706 StartTransactionCommand();
708 RemoveTempRelations(myTempNamespace);
710 CommitTransactionCommand();
715 * Routines for handling the GUC variable 'search_path'.
718 /* parse_hook: is proposed value valid? */
720 check_search_path(const char *proposed)
726 /* Need a modifiable copy of string */
727 rawname = pstrdup(proposed);
729 /* Parse string into list of identifiers */
730 if (!SplitIdentifierString(rawname, ',', &namelist))
732 /* syntax error in name list */
739 * If we aren't inside a transaction, we cannot do database access so
740 * cannot verify the individual names. Must accept the list on faith.
741 * (This case can happen, for example, when the postmaster reads a
742 * search_path setting from postgresql.conf.)
744 if (!IsTransactionState())
752 * Verify that all the names are either valid namespace names or "$user".
753 * (We do not require $user to correspond to a valid namespace; should we?)
757 char *curname = (char *) lfirst(l);
759 if (strcmp(curname, "$user") == 0)
761 if (!SearchSysCacheExists(NAMESPACENAME,
762 CStringGetDatum(curname),
777 /* assign_hook: do extra actions needed when assigning to search_path */
779 assign_search_path(const char *newval)
786 MemoryContext oldcxt;
789 * If we aren't inside a transaction, we cannot do database access so
790 * cannot look up the names. In this case, do nothing; the internal
791 * search path will be fixed later by InitializeSearchPath. (We assume
792 * this situation can only happen in the postmaster or early in backend
795 if (!IsTransactionState())
798 /* Need a modifiable copy of string */
799 rawname = pstrdup(newval);
801 /* Parse string into list of identifiers */
802 if (!SplitIdentifierString(rawname, ',', &namelist))
804 /* syntax error in name list */
805 /* this should not happen if GUC checked check_search_path */
806 elog(ERROR, "assign_search_path: invalid list syntax");
810 * Convert the list of names to a list of OIDs. If any names are not
811 * recognizable, just leave them out of the list. (This is our only
812 * reasonable recourse when the already-accepted default is bogus.)
817 char *curname = (char *) lfirst(l);
820 if (strcmp(curname, "$user") == 0)
822 /* $user --- substitute namespace matching user name, if any */
825 tuple = SearchSysCache(SHADOWSYSID,
826 ObjectIdGetDatum(GetSessionUserId()),
828 if (HeapTupleIsValid(tuple))
832 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
833 namespaceId = GetSysCacheOid(NAMESPACENAME,
834 CStringGetDatum(uname),
836 if (OidIsValid(namespaceId))
837 oidlist = lappendi(oidlist, namespaceId);
838 ReleaseSysCache(tuple);
843 /* normal namespace reference */
844 namespaceId = GetSysCacheOid(NAMESPACENAME,
845 CStringGetDatum(curname),
847 if (OidIsValid(namespaceId))
848 oidlist = lappendi(oidlist, namespaceId);
853 * Now that we've successfully built the new list of namespace OIDs,
854 * save it in permanent storage.
856 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
857 newpath = listCopy(oidlist);
858 MemoryContextSwitchTo(oldcxt);
860 /* Now safe to assign to state variable. */
861 freeList(namespaceSearchPath);
862 namespaceSearchPath = newpath;
865 * Update info derived from search path.
867 pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE,
868 namespaceSearchPath);
870 if (namespaceSearchPath == NIL)
871 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
873 defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath);
882 * InitializeSearchPath: initialize module during InitPostgres.
884 * This is called after we are up enough to be able to do catalog lookups.
887 InitializeSearchPath(void)
890 * In normal multi-user mode, we want the default search path to be
891 * '$user,public' (or as much of that as exists, anyway; see the
892 * error handling in assign_search_path); which is what guc.c has as
893 * the wired-in default value. But in bootstrap or standalone-backend
894 * mode, the default search path must be empty so that initdb correctly
895 * creates everything in PG_CATALOG_NAMESPACE. Accordingly, adjust the
896 * default setting if we are not running under postmaster. (If a
897 * non-default setting has been supplied, this will not overwrite it.)
899 if (!IsUnderPostmaster)
901 SetConfigOption("search_path", "",
902 PGC_POSTMASTER, PGC_S_DEFAULT);
905 * If a search path setting was provided before we were able to execute
906 * lookups, establish the internal search path now.
908 if (namespace_search_path && *namespace_search_path &&
909 namespaceSearchPath == NIL)
910 assign_search_path(namespace_search_path);