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-2007, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
16 * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.93 2007/03/23 19:53:51 tgl Exp $
18 *-------------------------------------------------------------------------
22 #include "access/xact.h"
23 #include "catalog/dependency.h"
24 #include "catalog/namespace.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_conversion.h"
27 #include "catalog/pg_namespace.h"
28 #include "catalog/pg_opclass.h"
29 #include "catalog/pg_operator.h"
30 #include "catalog/pg_opfamily.h"
31 #include "catalog/pg_proc.h"
32 #include "catalog/pg_type.h"
33 #include "commands/dbcommands.h"
34 #include "miscadmin.h"
35 #include "nodes/makefuncs.h"
36 #include "storage/backendid.h"
37 #include "storage/ipc.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/guc.h"
41 #include "utils/inval.h"
42 #include "utils/lsyscache.h"
43 #include "utils/memutils.h"
44 #include "utils/syscache.h"
48 * The namespace search path is a possibly-empty list of namespace OIDs.
49 * In addition to the explicit list, implicitly-searched namespaces
52 * 1. If a TEMP table namespace has been initialized in this session, it
53 * is implicitly searched first. (The only time this doesn't happen is
54 * when we are obeying an override search path spec that says not to use the
55 * temp namespace, or the temp namespace is included in the explicit list.)
57 * 2. The system catalog namespace is always searched. If the system
58 * namespace is present in the explicit path then it will be searched in
59 * the specified order; otherwise it will be searched after TEMP tables and
60 * *before* the explicit list. (It might seem that the system namespace
61 * should be implicitly last, but this behavior appears to be required by
62 * SQL99. Also, this provides a way to search the system namespace first
63 * without thereby making it the default creation target namespace.)
65 * The default creation target namespace is always the first element of the
66 * explicit list. If the explicit list is empty, there is no default target.
68 * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
69 * the system namespace is the only one searched or inserted into.
70 * initdb is also careful to set search_path to 'pg_catalog' for its
71 * post-bootstrap standalone backend runs. Otherwise the default search
72 * path is determined by GUC. The factory default path contains the PUBLIC
73 * namespace (if it exists), preceded by the user's personal namespace
76 * We support a stack of "override" search path settings for use within
77 * specific sections of backend code. namespace_search_path is ignored
78 * whenever the override stack is nonempty. activeSearchPath is always
79 * the actually active path; it points either to the search list of the
80 * topmost stack entry, or to baseSearchPath which is the list derived
81 * from namespace_search_path.
83 * If baseSearchPathValid is false, then baseSearchPath (and other
84 * derived variables) need to be recomputed from namespace_search_path.
85 * We mark it invalid upon an assignment to namespace_search_path or receipt
86 * of a syscache invalidation event for pg_namespace. The recomputation
87 * is done during the next non-overridden lookup attempt. Note that an
88 * override spec is never subject to recomputation.
90 * Any namespaces mentioned in namespace_search_path that are not readable
91 * by the current user ID are simply left out of baseSearchPath; so
92 * we have to be willing to recompute the path when current userid changes.
93 * namespaceUser is the userid the path has been computed for.
95 * Note: all data pointed to by these List variables is in TopMemoryContext.
98 /* These variables define the actually active state: */
100 static List *activeSearchPath = NIL;
102 /* default place to create stuff; if InvalidOid, no default */
103 static Oid activeCreationNamespace = InvalidOid;
105 /* These variables are the values last derived from namespace_search_path: */
107 static List *baseSearchPath = NIL;
109 static Oid baseCreationNamespace = InvalidOid;
111 static Oid namespaceUser = InvalidOid;
113 /* The above three values are valid only if baseSearchPathValid */
114 static bool baseSearchPathValid = true;
116 /* Override requests are remembered in a stack of OverrideStackEntry structs */
120 List *searchPath; /* the desired search path */
121 Oid creationNamespace; /* the desired creation namespace */
122 int nestLevel; /* subtransaction nesting level */
123 } OverrideStackEntry;
125 static List *overrideStack = NIL;
128 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
129 * in a particular backend session (this happens when a CREATE TEMP TABLE
130 * command is first executed). Thereafter it's the OID of the temp namespace.
132 * myTempNamespaceSubID shows whether we've created the TEMP namespace in the
133 * current subtransaction. The flag propagates up the subtransaction tree,
134 * so the main transaction will correctly recognize the flag if all
135 * intermediate subtransactions commit. When it is InvalidSubTransactionId,
136 * we either haven't made the TEMP namespace yet, or have successfully
137 * committed its creation, depending on whether myTempNamespace is valid.
139 static Oid myTempNamespace = InvalidOid;
141 static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
144 * This is the user's textual search path specification --- it's the value
145 * of the GUC variable 'search_path'.
147 char *namespace_search_path = NULL;
150 /* Local functions */
151 static void recomputeNamespacePath(void);
152 static void InitTempTableNamespace(void);
153 static void RemoveTempRelations(Oid tempNamespaceId);
154 static void RemoveTempRelationsCallback(int code, Datum arg);
155 static void NamespaceCallback(Datum arg, Oid relid);
157 /* These don't really need to appear in any header file */
158 Datum pg_table_is_visible(PG_FUNCTION_ARGS);
159 Datum pg_type_is_visible(PG_FUNCTION_ARGS);
160 Datum pg_function_is_visible(PG_FUNCTION_ARGS);
161 Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
162 Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
163 Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
164 Datum pg_my_temp_schema(PG_FUNCTION_ARGS);
165 Datum pg_is_other_temp_schema(PG_FUNCTION_ARGS);
170 * Given a RangeVar describing an existing relation,
171 * select the proper namespace and look up the relation OID.
173 * If the relation is not found, return InvalidOid if failOK = true,
174 * otherwise raise an error.
177 RangeVarGetRelid(const RangeVar *relation, bool failOK)
183 * We check the catalog name and then ignore it.
185 if (relation->catalogname)
187 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
189 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
190 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
191 relation->catalogname, relation->schemaname,
192 relation->relname)));
195 if (relation->schemaname)
197 /* use exact schema given */
198 namespaceId = LookupExplicitNamespace(relation->schemaname);
199 relId = get_relname_relid(relation->relname, namespaceId);
203 /* search the namespace path */
204 relId = RelnameGetRelid(relation->relname);
207 if (!OidIsValid(relId) && !failOK)
209 if (relation->schemaname)
211 (errcode(ERRCODE_UNDEFINED_TABLE),
212 errmsg("relation \"%s.%s\" does not exist",
213 relation->schemaname, relation->relname)));
216 (errcode(ERRCODE_UNDEFINED_TABLE),
217 errmsg("relation \"%s\" does not exist",
218 relation->relname)));
224 * RangeVarGetCreationNamespace
225 * Given a RangeVar describing a to-be-created relation,
226 * choose which namespace to create it in.
228 * Note: calling this may result in a CommandCounterIncrement operation.
229 * That will happen on the first request for a temp table in any particular
230 * backend run; we will need to either create or clean out the temp schema.
233 RangeVarGetCreationNamespace(const RangeVar *newRelation)
238 * We check the catalog name and then ignore it.
240 if (newRelation->catalogname)
242 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
244 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
245 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
246 newRelation->catalogname, newRelation->schemaname,
247 newRelation->relname)));
250 if (newRelation->istemp)
252 /* TEMP tables are created in our backend-local temp namespace */
253 if (newRelation->schemaname)
255 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
256 errmsg("temporary tables cannot specify a schema name")));
257 /* Initialize temp namespace if first time through */
258 if (!OidIsValid(myTempNamespace))
259 InitTempTableNamespace();
260 return myTempNamespace;
263 if (newRelation->schemaname)
265 /* use exact schema given */
266 namespaceId = GetSysCacheOid(NAMESPACENAME,
267 CStringGetDatum(newRelation->schemaname),
269 if (!OidIsValid(namespaceId))
271 (errcode(ERRCODE_UNDEFINED_SCHEMA),
272 errmsg("schema \"%s\" does not exist",
273 newRelation->schemaname)));
274 /* we do not check for USAGE rights here! */
278 /* use the default creation namespace */
279 recomputeNamespacePath();
280 namespaceId = activeCreationNamespace;
281 if (!OidIsValid(namespaceId))
283 (errcode(ERRCODE_UNDEFINED_SCHEMA),
284 errmsg("no schema has been selected to create in")));
287 /* Note: callers will check for CREATE rights when appropriate */
294 * Try to resolve an unqualified relation name.
295 * Returns OID if relation found in search path, else InvalidOid.
298 RelnameGetRelid(const char *relname)
303 recomputeNamespacePath();
305 foreach(l, activeSearchPath)
307 Oid namespaceId = lfirst_oid(l);
309 relid = get_relname_relid(relname, namespaceId);
310 if (OidIsValid(relid))
314 /* Not found in path */
321 * Determine whether a relation (identified by OID) is visible in the
322 * current search path. Visible means "would be found by searching
323 * for the unqualified relation name".
326 RelationIsVisible(Oid relid)
329 Form_pg_class relform;
333 reltup = SearchSysCache(RELOID,
334 ObjectIdGetDatum(relid),
336 if (!HeapTupleIsValid(reltup))
337 elog(ERROR, "cache lookup failed for relation %u", relid);
338 relform = (Form_pg_class) GETSTRUCT(reltup);
340 recomputeNamespacePath();
343 * Quick check: if it ain't in the path at all, it ain't visible. Items in
344 * the system namespace are surely in the path and so we needn't even do
345 * list_member_oid() for them.
347 relnamespace = relform->relnamespace;
348 if (relnamespace != PG_CATALOG_NAMESPACE &&
349 !list_member_oid(activeSearchPath, relnamespace))
354 * If it is in the path, it might still not be visible; it could be
355 * hidden by another relation of the same name earlier in the path. So
356 * we must do a slow check for conflicting relations.
358 char *relname = NameStr(relform->relname);
362 foreach(l, activeSearchPath)
364 Oid namespaceId = lfirst_oid(l);
366 if (namespaceId == relnamespace)
368 /* Found it first in path */
372 if (OidIsValid(get_relname_relid(relname, namespaceId)))
374 /* Found something else first in path */
380 ReleaseSysCache(reltup);
388 * Try to resolve an unqualified datatype name.
389 * Returns OID if type found in search path, else InvalidOid.
391 * This is essentially the same as RelnameGetRelid.
394 TypenameGetTypid(const char *typname)
399 recomputeNamespacePath();
401 foreach(l, activeSearchPath)
403 Oid namespaceId = lfirst_oid(l);
405 typid = GetSysCacheOid(TYPENAMENSP,
406 PointerGetDatum(typname),
407 ObjectIdGetDatum(namespaceId),
409 if (OidIsValid(typid))
413 /* Not found in path */
419 * Determine whether a type (identified by OID) is visible in the
420 * current search path. Visible means "would be found by searching
421 * for the unqualified type name".
424 TypeIsVisible(Oid typid)
427 Form_pg_type typform;
431 typtup = SearchSysCache(TYPEOID,
432 ObjectIdGetDatum(typid),
434 if (!HeapTupleIsValid(typtup))
435 elog(ERROR, "cache lookup failed for type %u", typid);
436 typform = (Form_pg_type) GETSTRUCT(typtup);
438 recomputeNamespacePath();
441 * Quick check: if it ain't in the path at all, it ain't visible. Items in
442 * the system namespace are surely in the path and so we needn't even do
443 * list_member_oid() for them.
445 typnamespace = typform->typnamespace;
446 if (typnamespace != PG_CATALOG_NAMESPACE &&
447 !list_member_oid(activeSearchPath, typnamespace))
452 * If it is in the path, it might still not be visible; it could be
453 * hidden by another type of the same name earlier in the path. So we
454 * must do a slow check for conflicting types.
456 char *typname = NameStr(typform->typname);
460 foreach(l, activeSearchPath)
462 Oid namespaceId = lfirst_oid(l);
464 if (namespaceId == typnamespace)
466 /* Found it first in path */
470 if (SearchSysCacheExists(TYPENAMENSP,
471 PointerGetDatum(typname),
472 ObjectIdGetDatum(namespaceId),
475 /* Found something else first in path */
481 ReleaseSysCache(typtup);
488 * FuncnameGetCandidates
489 * Given a possibly-qualified function name and argument count,
490 * retrieve a list of the possible matches.
492 * If nargs is -1, we return all functions matching the given name,
493 * regardless of argument count.
495 * We search a single namespace if the function name is qualified, else
496 * all namespaces in the search path. The return list will never contain
497 * multiple entries with identical argument lists --- in the multiple-
498 * namespace case, we arrange for entries in earlier namespaces to mask
499 * identical entries in later namespaces.
502 FuncnameGetCandidates(List *names, int nargs)
504 FuncCandidateList resultList = NULL;
511 /* deconstruct the name list */
512 DeconstructQualifiedName(names, &schemaname, &funcname);
516 /* use exact schema given */
517 namespaceId = LookupExplicitNamespace(schemaname);
521 /* flag to indicate we need namespace search */
522 namespaceId = InvalidOid;
523 recomputeNamespacePath();
526 /* Search syscache by name only */
527 catlist = SearchSysCacheList(PROCNAMEARGSNSP, 1,
528 CStringGetDatum(funcname),
531 for (i = 0; i < catlist->n_members; i++)
533 HeapTuple proctup = &catlist->members[i]->tuple;
534 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
535 int pronargs = procform->pronargs;
537 FuncCandidateList newResult;
539 /* Ignore if it doesn't match requested argument count */
540 if (nargs >= 0 && pronargs != nargs)
543 if (OidIsValid(namespaceId))
545 /* Consider only procs in specified namespace */
546 if (procform->pronamespace != namespaceId)
548 /* No need to check args, they must all be different */
552 /* Consider only procs that are in the search path */
555 foreach(nsp, activeSearchPath)
557 if (procform->pronamespace == lfirst_oid(nsp))
562 continue; /* proc is not in search path */
565 * Okay, it's in the search path, but does it have the same
566 * arguments as something we already accepted? If so, keep only
567 * the one that appears earlier in the search path.
569 * If we have an ordered list from SearchSysCacheList (the normal
570 * case), then any conflicting proc must immediately adjoin this
571 * one in the list, so we only need to look at the newest result
572 * item. If we have an unordered list, we have to scan the whole
577 FuncCandidateList prevResult;
579 if (catlist->ordered)
581 if (pronargs == resultList->nargs &&
582 memcmp(procform->proargtypes.values,
584 pronargs * sizeof(Oid)) == 0)
585 prevResult = resultList;
591 for (prevResult = resultList;
593 prevResult = prevResult->next)
595 if (pronargs == prevResult->nargs &&
596 memcmp(procform->proargtypes.values,
598 pronargs * sizeof(Oid)) == 0)
604 /* We have a match with a previous result */
605 Assert(pathpos != prevResult->pathpos);
606 if (pathpos > prevResult->pathpos)
607 continue; /* keep previous result */
608 /* replace previous result */
609 prevResult->pathpos = pathpos;
610 prevResult->oid = HeapTupleGetOid(proctup);
611 continue; /* args are same, of course */
617 * Okay to add it to result list
619 newResult = (FuncCandidateList)
620 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
621 + pronargs * sizeof(Oid));
622 newResult->pathpos = pathpos;
623 newResult->oid = HeapTupleGetOid(proctup);
624 newResult->nargs = pronargs;
625 memcpy(newResult->args, procform->proargtypes.values,
626 pronargs * sizeof(Oid));
628 newResult->next = resultList;
629 resultList = newResult;
632 ReleaseSysCacheList(catlist);
639 * Determine whether a function (identified by OID) is visible in the
640 * current search path. Visible means "would be found by searching
641 * for the unqualified function name with exact argument matches".
644 FunctionIsVisible(Oid funcid)
647 Form_pg_proc procform;
651 proctup = SearchSysCache(PROCOID,
652 ObjectIdGetDatum(funcid),
654 if (!HeapTupleIsValid(proctup))
655 elog(ERROR, "cache lookup failed for function %u", funcid);
656 procform = (Form_pg_proc) GETSTRUCT(proctup);
658 recomputeNamespacePath();
661 * Quick check: if it ain't in the path at all, it ain't visible. Items in
662 * the system namespace are surely in the path and so we needn't even do
663 * list_member_oid() for them.
665 pronamespace = procform->pronamespace;
666 if (pronamespace != PG_CATALOG_NAMESPACE &&
667 !list_member_oid(activeSearchPath, pronamespace))
672 * If it is in the path, it might still not be visible; it could be
673 * hidden by another proc of the same name and arguments earlier in
674 * the path. So we must do a slow check to see if this is the same
675 * proc that would be found by FuncnameGetCandidates.
677 char *proname = NameStr(procform->proname);
678 int nargs = procform->pronargs;
679 FuncCandidateList clist;
683 clist = FuncnameGetCandidates(list_make1(makeString(proname)), nargs);
685 for (; clist; clist = clist->next)
687 if (memcmp(clist->args, procform->proargtypes.values,
688 nargs * sizeof(Oid)) == 0)
690 /* Found the expected entry; is it the right proc? */
691 visible = (clist->oid == funcid);
697 ReleaseSysCache(proctup);
705 * Given a possibly-qualified operator name and exact input datatypes,
706 * look up the operator. Returns InvalidOid if not found.
708 * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
711 * If the operator name is not schema-qualified, it is sought in the current
712 * namespace search path.
715 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
722 /* deconstruct the name list */
723 DeconstructQualifiedName(names, &schemaname, &opername);
727 /* search only in exact schema given */
731 namespaceId = LookupExplicitNamespace(schemaname);
732 opertup = SearchSysCache(OPERNAMENSP,
733 CStringGetDatum(opername),
734 ObjectIdGetDatum(oprleft),
735 ObjectIdGetDatum(oprright),
736 ObjectIdGetDatum(namespaceId));
737 if (HeapTupleIsValid(opertup))
739 Oid result = HeapTupleGetOid(opertup);
741 ReleaseSysCache(opertup);
747 /* Search syscache by name and argument types */
748 catlist = SearchSysCacheList(OPERNAMENSP, 3,
749 CStringGetDatum(opername),
750 ObjectIdGetDatum(oprleft),
751 ObjectIdGetDatum(oprright),
754 if (catlist->n_members == 0)
756 /* no hope, fall out early */
757 ReleaseSysCacheList(catlist);
762 * We have to find the list member that is first in the search path, if
763 * there's more than one. This doubly-nested loop looks ugly, but in
764 * practice there should usually be few catlist members.
766 recomputeNamespacePath();
768 foreach(l, activeSearchPath)
770 Oid namespaceId = lfirst_oid(l);
773 for (i = 0; i < catlist->n_members; i++)
775 HeapTuple opertup = &catlist->members[i]->tuple;
776 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
778 if (operform->oprnamespace == namespaceId)
780 Oid result = HeapTupleGetOid(opertup);
782 ReleaseSysCacheList(catlist);
788 ReleaseSysCacheList(catlist);
793 * OpernameGetCandidates
794 * Given a possibly-qualified operator name and operator kind,
795 * retrieve a list of the possible matches.
797 * If oprkind is '\0', we return all operators matching the given name,
798 * regardless of arguments.
800 * We search a single namespace if the operator name is qualified, else
801 * all namespaces in the search path. The return list will never contain
802 * multiple entries with identical argument lists --- in the multiple-
803 * namespace case, we arrange for entries in earlier namespaces to mask
804 * identical entries in later namespaces.
806 * The returned items always have two args[] entries --- one or the other
807 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
810 OpernameGetCandidates(List *names, char oprkind)
812 FuncCandidateList resultList = NULL;
813 char *resultSpace = NULL;
821 /* deconstruct the name list */
822 DeconstructQualifiedName(names, &schemaname, &opername);
826 /* use exact schema given */
827 namespaceId = LookupExplicitNamespace(schemaname);
831 /* flag to indicate we need namespace search */
832 namespaceId = InvalidOid;
833 recomputeNamespacePath();
836 /* Search syscache by name only */
837 catlist = SearchSysCacheList(OPERNAMENSP, 1,
838 CStringGetDatum(opername),
842 * In typical scenarios, most if not all of the operators found by the
843 * catcache search will end up getting returned; and there can be quite a
844 * few, for common operator names such as '=' or '+'. To reduce the time
845 * spent in palloc, we allocate the result space as an array large enough
846 * to hold all the operators. The original coding of this routine did a
847 * separate palloc for each operator, but profiling revealed that the
848 * pallocs used an unreasonably large fraction of parsing time.
850 #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
852 if (catlist->n_members > 0)
853 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
855 for (i = 0; i < catlist->n_members; i++)
857 HeapTuple opertup = &catlist->members[i]->tuple;
858 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
860 FuncCandidateList newResult;
862 /* Ignore operators of wrong kind, if specific kind requested */
863 if (oprkind && operform->oprkind != oprkind)
866 if (OidIsValid(namespaceId))
868 /* Consider only opers in specified namespace */
869 if (operform->oprnamespace != namespaceId)
871 /* No need to check args, they must all be different */
875 /* Consider only opers that are in the search path */
878 foreach(nsp, activeSearchPath)
880 if (operform->oprnamespace == lfirst_oid(nsp))
885 continue; /* oper is not in search path */
888 * Okay, it's in the search path, but does it have the same
889 * arguments as something we already accepted? If so, keep only
890 * the one that appears earlier in the search path.
892 * If we have an ordered list from SearchSysCacheList (the normal
893 * case), then any conflicting oper must immediately adjoin this
894 * one in the list, so we only need to look at the newest result
895 * item. If we have an unordered list, we have to scan the whole
900 FuncCandidateList prevResult;
902 if (catlist->ordered)
904 if (operform->oprleft == resultList->args[0] &&
905 operform->oprright == resultList->args[1])
906 prevResult = resultList;
912 for (prevResult = resultList;
914 prevResult = prevResult->next)
916 if (operform->oprleft == prevResult->args[0] &&
917 operform->oprright == prevResult->args[1])
923 /* We have a match with a previous result */
924 Assert(pathpos != prevResult->pathpos);
925 if (pathpos > prevResult->pathpos)
926 continue; /* keep previous result */
927 /* replace previous result */
928 prevResult->pathpos = pathpos;
929 prevResult->oid = HeapTupleGetOid(opertup);
930 continue; /* args are same, of course */
936 * Okay to add it to result list
938 newResult = (FuncCandidateList) (resultSpace + nextResult);
939 nextResult += SPACE_PER_OP;
941 newResult->pathpos = pathpos;
942 newResult->oid = HeapTupleGetOid(opertup);
943 newResult->nargs = 2;
944 newResult->args[0] = operform->oprleft;
945 newResult->args[1] = operform->oprright;
946 newResult->next = resultList;
947 resultList = newResult;
950 ReleaseSysCacheList(catlist);
957 * Determine whether an operator (identified by OID) is visible in the
958 * current search path. Visible means "would be found by searching
959 * for the unqualified operator name with exact argument matches".
962 OperatorIsVisible(Oid oprid)
965 Form_pg_operator oprform;
969 oprtup = SearchSysCache(OPEROID,
970 ObjectIdGetDatum(oprid),
972 if (!HeapTupleIsValid(oprtup))
973 elog(ERROR, "cache lookup failed for operator %u", oprid);
974 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
976 recomputeNamespacePath();
979 * Quick check: if it ain't in the path at all, it ain't visible. Items in
980 * the system namespace are surely in the path and so we needn't even do
981 * list_member_oid() for them.
983 oprnamespace = oprform->oprnamespace;
984 if (oprnamespace != PG_CATALOG_NAMESPACE &&
985 !list_member_oid(activeSearchPath, oprnamespace))
990 * If it is in the path, it might still not be visible; it could be
991 * hidden by another operator of the same name and arguments earlier
992 * in the path. So we must do a slow check to see if this is the same
993 * operator that would be found by OpernameGetOprId.
995 char *oprname = NameStr(oprform->oprname);
997 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
998 oprform->oprleft, oprform->oprright)
1002 ReleaseSysCache(oprtup);
1009 * OpclassnameGetOpcid
1010 * Try to resolve an unqualified index opclass name.
1011 * Returns OID if opclass found in search path, else InvalidOid.
1013 * This is essentially the same as TypenameGetTypid, but we have to have
1014 * an extra argument for the index AM OID.
1017 OpclassnameGetOpcid(Oid amid, const char *opcname)
1022 recomputeNamespacePath();
1024 foreach(l, activeSearchPath)
1026 Oid namespaceId = lfirst_oid(l);
1028 opcid = GetSysCacheOid(CLAAMNAMENSP,
1029 ObjectIdGetDatum(amid),
1030 PointerGetDatum(opcname),
1031 ObjectIdGetDatum(namespaceId),
1033 if (OidIsValid(opcid))
1037 /* Not found in path */
1043 * Determine whether an opclass (identified by OID) is visible in the
1044 * current search path. Visible means "would be found by searching
1045 * for the unqualified opclass name".
1048 OpclassIsVisible(Oid opcid)
1051 Form_pg_opclass opcform;
1055 opctup = SearchSysCache(CLAOID,
1056 ObjectIdGetDatum(opcid),
1058 if (!HeapTupleIsValid(opctup))
1059 elog(ERROR, "cache lookup failed for opclass %u", opcid);
1060 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1062 recomputeNamespacePath();
1065 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1066 * the system namespace are surely in the path and so we needn't even do
1067 * list_member_oid() for them.
1069 opcnamespace = opcform->opcnamespace;
1070 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1071 !list_member_oid(activeSearchPath, opcnamespace))
1076 * If it is in the path, it might still not be visible; it could be
1077 * hidden by another opclass of the same name earlier in the path. So
1078 * we must do a slow check to see if this opclass would be found by
1079 * OpclassnameGetOpcid.
1081 char *opcname = NameStr(opcform->opcname);
1083 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
1086 ReleaseSysCache(opctup);
1092 * OpfamilynameGetOpfid
1093 * Try to resolve an unqualified index opfamily name.
1094 * Returns OID if opfamily found in search path, else InvalidOid.
1096 * This is essentially the same as TypenameGetTypid, but we have to have
1097 * an extra argument for the index AM OID.
1100 OpfamilynameGetOpfid(Oid amid, const char *opfname)
1105 recomputeNamespacePath();
1107 foreach(l, activeSearchPath)
1109 Oid namespaceId = lfirst_oid(l);
1111 opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
1112 ObjectIdGetDatum(amid),
1113 PointerGetDatum(opfname),
1114 ObjectIdGetDatum(namespaceId),
1116 if (OidIsValid(opfid))
1120 /* Not found in path */
1126 * Determine whether an opfamily (identified by OID) is visible in the
1127 * current search path. Visible means "would be found by searching
1128 * for the unqualified opfamily name".
1131 OpfamilyIsVisible(Oid opfid)
1134 Form_pg_opfamily opfform;
1138 opftup = SearchSysCache(OPFAMILYOID,
1139 ObjectIdGetDatum(opfid),
1141 if (!HeapTupleIsValid(opftup))
1142 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
1143 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
1145 recomputeNamespacePath();
1148 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1149 * the system namespace are surely in the path and so we needn't even do
1150 * list_member_oid() for them.
1152 opfnamespace = opfform->opfnamespace;
1153 if (opfnamespace != PG_CATALOG_NAMESPACE &&
1154 !list_member_oid(activeSearchPath, opfnamespace))
1159 * If it is in the path, it might still not be visible; it could be
1160 * hidden by another opfamily of the same name earlier in the path. So
1161 * we must do a slow check to see if this opfamily would be found by
1162 * OpfamilynameGetOpfid.
1164 char *opfname = NameStr(opfform->opfname);
1166 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
1169 ReleaseSysCache(opftup);
1175 * ConversionGetConid
1176 * Try to resolve an unqualified conversion name.
1177 * Returns OID if conversion found in search path, else InvalidOid.
1179 * This is essentially the same as RelnameGetRelid.
1182 ConversionGetConid(const char *conname)
1187 recomputeNamespacePath();
1189 foreach(l, activeSearchPath)
1191 Oid namespaceId = lfirst_oid(l);
1193 conid = GetSysCacheOid(CONNAMENSP,
1194 PointerGetDatum(conname),
1195 ObjectIdGetDatum(namespaceId),
1197 if (OidIsValid(conid))
1201 /* Not found in path */
1206 * ConversionIsVisible
1207 * Determine whether a conversion (identified by OID) is visible in the
1208 * current search path. Visible means "would be found by searching
1209 * for the unqualified conversion name".
1212 ConversionIsVisible(Oid conid)
1215 Form_pg_conversion conform;
1219 contup = SearchSysCache(CONVOID,
1220 ObjectIdGetDatum(conid),
1222 if (!HeapTupleIsValid(contup))
1223 elog(ERROR, "cache lookup failed for conversion %u", conid);
1224 conform = (Form_pg_conversion) GETSTRUCT(contup);
1226 recomputeNamespacePath();
1229 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1230 * the system namespace are surely in the path and so we needn't even do
1231 * list_member_oid() for them.
1233 connamespace = conform->connamespace;
1234 if (connamespace != PG_CATALOG_NAMESPACE &&
1235 !list_member_oid(activeSearchPath, connamespace))
1240 * If it is in the path, it might still not be visible; it could be
1241 * hidden by another conversion of the same name earlier in the path.
1242 * So we must do a slow check to see if this conversion would be found
1243 * by ConversionGetConid.
1245 char *conname = NameStr(conform->conname);
1247 visible = (ConversionGetConid(conname) == conid);
1250 ReleaseSysCache(contup);
1256 * DeconstructQualifiedName
1257 * Given a possibly-qualified name expressed as a list of String nodes,
1258 * extract the schema name and object name.
1260 * *nspname_p is set to NULL if there is no explicit schema name.
1263 DeconstructQualifiedName(List *names,
1268 char *schemaname = NULL;
1269 char *objname = NULL;
1271 switch (list_length(names))
1274 objname = strVal(linitial(names));
1277 schemaname = strVal(linitial(names));
1278 objname = strVal(lsecond(names));
1281 catalogname = strVal(linitial(names));
1282 schemaname = strVal(lsecond(names));
1283 objname = strVal(lthird(names));
1286 * We check the catalog name and then ignore it.
1288 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
1290 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1291 errmsg("cross-database references are not implemented: %s",
1292 NameListToString(names))));
1296 (errcode(ERRCODE_SYNTAX_ERROR),
1297 errmsg("improper qualified name (too many dotted names): %s",
1298 NameListToString(names))));
1302 *nspname_p = schemaname;
1303 *objname_p = objname;
1307 * LookupExplicitNamespace
1308 * Process an explicitly-specified schema name: look up the schema
1309 * and verify we have USAGE (lookup) rights in it.
1311 * Returns the namespace OID. Raises ereport if any problem.
1314 LookupExplicitNamespace(const char *nspname)
1317 AclResult aclresult;
1319 namespaceId = GetSysCacheOid(NAMESPACENAME,
1320 CStringGetDatum(nspname),
1322 if (!OidIsValid(namespaceId))
1324 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1325 errmsg("schema \"%s\" does not exist", nspname)));
1327 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
1328 if (aclresult != ACLCHECK_OK)
1329 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1336 * LookupCreationNamespace
1337 * Look up the schema and verify we have CREATE rights on it.
1339 * This is just like LookupExplicitNamespace except for the permission check.
1342 LookupCreationNamespace(const char *nspname)
1345 AclResult aclresult;
1347 namespaceId = GetSysCacheOid(NAMESPACENAME,
1348 CStringGetDatum(nspname),
1350 if (!OidIsValid(namespaceId))
1352 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1353 errmsg("schema \"%s\" does not exist", nspname)));
1355 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
1356 if (aclresult != ACLCHECK_OK)
1357 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1364 * QualifiedNameGetCreationNamespace
1365 * Given a possibly-qualified name for an object (in List-of-Values
1366 * format), determine what namespace the object should be created in.
1367 * Also extract and return the object name (last component of list).
1369 * Note: this does not apply any permissions check. Callers must check
1370 * for CREATE rights on the selected namespace when appropriate.
1372 * This is *not* used for tables. Hence, the TEMP table namespace is
1373 * never selected as the creation target.
1376 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1382 /* deconstruct the name list */
1383 DeconstructQualifiedName(names, &schemaname, &objname);
1387 /* use exact schema given */
1388 namespaceId = GetSysCacheOid(NAMESPACENAME,
1389 CStringGetDatum(schemaname),
1391 if (!OidIsValid(namespaceId))
1393 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1394 errmsg("schema \"%s\" does not exist", schemaname)));
1395 /* we do not check for USAGE rights here! */
1399 /* use the default creation namespace */
1400 recomputeNamespacePath();
1401 namespaceId = activeCreationNamespace;
1402 if (!OidIsValid(namespaceId))
1404 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1405 errmsg("no schema has been selected to create in")));
1408 *objname_p = objname;
1413 * makeRangeVarFromNameList
1414 * Utility routine to convert a qualified-name list into RangeVar form.
1417 makeRangeVarFromNameList(List *names)
1419 RangeVar *rel = makeRangeVar(NULL, NULL);
1421 switch (list_length(names))
1424 rel->relname = strVal(linitial(names));
1427 rel->schemaname = strVal(linitial(names));
1428 rel->relname = strVal(lsecond(names));
1431 rel->catalogname = strVal(linitial(names));
1432 rel->schemaname = strVal(lsecond(names));
1433 rel->relname = strVal(lthird(names));
1437 (errcode(ERRCODE_SYNTAX_ERROR),
1438 errmsg("improper relation name (too many dotted names): %s",
1439 NameListToString(names))));
1448 * Utility routine to convert a qualified-name list into a string.
1450 * This is used primarily to form error messages, and so we do not quote
1451 * the list elements, for the sake of legibility.
1454 NameListToString(List *names)
1456 StringInfoData string;
1459 initStringInfo(&string);
1463 if (l != list_head(names))
1464 appendStringInfoChar(&string, '.');
1465 appendStringInfoString(&string, strVal(lfirst(l)));
1472 * NameListToQuotedString
1473 * Utility routine to convert a qualified-name list into a string.
1475 * Same as above except that names will be double-quoted where necessary,
1476 * so the string could be re-parsed (eg, by textToQualifiedNameList).
1479 NameListToQuotedString(List *names)
1481 StringInfoData string;
1484 initStringInfo(&string);
1488 if (l != list_head(names))
1489 appendStringInfoChar(&string, '.');
1490 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
1497 * isTempNamespace - is the given namespace my temporary-table namespace?
1500 isTempNamespace(Oid namespaceId)
1502 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1508 * isAnyTempNamespace - is the given namespace a temporary-table namespace
1509 * (either my own, or another backend's)?
1512 isAnyTempNamespace(Oid namespaceId)
1517 /* If the namespace name starts with "pg_temp_", say "true" */
1518 nspname = get_namespace_name(namespaceId);
1520 return false; /* no such namespace? */
1521 result = (strncmp(nspname, "pg_temp_", 8) == 0);
1527 * isOtherTempNamespace - is the given namespace some other backend's
1528 * temporary-table namespace?
1531 isOtherTempNamespace(Oid namespaceId)
1533 /* If it's my own temp namespace, say "false" */
1534 if (isTempNamespace(namespaceId))
1536 /* Else, if the namespace name starts with "pg_temp_", say "true" */
1537 return isAnyTempNamespace(namespaceId);
1542 * GetOverrideSearchPath - fetch current search path definition in form
1543 * used by PushOverrideSearchPath.
1545 * The result structure is allocated in the specified memory context
1546 * (which might or might not be equal to CurrentMemoryContext); but any
1547 * junk created by revalidation calculations will be in CurrentMemoryContext.
1549 OverrideSearchPath *
1550 GetOverrideSearchPath(MemoryContext context)
1552 OverrideSearchPath *result;
1554 MemoryContext oldcxt;
1556 recomputeNamespacePath();
1558 oldcxt = MemoryContextSwitchTo(context);
1560 result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
1561 schemas = list_copy(activeSearchPath);
1562 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
1564 if (linitial_oid(schemas) == myTempNamespace)
1565 result->addTemp = true;
1568 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
1569 result->addCatalog = true;
1571 schemas = list_delete_first(schemas);
1573 result->schemas = schemas;
1575 MemoryContextSwitchTo(oldcxt);
1581 * PushOverrideSearchPath - temporarily override the search path
1583 * We allow nested overrides, hence the push/pop terminology. The GUC
1584 * search_path variable is ignored while an override is active.
1587 PushOverrideSearchPath(OverrideSearchPath *newpath)
1589 OverrideStackEntry *entry;
1592 MemoryContext oldcxt;
1595 * Copy the list for safekeeping, and insert implicitly-searched
1596 * namespaces as needed. This code should track recomputeNamespacePath.
1598 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1600 oidlist = list_copy(newpath->schemas);
1603 * Remember the first member of the explicit list.
1606 firstNS = InvalidOid;
1608 firstNS = linitial_oid(oidlist);
1611 * Add any implicitly-searched namespaces to the list. Note these go on
1612 * the front, not the back; also notice that we do not check USAGE
1613 * permissions for these.
1615 if (newpath->addCatalog)
1616 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
1618 if (newpath->addTemp)
1620 Assert(OidIsValid(myTempNamespace));
1621 oidlist = lcons_oid(myTempNamespace, oidlist);
1625 * Build the new stack entry, then insert it at the head of the list.
1627 entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
1628 entry->searchPath = oidlist;
1629 entry->creationNamespace = firstNS;
1630 entry->nestLevel = GetCurrentTransactionNestLevel();
1632 overrideStack = lcons(entry, overrideStack);
1634 /* And make it active. */
1635 activeSearchPath = entry->searchPath;
1636 activeCreationNamespace = entry->creationNamespace;
1638 MemoryContextSwitchTo(oldcxt);
1642 * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
1644 * Any push during a (sub)transaction will be popped automatically at abort.
1645 * But it's caller error if a push isn't popped in normal control flow.
1648 PopOverrideSearchPath(void)
1650 OverrideStackEntry *entry;
1652 /* Sanity checks. */
1653 if (overrideStack == NIL)
1654 elog(ERROR, "bogus PopOverrideSearchPath call");
1655 entry = (OverrideStackEntry *) linitial(overrideStack);
1656 if (entry->nestLevel != GetCurrentTransactionNestLevel())
1657 elog(ERROR, "bogus PopOverrideSearchPath call");
1659 /* Pop the stack and free storage. */
1660 overrideStack = list_delete_first(overrideStack);
1661 list_free(entry->searchPath);
1664 /* Activate the next level down. */
1667 entry = (OverrideStackEntry *) linitial(overrideStack);
1668 activeSearchPath = entry->searchPath;
1669 activeCreationNamespace = entry->creationNamespace;
1673 /* If not baseSearchPathValid, this is useless but harmless */
1674 activeSearchPath = baseSearchPath;
1675 activeCreationNamespace = baseCreationNamespace;
1681 * FindConversionByName - find a conversion by possibly qualified name
1684 FindConversionByName(List *name)
1687 char *conversion_name;
1692 /* deconstruct the name list */
1693 DeconstructQualifiedName(name, &schemaname, &conversion_name);
1697 /* use exact schema given */
1698 namespaceId = LookupExplicitNamespace(schemaname);
1699 return FindConversion(conversion_name, namespaceId);
1703 /* search for it in search path */
1704 recomputeNamespacePath();
1706 foreach(l, activeSearchPath)
1708 namespaceId = lfirst_oid(l);
1709 conoid = FindConversion(conversion_name, namespaceId);
1710 if (OidIsValid(conoid))
1715 /* Not found in path */
1720 * FindDefaultConversionProc - find default encoding conversion proc
1723 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
1728 recomputeNamespacePath();
1730 foreach(l, activeSearchPath)
1732 Oid namespaceId = lfirst_oid(l);
1734 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
1735 if (OidIsValid(proc))
1739 /* Not found in path */
1744 * recomputeNamespacePath - recompute path derived variables if needed.
1747 recomputeNamespacePath(void)
1749 Oid roleid = GetUserId();
1756 MemoryContext oldcxt;
1758 /* Do nothing if an override search spec is active. */
1762 /* Do nothing if path is already valid. */
1763 if (baseSearchPathValid && namespaceUser == roleid)
1766 /* Need a modifiable copy of namespace_search_path string */
1767 rawname = pstrdup(namespace_search_path);
1769 /* Parse string into list of identifiers */
1770 if (!SplitIdentifierString(rawname, ',', &namelist))
1772 /* syntax error in name list */
1773 /* this should not happen if GUC checked check_search_path */
1774 elog(ERROR, "invalid list syntax");
1778 * Convert the list of names to a list of OIDs. If any names are not
1779 * recognizable or we don't have read access, just leave them out of the
1780 * list. (We can't raise an error, since the search_path setting has
1781 * already been accepted.) Don't make duplicate entries, either.
1784 foreach(l, namelist)
1786 char *curname = (char *) lfirst(l);
1789 if (strcmp(curname, "$user") == 0)
1791 /* $user --- substitute namespace matching user name, if any */
1794 tuple = SearchSysCache(AUTHOID,
1795 ObjectIdGetDatum(roleid),
1797 if (HeapTupleIsValid(tuple))
1801 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
1802 namespaceId = GetSysCacheOid(NAMESPACENAME,
1803 CStringGetDatum(rname),
1805 ReleaseSysCache(tuple);
1806 if (OidIsValid(namespaceId) &&
1807 !list_member_oid(oidlist, namespaceId) &&
1808 pg_namespace_aclcheck(namespaceId, roleid,
1809 ACL_USAGE) == ACLCHECK_OK)
1810 oidlist = lappend_oid(oidlist, namespaceId);
1815 /* normal namespace reference */
1816 namespaceId = GetSysCacheOid(NAMESPACENAME,
1817 CStringGetDatum(curname),
1819 if (OidIsValid(namespaceId) &&
1820 !list_member_oid(oidlist, namespaceId) &&
1821 pg_namespace_aclcheck(namespaceId, roleid,
1822 ACL_USAGE) == ACLCHECK_OK)
1823 oidlist = lappend_oid(oidlist, namespaceId);
1828 * Remember the first member of the explicit list.
1831 firstNS = InvalidOid;
1833 firstNS = linitial_oid(oidlist);
1836 * Add any implicitly-searched namespaces to the list. Note these go on
1837 * the front, not the back; also notice that we do not check USAGE
1838 * permissions for these.
1840 if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
1841 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
1843 if (OidIsValid(myTempNamespace) &&
1844 !list_member_oid(oidlist, myTempNamespace))
1845 oidlist = lcons_oid(myTempNamespace, oidlist);
1848 * Now that we've successfully built the new list of namespace OIDs, save
1849 * it in permanent storage.
1851 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1852 newpath = list_copy(oidlist);
1853 MemoryContextSwitchTo(oldcxt);
1855 /* Now safe to assign to state variables. */
1856 list_free(baseSearchPath);
1857 baseSearchPath = newpath;
1858 baseCreationNamespace = firstNS;
1860 /* Mark the path valid. */
1861 baseSearchPathValid = true;
1862 namespaceUser = roleid;
1864 /* And make it active. */
1865 activeSearchPath = baseSearchPath;
1866 activeCreationNamespace = baseCreationNamespace;
1870 list_free(namelist);
1875 * InitTempTableNamespace
1876 * Initialize temp table namespace on first use in a particular backend
1879 InitTempTableNamespace(void)
1881 char namespaceName[NAMEDATALEN];
1885 * First, do permission check to see if we are authorized to make temp
1886 * tables. We use a nonstandard error message here since "databasename:
1887 * permission denied" might be a tad cryptic.
1889 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
1890 * that's necessary since current user ID could change during the session.
1891 * But there's no need to make the namespace in the first place until a
1892 * temp table creation request is made by someone with appropriate rights.
1894 if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
1895 ACL_CREATE_TEMP) != ACLCHECK_OK)
1897 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1898 errmsg("permission denied to create temporary tables in database \"%s\"",
1899 get_database_name(MyDatabaseId))));
1901 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
1903 namespaceId = GetSysCacheOid(NAMESPACENAME,
1904 CStringGetDatum(namespaceName),
1906 if (!OidIsValid(namespaceId))
1909 * First use of this temp namespace in this database; create it. The
1910 * temp namespaces are always owned by the superuser. We leave their
1911 * permissions at default --- i.e., no access except to superuser ---
1912 * to ensure that unprivileged users can't peek at other backends'
1913 * temp tables. This works because the places that access the temp
1914 * namespace for my own backend skip permissions checks on it.
1916 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
1917 /* Advance command counter to make namespace visible */
1918 CommandCounterIncrement();
1923 * If the namespace already exists, clean it out (in case the former
1924 * owner crashed without doing so).
1926 RemoveTempRelations(namespaceId);
1930 * Okay, we've prepared the temp namespace ... but it's not committed yet,
1931 * so all our work could be undone by transaction rollback. Set flag for
1932 * AtEOXact_Namespace to know what to do.
1934 myTempNamespace = namespaceId;
1936 /* It should not be done already. */
1937 AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
1938 myTempNamespaceSubID = GetCurrentSubTransactionId();
1940 baseSearchPathValid = false; /* need to rebuild list */
1944 * End-of-transaction cleanup for namespaces.
1947 AtEOXact_Namespace(bool isCommit)
1950 * If we abort the transaction in which a temp namespace was selected,
1951 * we'll have to do any creation or cleanout work over again. So, just
1952 * forget the namespace entirely until next time. On the other hand, if
1953 * we commit then register an exit callback to clean out the temp tables
1954 * at backend shutdown. (We only want to register the callback once per
1955 * session, so this is a good place to do it.)
1957 if (myTempNamespaceSubID != InvalidSubTransactionId)
1960 on_shmem_exit(RemoveTempRelationsCallback, 0);
1963 myTempNamespace = InvalidOid;
1964 baseSearchPathValid = false; /* need to rebuild list */
1966 myTempNamespaceSubID = InvalidSubTransactionId;
1970 * Clean up if someone failed to do PopOverrideSearchPath
1975 elog(WARNING, "leaked override search path");
1976 while (overrideStack)
1978 OverrideStackEntry *entry;
1980 entry = (OverrideStackEntry *) linitial(overrideStack);
1981 overrideStack = list_delete_first(overrideStack);
1982 list_free(entry->searchPath);
1985 /* If not baseSearchPathValid, this is useless but harmless */
1986 activeSearchPath = baseSearchPath;
1987 activeCreationNamespace = baseCreationNamespace;
1992 * AtEOSubXact_Namespace
1994 * At subtransaction commit, propagate the temp-namespace-creation
1995 * flag to the parent subtransaction.
1997 * At subtransaction abort, forget the flag if we set it up.
2000 AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
2001 SubTransactionId parentSubid)
2003 OverrideStackEntry *entry;
2005 if (myTempNamespaceSubID == mySubid)
2008 myTempNamespaceSubID = parentSubid;
2011 myTempNamespaceSubID = InvalidSubTransactionId;
2012 /* TEMP namespace creation failed, so reset state */
2013 myTempNamespace = InvalidOid;
2014 baseSearchPathValid = false; /* need to rebuild list */
2019 * Clean up if someone failed to do PopOverrideSearchPath
2021 while (overrideStack)
2023 entry = (OverrideStackEntry *) linitial(overrideStack);
2024 if (entry->nestLevel < GetCurrentTransactionNestLevel())
2027 elog(WARNING, "leaked override search path");
2028 overrideStack = list_delete_first(overrideStack);
2029 list_free(entry->searchPath);
2033 /* Activate the next level down. */
2036 entry = (OverrideStackEntry *) linitial(overrideStack);
2037 activeSearchPath = entry->searchPath;
2038 activeCreationNamespace = entry->creationNamespace;
2042 /* If not baseSearchPathValid, this is useless but harmless */
2043 activeSearchPath = baseSearchPath;
2044 activeCreationNamespace = baseCreationNamespace;
2049 * Remove all relations in the specified temp namespace.
2051 * This is called at backend shutdown (if we made any temp relations).
2052 * It is also called when we begin using a pre-existing temp namespace,
2053 * in order to clean out any relations that might have been created by
2054 * a crashed backend.
2057 RemoveTempRelations(Oid tempNamespaceId)
2059 ObjectAddress object;
2062 * We want to get rid of everything in the target namespace, but not the
2063 * namespace itself (deleting it only to recreate it later would be a
2064 * waste of cycles). We do this by finding everything that has a
2065 * dependency on the namespace.
2067 object.classId = NamespaceRelationId;
2068 object.objectId = tempNamespaceId;
2069 object.objectSubId = 0;
2071 deleteWhatDependsOn(&object, false);
2075 * Callback to remove temp relations at backend exit.
2078 RemoveTempRelationsCallback(int code, Datum arg)
2080 if (OidIsValid(myTempNamespace)) /* should always be true */
2082 /* Need to ensure we have a usable transaction. */
2083 AbortOutOfAnyTransaction();
2084 StartTransactionCommand();
2086 RemoveTempRelations(myTempNamespace);
2088 CommitTransactionCommand();
2094 * Routines for handling the GUC variable 'search_path'.
2097 /* assign_hook: validate new search_path, do extra actions as needed */
2099 assign_search_path(const char *newval, bool doit, GucSource source)
2105 /* Need a modifiable copy of string */
2106 rawname = pstrdup(newval);
2108 /* Parse string into list of identifiers */
2109 if (!SplitIdentifierString(rawname, ',', &namelist))
2111 /* syntax error in name list */
2113 list_free(namelist);
2118 * If we aren't inside a transaction, we cannot do database access so
2119 * cannot verify the individual names. Must accept the list on faith.
2121 if (source >= PGC_S_INTERACTIVE && IsTransactionState())
2124 * Verify that all the names are either valid namespace names or
2125 * "$user". We do not require $user to correspond to a valid
2126 * namespace. We do not check for USAGE rights, either; should we?
2128 * When source == PGC_S_TEST, we are checking the argument of an ALTER
2129 * DATABASE SET or ALTER USER SET command. It could be that the
2130 * intended use of the search path is for some other database, so we
2131 * should not error out if it mentions schemas not present in the
2132 * current database. We reduce the message to NOTICE instead.
2134 foreach(l, namelist)
2136 char *curname = (char *) lfirst(l);
2138 if (strcmp(curname, "$user") == 0)
2140 if (!SearchSysCacheExists(NAMESPACENAME,
2141 CStringGetDatum(curname),
2143 ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
2144 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2145 errmsg("schema \"%s\" does not exist", curname)));
2150 list_free(namelist);
2153 * We mark the path as needing recomputation, but don't do anything until
2154 * it's needed. This avoids trying to do database access during GUC
2158 baseSearchPathValid = false;
2164 * InitializeSearchPath: initialize module during InitPostgres.
2166 * This is called after we are up enough to be able to do catalog lookups.
2169 InitializeSearchPath(void)
2171 if (IsBootstrapProcessingMode())
2174 * In bootstrap mode, the search path must be 'pg_catalog' so that
2175 * tables are created in the proper namespace; ignore the GUC setting.
2177 MemoryContext oldcxt;
2179 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2180 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
2181 MemoryContextSwitchTo(oldcxt);
2182 baseCreationNamespace = PG_CATALOG_NAMESPACE;
2183 baseSearchPathValid = true;
2184 namespaceUser = GetUserId();
2185 activeSearchPath = baseSearchPath;
2186 activeCreationNamespace = baseCreationNamespace;
2191 * In normal mode, arrange for a callback on any syscache invalidation
2192 * of pg_namespace rows.
2194 CacheRegisterSyscacheCallback(NAMESPACEOID,
2197 /* Force search path to be recomputed on next use */
2198 baseSearchPathValid = false;
2204 * Syscache inval callback function
2207 NamespaceCallback(Datum arg, Oid relid)
2209 /* Force search path to be recomputed on next use */
2210 baseSearchPathValid = false;
2214 * Fetch the active search path. The return value is a palloc'ed list
2215 * of OIDs; the caller is responsible for freeing this storage as
2218 * The returned list includes the implicitly-prepended namespaces only if
2219 * includeImplicit is true.
2222 fetch_search_path(bool includeImplicit)
2226 recomputeNamespacePath();
2228 result = list_copy(activeSearchPath);
2229 if (!includeImplicit)
2231 while (result && linitial_oid(result) != activeCreationNamespace)
2232 result = list_delete_first(result);
2239 * Export the FooIsVisible functions as SQL-callable functions.
2243 pg_table_is_visible(PG_FUNCTION_ARGS)
2245 Oid oid = PG_GETARG_OID(0);
2247 PG_RETURN_BOOL(RelationIsVisible(oid));
2251 pg_type_is_visible(PG_FUNCTION_ARGS)
2253 Oid oid = PG_GETARG_OID(0);
2255 PG_RETURN_BOOL(TypeIsVisible(oid));
2259 pg_function_is_visible(PG_FUNCTION_ARGS)
2261 Oid oid = PG_GETARG_OID(0);
2263 PG_RETURN_BOOL(FunctionIsVisible(oid));
2267 pg_operator_is_visible(PG_FUNCTION_ARGS)
2269 Oid oid = PG_GETARG_OID(0);
2271 PG_RETURN_BOOL(OperatorIsVisible(oid));
2275 pg_opclass_is_visible(PG_FUNCTION_ARGS)
2277 Oid oid = PG_GETARG_OID(0);
2279 PG_RETURN_BOOL(OpclassIsVisible(oid));
2283 pg_conversion_is_visible(PG_FUNCTION_ARGS)
2285 Oid oid = PG_GETARG_OID(0);
2287 PG_RETURN_BOOL(ConversionIsVisible(oid));
2291 pg_my_temp_schema(PG_FUNCTION_ARGS)
2293 PG_RETURN_OID(myTempNamespace);
2297 pg_is_other_temp_schema(PG_FUNCTION_ARGS)
2299 Oid oid = PG_GETARG_OID(0);
2301 PG_RETURN_BOOL(isOtherTempNamespace(oid));