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.97 2007/07/25 22:16:18 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 * For security reasons, searches using the search path will ignore the temp
66 * namespace when searching for any object type other than relations and
67 * types. (We must allow types since temp tables have rowtypes.)
69 * The default creation target namespace is always the first element of the
70 * explicit list. If the explicit list is empty, there is no default target.
72 * The textual specification of search_path can include "$user" to refer to
73 * the namespace named the same as the current user, if any. (This is just
74 * ignored if there is no such namespace.) Also, it can include "pg_temp"
75 * to refer to the current backend's temp namespace. This is usually also
76 * ignorable if the temp namespace hasn't been set up, but there's a special
77 * case: if "pg_temp" appears first then it should be the default creation
78 * target. We kluge this case a little bit so that the temp namespace isn't
79 * set up until the first attempt to create something in it. (The reason for
80 * klugery is that we can't create the temp namespace outside a transaction,
81 * but initial GUC processing of search_path happens outside a transaction.)
82 * activeTempCreationPending is TRUE if "pg_temp" appears first in the string
83 * but is not reflected in activeCreationNamespace because the namespace isn't
86 * In bootstrap mode, the search path is set equal to "pg_catalog", so that
87 * the system namespace is the only one searched or inserted into.
88 * initdb is also careful to set search_path to "pg_catalog" for its
89 * post-bootstrap standalone backend runs. Otherwise the default search
90 * path is determined by GUC. The factory default path contains the PUBLIC
91 * namespace (if it exists), preceded by the user's personal namespace
94 * We support a stack of "override" search path settings for use within
95 * specific sections of backend code. namespace_search_path is ignored
96 * whenever the override stack is nonempty. activeSearchPath is always
97 * the actually active path; it points either to the search list of the
98 * topmost stack entry, or to baseSearchPath which is the list derived
99 * from namespace_search_path.
101 * If baseSearchPathValid is false, then baseSearchPath (and other
102 * derived variables) need to be recomputed from namespace_search_path.
103 * We mark it invalid upon an assignment to namespace_search_path or receipt
104 * of a syscache invalidation event for pg_namespace. The recomputation
105 * is done during the next non-overridden lookup attempt. Note that an
106 * override spec is never subject to recomputation.
108 * Any namespaces mentioned in namespace_search_path that are not readable
109 * by the current user ID are simply left out of baseSearchPath; so
110 * we have to be willing to recompute the path when current userid changes.
111 * namespaceUser is the userid the path has been computed for.
113 * Note: all data pointed to by these List variables is in TopMemoryContext.
116 /* These variables define the actually active state: */
118 static List *activeSearchPath = NIL;
120 /* default place to create stuff; if InvalidOid, no default */
121 static Oid activeCreationNamespace = InvalidOid;
123 /* if TRUE, activeCreationNamespace is wrong, it should be temp namespace */
124 static bool activeTempCreationPending = false;
126 /* These variables are the values last derived from namespace_search_path: */
128 static List *baseSearchPath = NIL;
130 static Oid baseCreationNamespace = InvalidOid;
132 static bool baseTempCreationPending = false;
134 static Oid namespaceUser = InvalidOid;
136 /* The above four values are valid only if baseSearchPathValid */
137 static bool baseSearchPathValid = true;
139 /* Override requests are remembered in a stack of OverrideStackEntry structs */
143 List *searchPath; /* the desired search path */
144 Oid creationNamespace; /* the desired creation namespace */
145 int nestLevel; /* subtransaction nesting level */
146 } OverrideStackEntry;
148 static List *overrideStack = NIL;
151 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
152 * in a particular backend session (this happens when a CREATE TEMP TABLE
153 * command is first executed). Thereafter it's the OID of the temp namespace.
155 * myTempToastNamespace is the OID of the namespace for my temp tables' toast
156 * tables. It is set when myTempNamespace is, and is InvalidOid before that.
158 * myTempNamespaceSubID shows whether we've created the TEMP namespace in the
159 * current subtransaction. The flag propagates up the subtransaction tree,
160 * so the main transaction will correctly recognize the flag if all
161 * intermediate subtransactions commit. When it is InvalidSubTransactionId,
162 * we either haven't made the TEMP namespace yet, or have successfully
163 * committed its creation, depending on whether myTempNamespace is valid.
165 static Oid myTempNamespace = InvalidOid;
167 static Oid myTempToastNamespace = InvalidOid;
169 static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
172 * This is the user's textual search path specification --- it's the value
173 * of the GUC variable 'search_path'.
175 char *namespace_search_path = NULL;
178 /* Local functions */
179 static void recomputeNamespacePath(void);
180 static void InitTempTableNamespace(void);
181 static void RemoveTempRelations(Oid tempNamespaceId);
182 static void RemoveTempRelationsCallback(int code, Datum arg);
183 static void NamespaceCallback(Datum arg, Oid relid);
185 /* These don't really need to appear in any header file */
186 Datum pg_table_is_visible(PG_FUNCTION_ARGS);
187 Datum pg_type_is_visible(PG_FUNCTION_ARGS);
188 Datum pg_function_is_visible(PG_FUNCTION_ARGS);
189 Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
190 Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
191 Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
192 Datum pg_my_temp_schema(PG_FUNCTION_ARGS);
193 Datum pg_is_other_temp_schema(PG_FUNCTION_ARGS);
198 * Given a RangeVar describing an existing relation,
199 * select the proper namespace and look up the relation OID.
201 * If the relation is not found, return InvalidOid if failOK = true,
202 * otherwise raise an error.
205 RangeVarGetRelid(const RangeVar *relation, bool failOK)
211 * We check the catalog name and then ignore it.
213 if (relation->catalogname)
215 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
217 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
218 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
219 relation->catalogname, relation->schemaname,
220 relation->relname)));
223 if (relation->schemaname)
225 /* use exact schema given */
226 namespaceId = LookupExplicitNamespace(relation->schemaname);
227 relId = get_relname_relid(relation->relname, namespaceId);
231 /* search the namespace path */
232 relId = RelnameGetRelid(relation->relname);
235 if (!OidIsValid(relId) && !failOK)
237 if (relation->schemaname)
239 (errcode(ERRCODE_UNDEFINED_TABLE),
240 errmsg("relation \"%s.%s\" does not exist",
241 relation->schemaname, relation->relname)));
244 (errcode(ERRCODE_UNDEFINED_TABLE),
245 errmsg("relation \"%s\" does not exist",
246 relation->relname)));
252 * RangeVarGetCreationNamespace
253 * Given a RangeVar describing a to-be-created relation,
254 * choose which namespace to create it in.
256 * Note: calling this may result in a CommandCounterIncrement operation.
257 * That will happen on the first request for a temp table in any particular
258 * backend run; we will need to either create or clean out the temp schema.
261 RangeVarGetCreationNamespace(const RangeVar *newRelation)
266 * We check the catalog name and then ignore it.
268 if (newRelation->catalogname)
270 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
272 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
273 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
274 newRelation->catalogname, newRelation->schemaname,
275 newRelation->relname)));
278 if (newRelation->istemp)
280 /* TEMP tables are created in our backend-local temp namespace */
281 if (newRelation->schemaname)
283 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
284 errmsg("temporary tables cannot specify a schema name")));
285 /* Initialize temp namespace if first time through */
286 if (!OidIsValid(myTempNamespace))
287 InitTempTableNamespace();
288 return myTempNamespace;
291 if (newRelation->schemaname)
293 /* check for pg_temp alias */
294 if (strcmp(newRelation->schemaname, "pg_temp") == 0)
296 /* Initialize temp namespace if first time through */
297 if (!OidIsValid(myTempNamespace))
298 InitTempTableNamespace();
299 return myTempNamespace;
301 /* use exact schema given */
302 namespaceId = GetSysCacheOid(NAMESPACENAME,
303 CStringGetDatum(newRelation->schemaname),
305 if (!OidIsValid(namespaceId))
307 (errcode(ERRCODE_UNDEFINED_SCHEMA),
308 errmsg("schema \"%s\" does not exist",
309 newRelation->schemaname)));
310 /* we do not check for USAGE rights here! */
314 /* use the default creation namespace */
315 recomputeNamespacePath();
316 if (activeTempCreationPending)
318 /* Need to initialize temp namespace */
319 InitTempTableNamespace();
320 return myTempNamespace;
322 namespaceId = activeCreationNamespace;
323 if (!OidIsValid(namespaceId))
325 (errcode(ERRCODE_UNDEFINED_SCHEMA),
326 errmsg("no schema has been selected to create in")));
329 /* Note: callers will check for CREATE rights when appropriate */
336 * Try to resolve an unqualified relation name.
337 * Returns OID if relation found in search path, else InvalidOid.
340 RelnameGetRelid(const char *relname)
345 recomputeNamespacePath();
347 foreach(l, activeSearchPath)
349 Oid namespaceId = lfirst_oid(l);
351 relid = get_relname_relid(relname, namespaceId);
352 if (OidIsValid(relid))
356 /* Not found in path */
363 * Determine whether a relation (identified by OID) is visible in the
364 * current search path. Visible means "would be found by searching
365 * for the unqualified relation name".
368 RelationIsVisible(Oid relid)
371 Form_pg_class relform;
375 reltup = SearchSysCache(RELOID,
376 ObjectIdGetDatum(relid),
378 if (!HeapTupleIsValid(reltup))
379 elog(ERROR, "cache lookup failed for relation %u", relid);
380 relform = (Form_pg_class) GETSTRUCT(reltup);
382 recomputeNamespacePath();
385 * Quick check: if it ain't in the path at all, it ain't visible. Items in
386 * the system namespace are surely in the path and so we needn't even do
387 * list_member_oid() for them.
389 relnamespace = relform->relnamespace;
390 if (relnamespace != PG_CATALOG_NAMESPACE &&
391 !list_member_oid(activeSearchPath, relnamespace))
396 * If it is in the path, it might still not be visible; it could be
397 * hidden by another relation of the same name earlier in the path. So
398 * we must do a slow check for conflicting relations.
400 char *relname = NameStr(relform->relname);
404 foreach(l, activeSearchPath)
406 Oid namespaceId = lfirst_oid(l);
408 if (namespaceId == relnamespace)
410 /* Found it first in path */
414 if (OidIsValid(get_relname_relid(relname, namespaceId)))
416 /* Found something else first in path */
422 ReleaseSysCache(reltup);
430 * Try to resolve an unqualified datatype name.
431 * Returns OID if type found in search path, else InvalidOid.
433 * This is essentially the same as RelnameGetRelid.
436 TypenameGetTypid(const char *typname)
441 recomputeNamespacePath();
443 foreach(l, activeSearchPath)
445 Oid namespaceId = lfirst_oid(l);
447 typid = GetSysCacheOid(TYPENAMENSP,
448 PointerGetDatum(typname),
449 ObjectIdGetDatum(namespaceId),
451 if (OidIsValid(typid))
455 /* Not found in path */
461 * Determine whether a type (identified by OID) is visible in the
462 * current search path. Visible means "would be found by searching
463 * for the unqualified type name".
466 TypeIsVisible(Oid typid)
469 Form_pg_type typform;
473 typtup = SearchSysCache(TYPEOID,
474 ObjectIdGetDatum(typid),
476 if (!HeapTupleIsValid(typtup))
477 elog(ERROR, "cache lookup failed for type %u", typid);
478 typform = (Form_pg_type) GETSTRUCT(typtup);
480 recomputeNamespacePath();
483 * Quick check: if it ain't in the path at all, it ain't visible. Items in
484 * the system namespace are surely in the path and so we needn't even do
485 * list_member_oid() for them.
487 typnamespace = typform->typnamespace;
488 if (typnamespace != PG_CATALOG_NAMESPACE &&
489 !list_member_oid(activeSearchPath, typnamespace))
494 * If it is in the path, it might still not be visible; it could be
495 * hidden by another type of the same name earlier in the path. So we
496 * must do a slow check for conflicting types.
498 char *typname = NameStr(typform->typname);
502 foreach(l, activeSearchPath)
504 Oid namespaceId = lfirst_oid(l);
506 if (namespaceId == typnamespace)
508 /* Found it first in path */
512 if (SearchSysCacheExists(TYPENAMENSP,
513 PointerGetDatum(typname),
514 ObjectIdGetDatum(namespaceId),
517 /* Found something else first in path */
523 ReleaseSysCache(typtup);
530 * FuncnameGetCandidates
531 * Given a possibly-qualified function name and argument count,
532 * retrieve a list of the possible matches.
534 * If nargs is -1, we return all functions matching the given name,
535 * regardless of argument count.
537 * We search a single namespace if the function name is qualified, else
538 * all namespaces in the search path. The return list will never contain
539 * multiple entries with identical argument lists --- in the multiple-
540 * namespace case, we arrange for entries in earlier namespaces to mask
541 * identical entries in later namespaces.
544 FuncnameGetCandidates(List *names, int nargs)
546 FuncCandidateList resultList = NULL;
553 /* deconstruct the name list */
554 DeconstructQualifiedName(names, &schemaname, &funcname);
558 /* use exact schema given */
559 namespaceId = LookupExplicitNamespace(schemaname);
563 /* flag to indicate we need namespace search */
564 namespaceId = InvalidOid;
565 recomputeNamespacePath();
568 /* Search syscache by name only */
569 catlist = SearchSysCacheList(PROCNAMEARGSNSP, 1,
570 CStringGetDatum(funcname),
573 for (i = 0; i < catlist->n_members; i++)
575 HeapTuple proctup = &catlist->members[i]->tuple;
576 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
577 int pronargs = procform->pronargs;
579 FuncCandidateList newResult;
581 /* Ignore if it doesn't match requested argument count */
582 if (nargs >= 0 && pronargs != nargs)
585 if (OidIsValid(namespaceId))
587 /* Consider only procs in specified namespace */
588 if (procform->pronamespace != namespaceId)
590 /* No need to check args, they must all be different */
595 * Consider only procs that are in the search path and are not
596 * in the temp namespace.
600 foreach(nsp, activeSearchPath)
602 if (procform->pronamespace == lfirst_oid(nsp) &&
603 procform->pronamespace != myTempNamespace)
608 continue; /* proc is not in search path */
611 * Okay, it's in the search path, but does it have the same
612 * arguments as something we already accepted? If so, keep only
613 * the one that appears earlier in the search path.
615 * If we have an ordered list from SearchSysCacheList (the normal
616 * case), then any conflicting proc must immediately adjoin this
617 * one in the list, so we only need to look at the newest result
618 * item. If we have an unordered list, we have to scan the whole
623 FuncCandidateList prevResult;
625 if (catlist->ordered)
627 if (pronargs == resultList->nargs &&
628 memcmp(procform->proargtypes.values,
630 pronargs * sizeof(Oid)) == 0)
631 prevResult = resultList;
637 for (prevResult = resultList;
639 prevResult = prevResult->next)
641 if (pronargs == prevResult->nargs &&
642 memcmp(procform->proargtypes.values,
644 pronargs * sizeof(Oid)) == 0)
650 /* We have a match with a previous result */
651 Assert(pathpos != prevResult->pathpos);
652 if (pathpos > prevResult->pathpos)
653 continue; /* keep previous result */
654 /* replace previous result */
655 prevResult->pathpos = pathpos;
656 prevResult->oid = HeapTupleGetOid(proctup);
657 continue; /* args are same, of course */
663 * Okay to add it to result list
665 newResult = (FuncCandidateList)
666 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
667 + pronargs * sizeof(Oid));
668 newResult->pathpos = pathpos;
669 newResult->oid = HeapTupleGetOid(proctup);
670 newResult->nargs = pronargs;
671 memcpy(newResult->args, procform->proargtypes.values,
672 pronargs * sizeof(Oid));
674 newResult->next = resultList;
675 resultList = newResult;
678 ReleaseSysCacheList(catlist);
685 * Determine whether a function (identified by OID) is visible in the
686 * current search path. Visible means "would be found by searching
687 * for the unqualified function name with exact argument matches".
690 FunctionIsVisible(Oid funcid)
693 Form_pg_proc procform;
697 proctup = SearchSysCache(PROCOID,
698 ObjectIdGetDatum(funcid),
700 if (!HeapTupleIsValid(proctup))
701 elog(ERROR, "cache lookup failed for function %u", funcid);
702 procform = (Form_pg_proc) GETSTRUCT(proctup);
704 recomputeNamespacePath();
707 * Quick check: if it ain't in the path at all, it ain't visible. Items in
708 * the system namespace are surely in the path and so we needn't even do
709 * list_member_oid() for them.
711 pronamespace = procform->pronamespace;
712 if (pronamespace != PG_CATALOG_NAMESPACE &&
713 !list_member_oid(activeSearchPath, pronamespace))
718 * If it is in the path, it might still not be visible; it could be
719 * hidden by another proc of the same name and arguments earlier in
720 * the path. So we must do a slow check to see if this is the same
721 * proc that would be found by FuncnameGetCandidates.
723 char *proname = NameStr(procform->proname);
724 int nargs = procform->pronargs;
725 FuncCandidateList clist;
729 clist = FuncnameGetCandidates(list_make1(makeString(proname)), nargs);
731 for (; clist; clist = clist->next)
733 if (memcmp(clist->args, procform->proargtypes.values,
734 nargs * sizeof(Oid)) == 0)
736 /* Found the expected entry; is it the right proc? */
737 visible = (clist->oid == funcid);
743 ReleaseSysCache(proctup);
751 * Given a possibly-qualified operator name and exact input datatypes,
752 * look up the operator. Returns InvalidOid if not found.
754 * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
757 * If the operator name is not schema-qualified, it is sought in the current
758 * namespace search path.
761 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
768 /* deconstruct the name list */
769 DeconstructQualifiedName(names, &schemaname, &opername);
773 /* search only in exact schema given */
777 namespaceId = LookupExplicitNamespace(schemaname);
778 opertup = SearchSysCache(OPERNAMENSP,
779 CStringGetDatum(opername),
780 ObjectIdGetDatum(oprleft),
781 ObjectIdGetDatum(oprright),
782 ObjectIdGetDatum(namespaceId));
783 if (HeapTupleIsValid(opertup))
785 Oid result = HeapTupleGetOid(opertup);
787 ReleaseSysCache(opertup);
793 /* Search syscache by name and argument types */
794 catlist = SearchSysCacheList(OPERNAMENSP, 3,
795 CStringGetDatum(opername),
796 ObjectIdGetDatum(oprleft),
797 ObjectIdGetDatum(oprright),
800 if (catlist->n_members == 0)
802 /* no hope, fall out early */
803 ReleaseSysCacheList(catlist);
808 * We have to find the list member that is first in the search path, if
809 * there's more than one. This doubly-nested loop looks ugly, but in
810 * practice there should usually be few catlist members.
812 recomputeNamespacePath();
814 foreach(l, activeSearchPath)
816 Oid namespaceId = lfirst_oid(l);
819 if (namespaceId == myTempNamespace)
820 continue; /* do not look in temp namespace */
822 for (i = 0; i < catlist->n_members; i++)
824 HeapTuple opertup = &catlist->members[i]->tuple;
825 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
827 if (operform->oprnamespace == namespaceId)
829 Oid result = HeapTupleGetOid(opertup);
831 ReleaseSysCacheList(catlist);
837 ReleaseSysCacheList(catlist);
842 * OpernameGetCandidates
843 * Given a possibly-qualified operator name and operator kind,
844 * retrieve a list of the possible matches.
846 * If oprkind is '\0', we return all operators matching the given name,
847 * regardless of arguments.
849 * We search a single namespace if the operator name is qualified, else
850 * all namespaces in the search path. The return list will never contain
851 * multiple entries with identical argument lists --- in the multiple-
852 * namespace case, we arrange for entries in earlier namespaces to mask
853 * identical entries in later namespaces.
855 * The returned items always have two args[] entries --- one or the other
856 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
859 OpernameGetCandidates(List *names, char oprkind)
861 FuncCandidateList resultList = NULL;
862 char *resultSpace = NULL;
870 /* deconstruct the name list */
871 DeconstructQualifiedName(names, &schemaname, &opername);
875 /* use exact schema given */
876 namespaceId = LookupExplicitNamespace(schemaname);
880 /* flag to indicate we need namespace search */
881 namespaceId = InvalidOid;
882 recomputeNamespacePath();
885 /* Search syscache by name only */
886 catlist = SearchSysCacheList(OPERNAMENSP, 1,
887 CStringGetDatum(opername),
891 * In typical scenarios, most if not all of the operators found by the
892 * catcache search will end up getting returned; and there can be quite a
893 * few, for common operator names such as '=' or '+'. To reduce the time
894 * spent in palloc, we allocate the result space as an array large enough
895 * to hold all the operators. The original coding of this routine did a
896 * separate palloc for each operator, but profiling revealed that the
897 * pallocs used an unreasonably large fraction of parsing time.
899 #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
901 if (catlist->n_members > 0)
902 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
904 for (i = 0; i < catlist->n_members; i++)
906 HeapTuple opertup = &catlist->members[i]->tuple;
907 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
909 FuncCandidateList newResult;
911 /* Ignore operators of wrong kind, if specific kind requested */
912 if (oprkind && operform->oprkind != oprkind)
915 if (OidIsValid(namespaceId))
917 /* Consider only opers in specified namespace */
918 if (operform->oprnamespace != namespaceId)
920 /* No need to check args, they must all be different */
925 * Consider only opers that are in the search path and are not
926 * in the temp namespace.
930 foreach(nsp, activeSearchPath)
932 if (operform->oprnamespace == lfirst_oid(nsp) &&
933 operform->oprnamespace != myTempNamespace)
938 continue; /* oper is not in search path */
941 * Okay, it's in the search path, but does it have the same
942 * arguments as something we already accepted? If so, keep only
943 * the one that appears earlier in the search path.
945 * If we have an ordered list from SearchSysCacheList (the normal
946 * case), then any conflicting oper must immediately adjoin this
947 * one in the list, so we only need to look at the newest result
948 * item. If we have an unordered list, we have to scan the whole
953 FuncCandidateList prevResult;
955 if (catlist->ordered)
957 if (operform->oprleft == resultList->args[0] &&
958 operform->oprright == resultList->args[1])
959 prevResult = resultList;
965 for (prevResult = resultList;
967 prevResult = prevResult->next)
969 if (operform->oprleft == prevResult->args[0] &&
970 operform->oprright == prevResult->args[1])
976 /* We have a match with a previous result */
977 Assert(pathpos != prevResult->pathpos);
978 if (pathpos > prevResult->pathpos)
979 continue; /* keep previous result */
980 /* replace previous result */
981 prevResult->pathpos = pathpos;
982 prevResult->oid = HeapTupleGetOid(opertup);
983 continue; /* args are same, of course */
989 * Okay to add it to result list
991 newResult = (FuncCandidateList) (resultSpace + nextResult);
992 nextResult += SPACE_PER_OP;
994 newResult->pathpos = pathpos;
995 newResult->oid = HeapTupleGetOid(opertup);
996 newResult->nargs = 2;
997 newResult->args[0] = operform->oprleft;
998 newResult->args[1] = operform->oprright;
999 newResult->next = resultList;
1000 resultList = newResult;
1003 ReleaseSysCacheList(catlist);
1010 * Determine whether an operator (identified by OID) is visible in the
1011 * current search path. Visible means "would be found by searching
1012 * for the unqualified operator name with exact argument matches".
1015 OperatorIsVisible(Oid oprid)
1018 Form_pg_operator oprform;
1022 oprtup = SearchSysCache(OPEROID,
1023 ObjectIdGetDatum(oprid),
1025 if (!HeapTupleIsValid(oprtup))
1026 elog(ERROR, "cache lookup failed for operator %u", oprid);
1027 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
1029 recomputeNamespacePath();
1032 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1033 * the system namespace are surely in the path and so we needn't even do
1034 * list_member_oid() for them.
1036 oprnamespace = oprform->oprnamespace;
1037 if (oprnamespace != PG_CATALOG_NAMESPACE &&
1038 !list_member_oid(activeSearchPath, oprnamespace))
1043 * If it is in the path, it might still not be visible; it could be
1044 * hidden by another operator of the same name and arguments earlier
1045 * in the path. So we must do a slow check to see if this is the same
1046 * operator that would be found by OpernameGetOprId.
1048 char *oprname = NameStr(oprform->oprname);
1050 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
1051 oprform->oprleft, oprform->oprright)
1055 ReleaseSysCache(oprtup);
1062 * OpclassnameGetOpcid
1063 * Try to resolve an unqualified index opclass name.
1064 * Returns OID if opclass found in search path, else InvalidOid.
1066 * This is essentially the same as TypenameGetTypid, but we have to have
1067 * an extra argument for the index AM OID.
1070 OpclassnameGetOpcid(Oid amid, const char *opcname)
1075 recomputeNamespacePath();
1077 foreach(l, activeSearchPath)
1079 Oid namespaceId = lfirst_oid(l);
1081 if (namespaceId == myTempNamespace)
1082 continue; /* do not look in temp namespace */
1084 opcid = GetSysCacheOid(CLAAMNAMENSP,
1085 ObjectIdGetDatum(amid),
1086 PointerGetDatum(opcname),
1087 ObjectIdGetDatum(namespaceId),
1089 if (OidIsValid(opcid))
1093 /* Not found in path */
1099 * Determine whether an opclass (identified by OID) is visible in the
1100 * current search path. Visible means "would be found by searching
1101 * for the unqualified opclass name".
1104 OpclassIsVisible(Oid opcid)
1107 Form_pg_opclass opcform;
1111 opctup = SearchSysCache(CLAOID,
1112 ObjectIdGetDatum(opcid),
1114 if (!HeapTupleIsValid(opctup))
1115 elog(ERROR, "cache lookup failed for opclass %u", opcid);
1116 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1118 recomputeNamespacePath();
1121 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1122 * the system namespace are surely in the path and so we needn't even do
1123 * list_member_oid() for them.
1125 opcnamespace = opcform->opcnamespace;
1126 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1127 !list_member_oid(activeSearchPath, opcnamespace))
1132 * If it is in the path, it might still not be visible; it could be
1133 * hidden by another opclass of the same name earlier in the path. So
1134 * we must do a slow check to see if this opclass would be found by
1135 * OpclassnameGetOpcid.
1137 char *opcname = NameStr(opcform->opcname);
1139 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
1142 ReleaseSysCache(opctup);
1148 * OpfamilynameGetOpfid
1149 * Try to resolve an unqualified index opfamily name.
1150 * Returns OID if opfamily found in search path, else InvalidOid.
1152 * This is essentially the same as TypenameGetTypid, but we have to have
1153 * an extra argument for the index AM OID.
1156 OpfamilynameGetOpfid(Oid amid, const char *opfname)
1161 recomputeNamespacePath();
1163 foreach(l, activeSearchPath)
1165 Oid namespaceId = lfirst_oid(l);
1167 if (namespaceId == myTempNamespace)
1168 continue; /* do not look in temp namespace */
1170 opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
1171 ObjectIdGetDatum(amid),
1172 PointerGetDatum(opfname),
1173 ObjectIdGetDatum(namespaceId),
1175 if (OidIsValid(opfid))
1179 /* Not found in path */
1185 * Determine whether an opfamily (identified by OID) is visible in the
1186 * current search path. Visible means "would be found by searching
1187 * for the unqualified opfamily name".
1190 OpfamilyIsVisible(Oid opfid)
1193 Form_pg_opfamily opfform;
1197 opftup = SearchSysCache(OPFAMILYOID,
1198 ObjectIdGetDatum(opfid),
1200 if (!HeapTupleIsValid(opftup))
1201 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
1202 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
1204 recomputeNamespacePath();
1207 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1208 * the system namespace are surely in the path and so we needn't even do
1209 * list_member_oid() for them.
1211 opfnamespace = opfform->opfnamespace;
1212 if (opfnamespace != PG_CATALOG_NAMESPACE &&
1213 !list_member_oid(activeSearchPath, opfnamespace))
1218 * If it is in the path, it might still not be visible; it could be
1219 * hidden by another opfamily of the same name earlier in the path. So
1220 * we must do a slow check to see if this opfamily would be found by
1221 * OpfamilynameGetOpfid.
1223 char *opfname = NameStr(opfform->opfname);
1225 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
1228 ReleaseSysCache(opftup);
1234 * ConversionGetConid
1235 * Try to resolve an unqualified conversion name.
1236 * Returns OID if conversion found in search path, else InvalidOid.
1238 * This is essentially the same as RelnameGetRelid.
1241 ConversionGetConid(const char *conname)
1246 recomputeNamespacePath();
1248 foreach(l, activeSearchPath)
1250 Oid namespaceId = lfirst_oid(l);
1252 if (namespaceId == myTempNamespace)
1253 continue; /* do not look in temp namespace */
1255 conid = GetSysCacheOid(CONNAMENSP,
1256 PointerGetDatum(conname),
1257 ObjectIdGetDatum(namespaceId),
1259 if (OidIsValid(conid))
1263 /* Not found in path */
1268 * ConversionIsVisible
1269 * Determine whether a conversion (identified by OID) is visible in the
1270 * current search path. Visible means "would be found by searching
1271 * for the unqualified conversion name".
1274 ConversionIsVisible(Oid conid)
1277 Form_pg_conversion conform;
1281 contup = SearchSysCache(CONVOID,
1282 ObjectIdGetDatum(conid),
1284 if (!HeapTupleIsValid(contup))
1285 elog(ERROR, "cache lookup failed for conversion %u", conid);
1286 conform = (Form_pg_conversion) GETSTRUCT(contup);
1288 recomputeNamespacePath();
1291 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1292 * the system namespace are surely in the path and so we needn't even do
1293 * list_member_oid() for them.
1295 connamespace = conform->connamespace;
1296 if (connamespace != PG_CATALOG_NAMESPACE &&
1297 !list_member_oid(activeSearchPath, connamespace))
1302 * If it is in the path, it might still not be visible; it could be
1303 * hidden by another conversion of the same name earlier in the path.
1304 * So we must do a slow check to see if this conversion would be found
1305 * by ConversionGetConid.
1307 char *conname = NameStr(conform->conname);
1309 visible = (ConversionGetConid(conname) == conid);
1312 ReleaseSysCache(contup);
1318 * DeconstructQualifiedName
1319 * Given a possibly-qualified name expressed as a list of String nodes,
1320 * extract the schema name and object name.
1322 * *nspname_p is set to NULL if there is no explicit schema name.
1325 DeconstructQualifiedName(List *names,
1330 char *schemaname = NULL;
1331 char *objname = NULL;
1333 switch (list_length(names))
1336 objname = strVal(linitial(names));
1339 schemaname = strVal(linitial(names));
1340 objname = strVal(lsecond(names));
1343 catalogname = strVal(linitial(names));
1344 schemaname = strVal(lsecond(names));
1345 objname = strVal(lthird(names));
1348 * We check the catalog name and then ignore it.
1350 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
1352 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1353 errmsg("cross-database references are not implemented: %s",
1354 NameListToString(names))));
1358 (errcode(ERRCODE_SYNTAX_ERROR),
1359 errmsg("improper qualified name (too many dotted names): %s",
1360 NameListToString(names))));
1364 *nspname_p = schemaname;
1365 *objname_p = objname;
1369 * LookupExplicitNamespace
1370 * Process an explicitly-specified schema name: look up the schema
1371 * and verify we have USAGE (lookup) rights in it.
1373 * Returns the namespace OID. Raises ereport if any problem.
1376 LookupExplicitNamespace(const char *nspname)
1379 AclResult aclresult;
1381 /* check for pg_temp alias */
1382 if (strcmp(nspname, "pg_temp") == 0)
1384 if (OidIsValid(myTempNamespace))
1385 return myTempNamespace;
1387 * Since this is used only for looking up existing objects, there
1388 * is no point in trying to initialize the temp namespace here;
1389 * and doing so might create problems for some callers.
1390 * Just fall through and give the "does not exist" error.
1394 namespaceId = GetSysCacheOid(NAMESPACENAME,
1395 CStringGetDatum(nspname),
1397 if (!OidIsValid(namespaceId))
1399 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1400 errmsg("schema \"%s\" does not exist", nspname)));
1402 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
1403 if (aclresult != ACLCHECK_OK)
1404 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1411 * LookupCreationNamespace
1412 * Look up the schema and verify we have CREATE rights on it.
1414 * This is just like LookupExplicitNamespace except for the permission check,
1415 * and that we are willing to create pg_temp if needed.
1417 * Note: calling this may result in a CommandCounterIncrement operation,
1418 * if we have to create or clean out the temp namespace.
1421 LookupCreationNamespace(const char *nspname)
1424 AclResult aclresult;
1426 /* check for pg_temp alias */
1427 if (strcmp(nspname, "pg_temp") == 0)
1429 /* Initialize temp namespace if first time through */
1430 if (!OidIsValid(myTempNamespace))
1431 InitTempTableNamespace();
1432 return myTempNamespace;
1435 namespaceId = GetSysCacheOid(NAMESPACENAME,
1436 CStringGetDatum(nspname),
1438 if (!OidIsValid(namespaceId))
1440 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1441 errmsg("schema \"%s\" does not exist", nspname)));
1443 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
1444 if (aclresult != ACLCHECK_OK)
1445 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1452 * QualifiedNameGetCreationNamespace
1453 * Given a possibly-qualified name for an object (in List-of-Values
1454 * format), determine what namespace the object should be created in.
1455 * Also extract and return the object name (last component of list).
1457 * Note: this does not apply any permissions check. Callers must check
1458 * for CREATE rights on the selected namespace when appropriate.
1460 * Note: calling this may result in a CommandCounterIncrement operation,
1461 * if we have to create or clean out the temp namespace.
1464 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1469 /* deconstruct the name list */
1470 DeconstructQualifiedName(names, &schemaname, objname_p);
1474 /* check for pg_temp alias */
1475 if (strcmp(schemaname, "pg_temp") == 0)
1477 /* Initialize temp namespace if first time through */
1478 if (!OidIsValid(myTempNamespace))
1479 InitTempTableNamespace();
1480 return myTempNamespace;
1482 /* use exact schema given */
1483 namespaceId = GetSysCacheOid(NAMESPACENAME,
1484 CStringGetDatum(schemaname),
1486 if (!OidIsValid(namespaceId))
1488 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1489 errmsg("schema \"%s\" does not exist", schemaname)));
1490 /* we do not check for USAGE rights here! */
1494 /* use the default creation namespace */
1495 recomputeNamespacePath();
1496 if (activeTempCreationPending)
1498 /* Need to initialize temp namespace */
1499 InitTempTableNamespace();
1500 return myTempNamespace;
1502 namespaceId = activeCreationNamespace;
1503 if (!OidIsValid(namespaceId))
1505 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1506 errmsg("no schema has been selected to create in")));
1513 * makeRangeVarFromNameList
1514 * Utility routine to convert a qualified-name list into RangeVar form.
1517 makeRangeVarFromNameList(List *names)
1519 RangeVar *rel = makeRangeVar(NULL, NULL);
1521 switch (list_length(names))
1524 rel->relname = strVal(linitial(names));
1527 rel->schemaname = strVal(linitial(names));
1528 rel->relname = strVal(lsecond(names));
1531 rel->catalogname = strVal(linitial(names));
1532 rel->schemaname = strVal(lsecond(names));
1533 rel->relname = strVal(lthird(names));
1537 (errcode(ERRCODE_SYNTAX_ERROR),
1538 errmsg("improper relation name (too many dotted names): %s",
1539 NameListToString(names))));
1548 * Utility routine to convert a qualified-name list into a string.
1550 * This is used primarily to form error messages, and so we do not quote
1551 * the list elements, for the sake of legibility.
1554 NameListToString(List *names)
1556 StringInfoData string;
1559 initStringInfo(&string);
1563 if (l != list_head(names))
1564 appendStringInfoChar(&string, '.');
1565 appendStringInfoString(&string, strVal(lfirst(l)));
1572 * NameListToQuotedString
1573 * Utility routine to convert a qualified-name list into a string.
1575 * Same as above except that names will be double-quoted where necessary,
1576 * so the string could be re-parsed (eg, by textToQualifiedNameList).
1579 NameListToQuotedString(List *names)
1581 StringInfoData string;
1584 initStringInfo(&string);
1588 if (l != list_head(names))
1589 appendStringInfoChar(&string, '.');
1590 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
1597 * isTempNamespace - is the given namespace my temporary-table namespace?
1600 isTempNamespace(Oid namespaceId)
1602 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1608 * isTempToastNamespace - is the given namespace my temporary-toast-table
1612 isTempToastNamespace(Oid namespaceId)
1614 if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
1620 * isTempOrToastNamespace - is the given namespace my temporary-table
1621 * namespace or my temporary-toast-table namespace?
1624 isTempOrToastNamespace(Oid namespaceId)
1626 if (OidIsValid(myTempNamespace) &&
1627 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
1633 * isAnyTempNamespace - is the given namespace a temporary-table namespace
1634 * (either my own, or another backend's)? Temporary-toast-table namespaces
1635 * are included, too.
1638 isAnyTempNamespace(Oid namespaceId)
1643 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
1644 nspname = get_namespace_name(namespaceId);
1646 return false; /* no such namespace? */
1647 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
1648 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
1654 * isOtherTempNamespace - is the given namespace some other backend's
1655 * temporary-table namespace (including temporary-toast-table namespaces)?
1658 isOtherTempNamespace(Oid namespaceId)
1660 /* If it's my own temp namespace, say "false" */
1661 if (isTempOrToastNamespace(namespaceId))
1663 /* Else, if it's any temp namespace, say "true" */
1664 return isAnyTempNamespace(namespaceId);
1668 * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
1669 * which must already be assigned. (This is only used when creating a toast
1670 * table for a temp table, so we must have already done InitTempTableNamespace)
1673 GetTempToastNamespace(void)
1675 Assert(OidIsValid(myTempToastNamespace));
1676 return myTempToastNamespace;
1681 * GetOverrideSearchPath - fetch current search path definition in form
1682 * used by PushOverrideSearchPath.
1684 * The result structure is allocated in the specified memory context
1685 * (which might or might not be equal to CurrentMemoryContext); but any
1686 * junk created by revalidation calculations will be in CurrentMemoryContext.
1688 OverrideSearchPath *
1689 GetOverrideSearchPath(MemoryContext context)
1691 OverrideSearchPath *result;
1693 MemoryContext oldcxt;
1695 recomputeNamespacePath();
1697 oldcxt = MemoryContextSwitchTo(context);
1699 result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
1700 schemas = list_copy(activeSearchPath);
1701 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
1703 if (linitial_oid(schemas) == myTempNamespace)
1704 result->addTemp = true;
1707 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
1708 result->addCatalog = true;
1710 schemas = list_delete_first(schemas);
1712 result->schemas = schemas;
1714 MemoryContextSwitchTo(oldcxt);
1720 * PushOverrideSearchPath - temporarily override the search path
1722 * We allow nested overrides, hence the push/pop terminology. The GUC
1723 * search_path variable is ignored while an override is active.
1726 PushOverrideSearchPath(OverrideSearchPath *newpath)
1728 OverrideStackEntry *entry;
1731 MemoryContext oldcxt;
1734 * Copy the list for safekeeping, and insert implicitly-searched
1735 * namespaces as needed. This code should track recomputeNamespacePath.
1737 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1739 oidlist = list_copy(newpath->schemas);
1742 * Remember the first member of the explicit list.
1745 firstNS = InvalidOid;
1747 firstNS = linitial_oid(oidlist);
1750 * Add any implicitly-searched namespaces to the list. Note these go on
1751 * the front, not the back; also notice that we do not check USAGE
1752 * permissions for these.
1754 if (newpath->addCatalog)
1755 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
1757 if (newpath->addTemp)
1759 Assert(OidIsValid(myTempNamespace));
1760 oidlist = lcons_oid(myTempNamespace, oidlist);
1764 * Build the new stack entry, then insert it at the head of the list.
1766 entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
1767 entry->searchPath = oidlist;
1768 entry->creationNamespace = firstNS;
1769 entry->nestLevel = GetCurrentTransactionNestLevel();
1771 overrideStack = lcons(entry, overrideStack);
1773 /* And make it active. */
1774 activeSearchPath = entry->searchPath;
1775 activeCreationNamespace = entry->creationNamespace;
1776 activeTempCreationPending = false; /* XXX is this OK? */
1778 MemoryContextSwitchTo(oldcxt);
1782 * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
1784 * Any push during a (sub)transaction will be popped automatically at abort.
1785 * But it's caller error if a push isn't popped in normal control flow.
1788 PopOverrideSearchPath(void)
1790 OverrideStackEntry *entry;
1792 /* Sanity checks. */
1793 if (overrideStack == NIL)
1794 elog(ERROR, "bogus PopOverrideSearchPath call");
1795 entry = (OverrideStackEntry *) linitial(overrideStack);
1796 if (entry->nestLevel != GetCurrentTransactionNestLevel())
1797 elog(ERROR, "bogus PopOverrideSearchPath call");
1799 /* Pop the stack and free storage. */
1800 overrideStack = list_delete_first(overrideStack);
1801 list_free(entry->searchPath);
1804 /* Activate the next level down. */
1807 entry = (OverrideStackEntry *) linitial(overrideStack);
1808 activeSearchPath = entry->searchPath;
1809 activeCreationNamespace = entry->creationNamespace;
1810 activeTempCreationPending = false; /* XXX is this OK? */
1814 /* If not baseSearchPathValid, this is useless but harmless */
1815 activeSearchPath = baseSearchPath;
1816 activeCreationNamespace = baseCreationNamespace;
1817 activeTempCreationPending = baseTempCreationPending;
1823 * FindConversionByName - find a conversion by possibly qualified name
1826 FindConversionByName(List *name)
1829 char *conversion_name;
1834 /* deconstruct the name list */
1835 DeconstructQualifiedName(name, &schemaname, &conversion_name);
1839 /* use exact schema given */
1840 namespaceId = LookupExplicitNamespace(schemaname);
1841 return FindConversion(conversion_name, namespaceId);
1845 /* search for it in search path */
1846 recomputeNamespacePath();
1848 foreach(l, activeSearchPath)
1850 namespaceId = lfirst_oid(l);
1852 if (namespaceId == myTempNamespace)
1853 continue; /* do not look in temp namespace */
1855 conoid = FindConversion(conversion_name, namespaceId);
1856 if (OidIsValid(conoid))
1861 /* Not found in path */
1866 * FindDefaultConversionProc - find default encoding conversion proc
1869 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
1874 recomputeNamespacePath();
1876 foreach(l, activeSearchPath)
1878 Oid namespaceId = lfirst_oid(l);
1880 if (namespaceId == myTempNamespace)
1881 continue; /* do not look in temp namespace */
1883 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
1884 if (OidIsValid(proc))
1888 /* Not found in path */
1893 * recomputeNamespacePath - recompute path derived variables if needed.
1896 recomputeNamespacePath(void)
1898 Oid roleid = GetUserId();
1906 MemoryContext oldcxt;
1908 /* Do nothing if an override search spec is active. */
1912 /* Do nothing if path is already valid. */
1913 if (baseSearchPathValid && namespaceUser == roleid)
1916 /* Need a modifiable copy of namespace_search_path string */
1917 rawname = pstrdup(namespace_search_path);
1919 /* Parse string into list of identifiers */
1920 if (!SplitIdentifierString(rawname, ',', &namelist))
1922 /* syntax error in name list */
1923 /* this should not happen if GUC checked check_search_path */
1924 elog(ERROR, "invalid list syntax");
1928 * Convert the list of names to a list of OIDs. If any names are not
1929 * recognizable or we don't have read access, just leave them out of the
1930 * list. (We can't raise an error, since the search_path setting has
1931 * already been accepted.) Don't make duplicate entries, either.
1934 temp_missing = false;
1935 foreach(l, namelist)
1937 char *curname = (char *) lfirst(l);
1940 if (strcmp(curname, "$user") == 0)
1942 /* $user --- substitute namespace matching user name, if any */
1945 tuple = SearchSysCache(AUTHOID,
1946 ObjectIdGetDatum(roleid),
1948 if (HeapTupleIsValid(tuple))
1952 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
1953 namespaceId = GetSysCacheOid(NAMESPACENAME,
1954 CStringGetDatum(rname),
1956 ReleaseSysCache(tuple);
1957 if (OidIsValid(namespaceId) &&
1958 !list_member_oid(oidlist, namespaceId) &&
1959 pg_namespace_aclcheck(namespaceId, roleid,
1960 ACL_USAGE) == ACLCHECK_OK)
1961 oidlist = lappend_oid(oidlist, namespaceId);
1964 else if (strcmp(curname, "pg_temp") == 0)
1966 /* pg_temp --- substitute temp namespace, if any */
1967 if (OidIsValid(myTempNamespace))
1969 if (!list_member_oid(oidlist, myTempNamespace))
1970 oidlist = lappend_oid(oidlist, myTempNamespace);
1974 /* If it ought to be the creation namespace, set flag */
1976 temp_missing = true;
1981 /* normal namespace reference */
1982 namespaceId = GetSysCacheOid(NAMESPACENAME,
1983 CStringGetDatum(curname),
1985 if (OidIsValid(namespaceId) &&
1986 !list_member_oid(oidlist, namespaceId) &&
1987 pg_namespace_aclcheck(namespaceId, roleid,
1988 ACL_USAGE) == ACLCHECK_OK)
1989 oidlist = lappend_oid(oidlist, namespaceId);
1994 * Remember the first member of the explicit list. (Note: this is
1995 * nominally wrong if temp_missing, but we need it anyway to distinguish
1996 * explicit from implicit mention of pg_catalog.)
1999 firstNS = InvalidOid;
2001 firstNS = linitial_oid(oidlist);
2004 * Add any implicitly-searched namespaces to the list. Note these go on
2005 * the front, not the back; also notice that we do not check USAGE
2006 * permissions for these.
2008 if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
2009 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2011 if (OidIsValid(myTempNamespace) &&
2012 !list_member_oid(oidlist, myTempNamespace))
2013 oidlist = lcons_oid(myTempNamespace, oidlist);
2016 * Now that we've successfully built the new list of namespace OIDs, save
2017 * it in permanent storage.
2019 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2020 newpath = list_copy(oidlist);
2021 MemoryContextSwitchTo(oldcxt);
2023 /* Now safe to assign to state variables. */
2024 list_free(baseSearchPath);
2025 baseSearchPath = newpath;
2026 baseCreationNamespace = firstNS;
2027 baseTempCreationPending = temp_missing;
2029 /* Mark the path valid. */
2030 baseSearchPathValid = true;
2031 namespaceUser = roleid;
2033 /* And make it active. */
2034 activeSearchPath = baseSearchPath;
2035 activeCreationNamespace = baseCreationNamespace;
2036 activeTempCreationPending = baseTempCreationPending;
2040 list_free(namelist);
2045 * InitTempTableNamespace
2046 * Initialize temp table namespace on first use in a particular backend
2049 InitTempTableNamespace(void)
2051 char namespaceName[NAMEDATALEN];
2055 Assert(!OidIsValid(myTempNamespace));
2058 * First, do permission check to see if we are authorized to make temp
2059 * tables. We use a nonstandard error message here since "databasename:
2060 * permission denied" might be a tad cryptic.
2062 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
2063 * that's necessary since current user ID could change during the session.
2064 * But there's no need to make the namespace in the first place until a
2065 * temp table creation request is made by someone with appropriate rights.
2067 if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
2068 ACL_CREATE_TEMP) != ACLCHECK_OK)
2070 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2071 errmsg("permission denied to create temporary tables in database \"%s\"",
2072 get_database_name(MyDatabaseId))));
2074 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
2076 namespaceId = GetSysCacheOid(NAMESPACENAME,
2077 CStringGetDatum(namespaceName),
2079 if (!OidIsValid(namespaceId))
2082 * First use of this temp namespace in this database; create it. The
2083 * temp namespaces are always owned by the superuser. We leave their
2084 * permissions at default --- i.e., no access except to superuser ---
2085 * to ensure that unprivileged users can't peek at other backends'
2086 * temp tables. This works because the places that access the temp
2087 * namespace for my own backend skip permissions checks on it.
2089 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2090 /* Advance command counter to make namespace visible */
2091 CommandCounterIncrement();
2096 * If the namespace already exists, clean it out (in case the former
2097 * owner crashed without doing so).
2099 RemoveTempRelations(namespaceId);
2103 * If the corresponding temp-table namespace doesn't exist yet, create it.
2104 * (We assume there is no need to clean it out if it does exist, since
2105 * dropping a parent table should make its toast table go away.)
2107 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
2110 toastspaceId = GetSysCacheOid(NAMESPACENAME,
2111 CStringGetDatum(namespaceName),
2113 if (!OidIsValid(toastspaceId))
2115 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2116 /* Advance command counter to make namespace visible */
2117 CommandCounterIncrement();
2121 * Okay, we've prepared the temp namespace ... but it's not committed yet,
2122 * so all our work could be undone by transaction rollback. Set flag for
2123 * AtEOXact_Namespace to know what to do.
2125 myTempNamespace = namespaceId;
2126 myTempToastNamespace = toastspaceId;
2128 /* It should not be done already. */
2129 AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
2130 myTempNamespaceSubID = GetCurrentSubTransactionId();
2132 baseSearchPathValid = false; /* need to rebuild list */
2136 * End-of-transaction cleanup for namespaces.
2139 AtEOXact_Namespace(bool isCommit)
2142 * If we abort the transaction in which a temp namespace was selected,
2143 * we'll have to do any creation or cleanout work over again. So, just
2144 * forget the namespace entirely until next time. On the other hand, if
2145 * we commit then register an exit callback to clean out the temp tables
2146 * at backend shutdown. (We only want to register the callback once per
2147 * session, so this is a good place to do it.)
2149 if (myTempNamespaceSubID != InvalidSubTransactionId)
2152 on_shmem_exit(RemoveTempRelationsCallback, 0);
2155 myTempNamespace = InvalidOid;
2156 myTempToastNamespace = InvalidOid;
2157 baseSearchPathValid = false; /* need to rebuild list */
2159 myTempNamespaceSubID = InvalidSubTransactionId;
2163 * Clean up if someone failed to do PopOverrideSearchPath
2168 elog(WARNING, "leaked override search path");
2169 while (overrideStack)
2171 OverrideStackEntry *entry;
2173 entry = (OverrideStackEntry *) linitial(overrideStack);
2174 overrideStack = list_delete_first(overrideStack);
2175 list_free(entry->searchPath);
2178 /* If not baseSearchPathValid, this is useless but harmless */
2179 activeSearchPath = baseSearchPath;
2180 activeCreationNamespace = baseCreationNamespace;
2181 activeTempCreationPending = baseTempCreationPending;
2186 * AtEOSubXact_Namespace
2188 * At subtransaction commit, propagate the temp-namespace-creation
2189 * flag to the parent subtransaction.
2191 * At subtransaction abort, forget the flag if we set it up.
2194 AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
2195 SubTransactionId parentSubid)
2197 OverrideStackEntry *entry;
2199 if (myTempNamespaceSubID == mySubid)
2202 myTempNamespaceSubID = parentSubid;
2205 myTempNamespaceSubID = InvalidSubTransactionId;
2206 /* TEMP namespace creation failed, so reset state */
2207 myTempNamespace = InvalidOid;
2208 myTempToastNamespace = InvalidOid;
2209 baseSearchPathValid = false; /* need to rebuild list */
2214 * Clean up if someone failed to do PopOverrideSearchPath
2216 while (overrideStack)
2218 entry = (OverrideStackEntry *) linitial(overrideStack);
2219 if (entry->nestLevel < GetCurrentTransactionNestLevel())
2222 elog(WARNING, "leaked override search path");
2223 overrideStack = list_delete_first(overrideStack);
2224 list_free(entry->searchPath);
2228 /* Activate the next level down. */
2231 entry = (OverrideStackEntry *) linitial(overrideStack);
2232 activeSearchPath = entry->searchPath;
2233 activeCreationNamespace = entry->creationNamespace;
2234 activeTempCreationPending = false; /* XXX is this OK? */
2238 /* If not baseSearchPathValid, this is useless but harmless */
2239 activeSearchPath = baseSearchPath;
2240 activeCreationNamespace = baseCreationNamespace;
2241 activeTempCreationPending = baseTempCreationPending;
2246 * Remove all relations in the specified temp namespace.
2248 * This is called at backend shutdown (if we made any temp relations).
2249 * It is also called when we begin using a pre-existing temp namespace,
2250 * in order to clean out any relations that might have been created by
2251 * a crashed backend.
2254 RemoveTempRelations(Oid tempNamespaceId)
2256 ObjectAddress object;
2259 * We want to get rid of everything in the target namespace, but not the
2260 * namespace itself (deleting it only to recreate it later would be a
2261 * waste of cycles). We do this by finding everything that has a
2262 * dependency on the namespace.
2264 object.classId = NamespaceRelationId;
2265 object.objectId = tempNamespaceId;
2266 object.objectSubId = 0;
2268 deleteWhatDependsOn(&object, false);
2272 * Callback to remove temp relations at backend exit.
2275 RemoveTempRelationsCallback(int code, Datum arg)
2277 if (OidIsValid(myTempNamespace)) /* should always be true */
2279 /* Need to ensure we have a usable transaction. */
2280 AbortOutOfAnyTransaction();
2281 StartTransactionCommand();
2283 RemoveTempRelations(myTempNamespace);
2285 CommitTransactionCommand();
2290 * Remove all temp tables from the temporary namespace.
2293 ResetTempTableNamespace(void)
2295 if (OidIsValid(myTempNamespace))
2296 RemoveTempRelations(myTempNamespace);
2301 * Routines for handling the GUC variable 'search_path'.
2304 /* assign_hook: validate new search_path, do extra actions as needed */
2306 assign_search_path(const char *newval, bool doit, GucSource source)
2312 /* Need a modifiable copy of string */
2313 rawname = pstrdup(newval);
2315 /* Parse string into list of identifiers */
2316 if (!SplitIdentifierString(rawname, ',', &namelist))
2318 /* syntax error in name list */
2320 list_free(namelist);
2325 * If we aren't inside a transaction, we cannot do database access so
2326 * cannot verify the individual names. Must accept the list on faith.
2328 if (source >= PGC_S_INTERACTIVE && IsTransactionState())
2331 * Verify that all the names are either valid namespace names or
2332 * "$user" or "pg_temp". We do not require $user to correspond to a
2333 * valid namespace, and pg_temp might not exist yet. We do not check
2334 * for USAGE rights, either; should we?
2336 * When source == PGC_S_TEST, we are checking the argument of an ALTER
2337 * DATABASE SET or ALTER USER SET command. It could be that the
2338 * intended use of the search path is for some other database, so we
2339 * should not error out if it mentions schemas not present in the
2340 * current database. We reduce the message to NOTICE instead.
2342 foreach(l, namelist)
2344 char *curname = (char *) lfirst(l);
2346 if (strcmp(curname, "$user") == 0)
2348 if (strcmp(curname, "pg_temp") == 0)
2350 if (!SearchSysCacheExists(NAMESPACENAME,
2351 CStringGetDatum(curname),
2353 ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
2354 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2355 errmsg("schema \"%s\" does not exist", curname)));
2360 list_free(namelist);
2363 * We mark the path as needing recomputation, but don't do anything until
2364 * it's needed. This avoids trying to do database access during GUC
2368 baseSearchPathValid = false;
2374 * InitializeSearchPath: initialize module during InitPostgres.
2376 * This is called after we are up enough to be able to do catalog lookups.
2379 InitializeSearchPath(void)
2381 if (IsBootstrapProcessingMode())
2384 * In bootstrap mode, the search path must be 'pg_catalog' so that
2385 * tables are created in the proper namespace; ignore the GUC setting.
2387 MemoryContext oldcxt;
2389 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2390 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
2391 MemoryContextSwitchTo(oldcxt);
2392 baseCreationNamespace = PG_CATALOG_NAMESPACE;
2393 baseTempCreationPending = false;
2394 baseSearchPathValid = true;
2395 namespaceUser = GetUserId();
2396 activeSearchPath = baseSearchPath;
2397 activeCreationNamespace = baseCreationNamespace;
2398 activeTempCreationPending = baseTempCreationPending;
2403 * In normal mode, arrange for a callback on any syscache invalidation
2404 * of pg_namespace rows.
2406 CacheRegisterSyscacheCallback(NAMESPACEOID,
2409 /* Force search path to be recomputed on next use */
2410 baseSearchPathValid = false;
2416 * Syscache inval callback function
2419 NamespaceCallback(Datum arg, Oid relid)
2421 /* Force search path to be recomputed on next use */
2422 baseSearchPathValid = false;
2426 * Fetch the active search path. The return value is a palloc'ed list
2427 * of OIDs; the caller is responsible for freeing this storage as
2430 * The returned list includes the implicitly-prepended namespaces only if
2431 * includeImplicit is true.
2433 * Note: calling this may result in a CommandCounterIncrement operation,
2434 * if we have to create or clean out the temp namespace.
2437 fetch_search_path(bool includeImplicit)
2441 recomputeNamespacePath();
2444 * If the temp namespace should be first, force it to exist. This is
2445 * so that callers can trust the result to reflect the actual default
2446 * creation namespace. It's a bit bogus to do this here, since
2447 * current_schema() is supposedly a stable function without side-effects,
2448 * but the alternatives seem worse.
2450 if (activeTempCreationPending)
2452 InitTempTableNamespace();
2453 recomputeNamespacePath();
2456 result = list_copy(activeSearchPath);
2457 if (!includeImplicit)
2459 while (result && linitial_oid(result) != activeCreationNamespace)
2460 result = list_delete_first(result);
2467 * Export the FooIsVisible functions as SQL-callable functions.
2471 pg_table_is_visible(PG_FUNCTION_ARGS)
2473 Oid oid = PG_GETARG_OID(0);
2475 PG_RETURN_BOOL(RelationIsVisible(oid));
2479 pg_type_is_visible(PG_FUNCTION_ARGS)
2481 Oid oid = PG_GETARG_OID(0);
2483 PG_RETURN_BOOL(TypeIsVisible(oid));
2487 pg_function_is_visible(PG_FUNCTION_ARGS)
2489 Oid oid = PG_GETARG_OID(0);
2491 PG_RETURN_BOOL(FunctionIsVisible(oid));
2495 pg_operator_is_visible(PG_FUNCTION_ARGS)
2497 Oid oid = PG_GETARG_OID(0);
2499 PG_RETURN_BOOL(OperatorIsVisible(oid));
2503 pg_opclass_is_visible(PG_FUNCTION_ARGS)
2505 Oid oid = PG_GETARG_OID(0);
2507 PG_RETURN_BOOL(OpclassIsVisible(oid));
2511 pg_conversion_is_visible(PG_FUNCTION_ARGS)
2513 Oid oid = PG_GETARG_OID(0);
2515 PG_RETURN_BOOL(ConversionIsVisible(oid));
2519 pg_my_temp_schema(PG_FUNCTION_ARGS)
2521 PG_RETURN_OID(myTempNamespace);
2525 pg_is_other_temp_schema(PG_FUNCTION_ARGS)
2527 Oid oid = PG_GETARG_OID(0);
2529 PG_RETURN_BOOL(isOtherTempNamespace(oid));