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-2003, 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.60 2003/12/12 18:45:08 petere Exp $
18 *-------------------------------------------------------------------------
22 #include "access/xact.h"
23 #include "catalog/catname.h"
24 #include "catalog/dependency.h"
25 #include "catalog/namespace.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_proc.h"
31 #include "catalog/pg_shadow.h"
32 #include "catalog/pg_type.h"
33 #include "commands/dbcommands.h"
34 #include "lib/stringinfo.h"
35 #include "miscadmin.h"
36 #include "nodes/makefuncs.h"
37 #include "storage/backendid.h"
38 #include "storage/ipc.h"
39 #include "utils/acl.h"
40 #include "utils/builtins.h"
41 #include "utils/catcache.h"
42 #include "utils/inval.h"
43 #include "utils/lsyscache.h"
44 #include "utils/memutils.h"
45 #include "utils/syscache.h"
49 * The namespace search path is a possibly-empty list of namespace OIDs.
50 * In addition to the explicit list, several implicitly-searched namespaces
53 * 1. If a "special" namespace has been set by PushSpecialNamespace, it is
54 * always searched first. (This is a hack for CREATE SCHEMA.)
56 * 2. If a TEMP table namespace has been initialized in this session, it
57 * is always searched just after any special namespace.
59 * 3. The system catalog namespace is always searched. If the system
60 * namespace is present in the explicit path then it will be searched in
61 * the specified order; otherwise it will be searched after TEMP tables and
62 * *before* the explicit list. (It might seem that the system namespace
63 * should be implicitly last, but this behavior appears to be required by
64 * SQL99. Also, this provides a way to search the system namespace first
65 * without thereby making it the default creation target namespace.)
67 * The default creation target namespace is normally equal to the first
68 * element of the explicit list, but is the "special" namespace when one
69 * has been set. If the explicit list is empty and there is no special
70 * namespace, there is no default target.
72 * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
73 * the system namespace is the only one searched or inserted into.
74 * The initdb script is also careful to set search_path to 'pg_catalog' for
75 * its post-bootstrap standalone backend runs. Otherwise the default search
76 * path is determined by GUC. The factory default path contains the PUBLIC
77 * namespace (if it exists), preceded by the user's personal namespace
80 * If namespaceSearchPathValid is false, then namespaceSearchPath (and other
81 * derived variables) need to be recomputed from namespace_search_path.
82 * We mark it invalid upon an assignment to namespace_search_path or receipt
83 * of a syscache invalidation event for pg_namespace. The recomputation
84 * is done during the next lookup attempt.
86 * Any namespaces mentioned in namespace_search_path that are not readable
87 * by the current user ID are simply left out of namespaceSearchPath; so
88 * we have to be willing to recompute the path when current userid changes.
89 * namespaceUser is the userid the path has been computed for.
92 static List *namespaceSearchPath = NIL;
94 static Oid namespaceUser = InvalidOid;
96 /* default place to create stuff; if InvalidOid, no default */
97 static Oid defaultCreationNamespace = InvalidOid;
99 /* first explicit member of list; usually same as defaultCreationNamespace */
100 static Oid firstExplicitNamespace = InvalidOid;
102 /* The above four values are valid only if namespaceSearchPathValid */
103 static bool namespaceSearchPathValid = true;
106 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
107 * in a particular backend session (this happens when a CREATE TEMP TABLE
108 * command is first executed). Thereafter it's the OID of the temp namespace.
109 * firstTempTransaction flags whether we've committed creation of the TEMP
112 static Oid myTempNamespace = InvalidOid;
114 static bool firstTempTransaction = false;
117 * "Special" namespace for CREATE SCHEMA. If set, it's the first search
118 * path element, and also the default creation namespace.
120 static Oid mySpecialNamespace = InvalidOid;
123 * This is the text equivalent of the search path --- it's the value
124 * of the GUC variable 'search_path'.
126 char *namespace_search_path = NULL;
129 /* Local functions */
130 static void recomputeNamespacePath(void);
131 static void InitTempTableNamespace(void);
132 static void RemoveTempRelations(Oid tempNamespaceId);
133 static void RemoveTempRelationsCallback(int code, Datum arg);
134 static void NamespaceCallback(Datum arg, Oid relid);
136 /* These don't really need to appear in any header file */
137 Datum pg_table_is_visible(PG_FUNCTION_ARGS);
138 Datum pg_type_is_visible(PG_FUNCTION_ARGS);
139 Datum pg_function_is_visible(PG_FUNCTION_ARGS);
140 Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
141 Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
142 Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
147 * Given a RangeVar describing an existing relation,
148 * select the proper namespace and look up the relation OID.
150 * If the relation is not found, return InvalidOid if failOK = true,
151 * otherwise raise an error.
154 RangeVarGetRelid(const RangeVar *relation, bool failOK)
160 * We check the catalog name and then ignore it.
162 if (relation->catalogname)
164 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
166 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
167 errmsg("cross-database references are not implemented")));
170 if (relation->schemaname)
172 /* use exact schema given */
173 namespaceId = LookupExplicitNamespace(relation->schemaname);
174 relId = get_relname_relid(relation->relname, namespaceId);
178 /* search the namespace path */
179 relId = RelnameGetRelid(relation->relname);
182 if (!OidIsValid(relId) && !failOK)
184 if (relation->schemaname)
186 (errcode(ERRCODE_UNDEFINED_TABLE),
187 errmsg("relation \"%s.%s\" does not exist",
188 relation->schemaname, relation->relname)));
191 (errcode(ERRCODE_UNDEFINED_TABLE),
192 errmsg("relation \"%s\" does not exist",
193 relation->relname)));
199 * RangeVarGetCreationNamespace
200 * Given a RangeVar describing a to-be-created relation,
201 * choose which namespace to create it in.
203 * Note: calling this may result in a CommandCounterIncrement operation.
204 * That will happen on the first request for a temp table in any particular
205 * backend run; we will need to either create or clean out the temp schema.
208 RangeVarGetCreationNamespace(const RangeVar *newRelation)
213 * We check the catalog name and then ignore it.
215 if (newRelation->catalogname)
217 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
219 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
220 errmsg("cross-database references are not implemented")));
223 if (newRelation->istemp)
225 /* TEMP tables are created in our backend-local temp namespace */
226 if (newRelation->schemaname)
228 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
229 errmsg("temporary tables may not specify a schema name")));
230 /* Initialize temp namespace if first time through */
231 if (!OidIsValid(myTempNamespace))
232 InitTempTableNamespace();
233 return myTempNamespace;
236 if (newRelation->schemaname)
238 /* use exact schema given */
239 namespaceId = GetSysCacheOid(NAMESPACENAME,
240 CStringGetDatum(newRelation->schemaname),
242 if (!OidIsValid(namespaceId))
244 (errcode(ERRCODE_UNDEFINED_SCHEMA),
245 errmsg("schema \"%s\" does not exist",
246 newRelation->schemaname)));
247 /* we do not check for USAGE rights here! */
251 /* use the default creation namespace */
252 recomputeNamespacePath();
253 namespaceId = defaultCreationNamespace;
254 if (!OidIsValid(namespaceId))
256 (errcode(ERRCODE_UNDEFINED_SCHEMA),
257 errmsg("no schema has been selected to create in")));
260 /* Note: callers will check for CREATE rights when appropriate */
267 * Try to resolve an unqualified relation name.
268 * Returns OID if relation found in search path, else InvalidOid.
271 RelnameGetRelid(const char *relname)
276 recomputeNamespacePath();
278 foreach(lptr, namespaceSearchPath)
280 Oid namespaceId = lfirsto(lptr);
282 relid = get_relname_relid(relname, namespaceId);
283 if (OidIsValid(relid))
287 /* Not found in path */
294 * Determine whether a relation (identified by OID) is visible in the
295 * current search path. Visible means "would be found by searching
296 * for the unqualified relation name".
299 RelationIsVisible(Oid relid)
302 Form_pg_class relform;
306 reltup = SearchSysCache(RELOID,
307 ObjectIdGetDatum(relid),
309 if (!HeapTupleIsValid(reltup))
310 elog(ERROR, "cache lookup failed for relation %u", relid);
311 relform = (Form_pg_class) GETSTRUCT(reltup);
313 recomputeNamespacePath();
316 * Quick check: if it ain't in the path at all, it ain't visible.
317 * Items in the system namespace are surely in the path and so we
318 * needn't even do oidMember() for them.
320 relnamespace = relform->relnamespace;
321 if (relnamespace != PG_CATALOG_NAMESPACE &&
322 !oidMember(relnamespace, namespaceSearchPath))
327 * If it is in the path, it might still not be visible; it could
328 * be hidden by another relation of the same name earlier in the
329 * path. So we must do a slow check to see if this rel would be
330 * found by RelnameGetRelid.
332 char *relname = NameStr(relform->relname);
334 visible = (RelnameGetRelid(relname) == relid);
337 ReleaseSysCache(reltup);
345 * Try to resolve an unqualified datatype name.
346 * Returns OID if type found in search path, else InvalidOid.
348 * This is essentially the same as RelnameGetRelid.
351 TypenameGetTypid(const char *typname)
356 recomputeNamespacePath();
358 foreach(lptr, namespaceSearchPath)
360 Oid namespaceId = lfirsto(lptr);
362 typid = GetSysCacheOid(TYPENAMENSP,
363 PointerGetDatum(typname),
364 ObjectIdGetDatum(namespaceId),
366 if (OidIsValid(typid))
370 /* Not found in path */
376 * Determine whether a type (identified by OID) is visible in the
377 * current search path. Visible means "would be found by searching
378 * for the unqualified type name".
381 TypeIsVisible(Oid typid)
384 Form_pg_type typform;
388 typtup = SearchSysCache(TYPEOID,
389 ObjectIdGetDatum(typid),
391 if (!HeapTupleIsValid(typtup))
392 elog(ERROR, "cache lookup failed for type %u", typid);
393 typform = (Form_pg_type) GETSTRUCT(typtup);
395 recomputeNamespacePath();
398 * Quick check: if it ain't in the path at all, it ain't visible.
399 * Items in the system namespace are surely in the path and so we
400 * needn't even do oidMember() for them.
402 typnamespace = typform->typnamespace;
403 if (typnamespace != PG_CATALOG_NAMESPACE &&
404 !oidMember(typnamespace, namespaceSearchPath))
409 * If it is in the path, it might still not be visible; it could
410 * be hidden by another type of the same name earlier in the path.
411 * So we must do a slow check to see if this type would be found
412 * by TypenameGetTypid.
414 char *typname = NameStr(typform->typname);
416 visible = (TypenameGetTypid(typname) == typid);
419 ReleaseSysCache(typtup);
426 * FuncnameGetCandidates
427 * Given a possibly-qualified function name and argument count,
428 * retrieve a list of the possible matches.
430 * If nargs is -1, we return all functions matching the given name,
431 * regardless of argument count.
433 * We search a single namespace if the function name is qualified, else
434 * all namespaces in the search path. The return list will never contain
435 * multiple entries with identical argument lists --- in the multiple-
436 * namespace case, we arrange for entries in earlier namespaces to mask
437 * identical entries in later namespaces.
440 FuncnameGetCandidates(List *names, int nargs)
442 FuncCandidateList resultList = NULL;
449 /* deconstruct the name list */
450 DeconstructQualifiedName(names, &schemaname, &funcname);
454 /* use exact schema given */
455 namespaceId = LookupExplicitNamespace(schemaname);
459 /* flag to indicate we need namespace search */
460 namespaceId = InvalidOid;
461 recomputeNamespacePath();
464 /* Search syscache by name and (optionally) nargs only */
466 catlist = SearchSysCacheList(PROCNAMENSP, 2,
467 CStringGetDatum(funcname),
468 Int16GetDatum(nargs),
471 catlist = SearchSysCacheList(PROCNAMENSP, 1,
472 CStringGetDatum(funcname),
475 for (i = 0; i < catlist->n_members; i++)
477 HeapTuple proctup = &catlist->members[i]->tuple;
478 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
480 FuncCandidateList newResult;
482 nargs = procform->pronargs;
484 if (OidIsValid(namespaceId))
486 /* Consider only procs in specified namespace */
487 if (procform->pronamespace != namespaceId)
489 /* No need to check args, they must all be different */
493 /* Consider only procs that are in the search path */
496 foreach(nsp, namespaceSearchPath)
498 if (procform->pronamespace == lfirsto(nsp))
503 continue; /* proc is not in search path */
506 * Okay, it's in the search path, but does it have the same
507 * arguments as something we already accepted? If so, keep
508 * only the one that appears earlier in the search path.
510 * If we have an ordered list from SearchSysCacheList (the normal
511 * case), then any conflicting proc must immediately adjoin
512 * this one in the list, so we only need to look at the newest
513 * result item. If we have an unordered list, we have to scan
514 * the whole result list.
518 FuncCandidateList prevResult;
520 if (catlist->ordered)
522 if (nargs == resultList->nargs &&
523 memcmp(procform->proargtypes, resultList->args,
524 nargs * sizeof(Oid)) == 0)
525 prevResult = resultList;
531 for (prevResult = resultList;
533 prevResult = prevResult->next)
535 if (nargs == prevResult->nargs &&
536 memcmp(procform->proargtypes, prevResult->args,
537 nargs * sizeof(Oid)) == 0)
543 /* We have a match with a previous result */
544 Assert(pathpos != prevResult->pathpos);
545 if (pathpos > prevResult->pathpos)
546 continue; /* keep previous result */
547 /* replace previous result */
548 prevResult->pathpos = pathpos;
549 prevResult->oid = HeapTupleGetOid(proctup);
550 continue; /* args are same, of course */
556 * Okay to add it to result list
558 newResult = (FuncCandidateList)
559 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
560 + nargs * sizeof(Oid));
561 newResult->pathpos = pathpos;
562 newResult->oid = HeapTupleGetOid(proctup);
563 newResult->nargs = nargs;
564 memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
566 newResult->next = resultList;
567 resultList = newResult;
570 ReleaseSysCacheList(catlist);
577 * Determine whether a function (identified by OID) is visible in the
578 * current search path. Visible means "would be found by searching
579 * for the unqualified function name with exact argument matches".
582 FunctionIsVisible(Oid funcid)
585 Form_pg_proc procform;
589 proctup = SearchSysCache(PROCOID,
590 ObjectIdGetDatum(funcid),
592 if (!HeapTupleIsValid(proctup))
593 elog(ERROR, "cache lookup failed for function %u", funcid);
594 procform = (Form_pg_proc) GETSTRUCT(proctup);
596 recomputeNamespacePath();
599 * Quick check: if it ain't in the path at all, it ain't visible.
600 * Items in the system namespace are surely in the path and so we
601 * needn't even do oidMember() for them.
603 pronamespace = procform->pronamespace;
604 if (pronamespace != PG_CATALOG_NAMESPACE &&
605 !oidMember(pronamespace, namespaceSearchPath))
610 * If it is in the path, it might still not be visible; it could
611 * be hidden by another proc of the same name and arguments
612 * earlier in the path. So we must do a slow check to see if this
613 * is the same proc that would be found by FuncnameGetCandidates.
615 char *proname = NameStr(procform->proname);
616 int nargs = procform->pronargs;
617 FuncCandidateList clist;
621 clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
623 for (; clist; clist = clist->next)
625 if (memcmp(clist->args, procform->proargtypes,
626 nargs * sizeof(Oid)) == 0)
628 /* Found the expected entry; is it the right proc? */
629 visible = (clist->oid == funcid);
635 ReleaseSysCache(proctup);
642 * OpernameGetCandidates
643 * Given a possibly-qualified operator name and operator kind,
644 * retrieve a list of the possible matches.
646 * If oprkind is '\0', we return all operators matching the given name,
647 * regardless of arguments.
649 * We search a single namespace if the operator name is qualified, else
650 * all namespaces in the search path. The return list will never contain
651 * multiple entries with identical argument lists --- in the multiple-
652 * namespace case, we arrange for entries in earlier namespaces to mask
653 * identical entries in later namespaces.
655 * The returned items always have two args[] entries --- one or the other
656 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
659 OpernameGetCandidates(List *names, char oprkind)
661 FuncCandidateList resultList = NULL;
668 /* deconstruct the name list */
669 DeconstructQualifiedName(names, &schemaname, &opername);
673 /* use exact schema given */
674 namespaceId = LookupExplicitNamespace(schemaname);
678 /* flag to indicate we need namespace search */
679 namespaceId = InvalidOid;
680 recomputeNamespacePath();
683 /* Search syscache by name only */
684 catlist = SearchSysCacheList(OPERNAMENSP, 1,
685 CStringGetDatum(opername),
688 for (i = 0; i < catlist->n_members; i++)
690 HeapTuple opertup = &catlist->members[i]->tuple;
691 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
693 FuncCandidateList newResult;
695 /* Ignore operators of wrong kind, if specific kind requested */
696 if (oprkind && operform->oprkind != oprkind)
699 if (OidIsValid(namespaceId))
701 /* Consider only opers in specified namespace */
702 if (operform->oprnamespace != namespaceId)
704 /* No need to check args, they must all be different */
708 /* Consider only opers that are in the search path */
711 foreach(nsp, namespaceSearchPath)
713 if (operform->oprnamespace == lfirsto(nsp))
718 continue; /* oper is not in search path */
721 * Okay, it's in the search path, but does it have the same
722 * arguments as something we already accepted? If so, keep
723 * only the one that appears earlier in the search path.
725 * If we have an ordered list from SearchSysCacheList (the normal
726 * case), then any conflicting oper must immediately adjoin
727 * this one in the list, so we only need to look at the newest
728 * result item. If we have an unordered list, we have to scan
729 * the whole result list.
733 FuncCandidateList prevResult;
735 if (catlist->ordered)
737 if (operform->oprleft == resultList->args[0] &&
738 operform->oprright == resultList->args[1])
739 prevResult = resultList;
745 for (prevResult = resultList;
747 prevResult = prevResult->next)
749 if (operform->oprleft == prevResult->args[0] &&
750 operform->oprright == prevResult->args[1])
756 /* We have a match with a previous result */
757 Assert(pathpos != prevResult->pathpos);
758 if (pathpos > prevResult->pathpos)
759 continue; /* keep previous result */
760 /* replace previous result */
761 prevResult->pathpos = pathpos;
762 prevResult->oid = HeapTupleGetOid(opertup);
763 continue; /* args are same, of course */
769 * Okay to add it to result list
771 newResult = (FuncCandidateList)
772 palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
773 newResult->pathpos = pathpos;
774 newResult->oid = HeapTupleGetOid(opertup);
775 newResult->nargs = 2;
776 newResult->args[0] = operform->oprleft;
777 newResult->args[1] = operform->oprright;
778 newResult->next = resultList;
779 resultList = newResult;
782 ReleaseSysCacheList(catlist);
789 * Determine whether an operator (identified by OID) is visible in the
790 * current search path. Visible means "would be found by searching
791 * for the unqualified operator name with exact argument matches".
794 OperatorIsVisible(Oid oprid)
797 Form_pg_operator oprform;
801 oprtup = SearchSysCache(OPEROID,
802 ObjectIdGetDatum(oprid),
804 if (!HeapTupleIsValid(oprtup))
805 elog(ERROR, "cache lookup failed for operator %u", oprid);
806 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
808 recomputeNamespacePath();
811 * Quick check: if it ain't in the path at all, it ain't visible.
812 * Items in the system namespace are surely in the path and so we
813 * needn't even do oidMember() for them.
815 oprnamespace = oprform->oprnamespace;
816 if (oprnamespace != PG_CATALOG_NAMESPACE &&
817 !oidMember(oprnamespace, namespaceSearchPath))
822 * If it is in the path, it might still not be visible; it could
823 * be hidden by another operator of the same name and arguments
824 * earlier in the path. So we must do a slow check to see if this
825 * is the same operator that would be found by
826 * OpernameGetCandidates.
828 char *oprname = NameStr(oprform->oprname);
829 FuncCandidateList clist;
833 clist = OpernameGetCandidates(makeList1(makeString(oprname)),
836 for (; clist; clist = clist->next)
838 if (clist->args[0] == oprform->oprleft &&
839 clist->args[1] == oprform->oprright)
841 /* Found the expected entry; is it the right op? */
842 visible = (clist->oid == oprid);
848 ReleaseSysCache(oprtup);
855 * OpclassGetCandidates
856 * Given an index access method OID, retrieve a list of all the
857 * opclasses for that AM that are visible in the search path.
859 * NOTE: the opcname_tmp field in the returned structs should not be used
860 * by callers, because it points at syscache entries that we release at
861 * the end of this routine. If any callers needed the name information,
862 * we could pstrdup() the names ... but at present it'd be wasteful.
865 OpclassGetCandidates(Oid amid)
867 OpclassCandidateList resultList = NULL;
871 /* Search syscache by AM OID only */
872 catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
873 ObjectIdGetDatum(amid),
876 recomputeNamespacePath();
878 for (i = 0; i < catlist->n_members; i++)
880 HeapTuple opctup = &catlist->members[i]->tuple;
881 Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
883 OpclassCandidateList newResult;
886 /* Consider only opclasses that are in the search path */
887 foreach(nsp, namespaceSearchPath)
889 if (opcform->opcnamespace == lfirsto(nsp))
894 continue; /* opclass is not in search path */
897 * Okay, it's in the search path, but does it have the same name
898 * as something we already accepted? If so, keep only the one
899 * that appears earlier in the search path.
901 * If we have an ordered list from SearchSysCacheList (the normal
902 * case), then any conflicting opclass must immediately adjoin
903 * this one in the list, so we only need to look at the newest
904 * result item. If we have an unordered list, we have to scan the
909 OpclassCandidateList prevResult;
911 if (catlist->ordered)
913 if (strcmp(NameStr(opcform->opcname),
914 resultList->opcname_tmp) == 0)
915 prevResult = resultList;
921 for (prevResult = resultList;
923 prevResult = prevResult->next)
925 if (strcmp(NameStr(opcform->opcname),
926 prevResult->opcname_tmp) == 0)
932 /* We have a match with a previous result */
933 Assert(pathpos != prevResult->pathpos);
934 if (pathpos > prevResult->pathpos)
935 continue; /* keep previous result */
936 /* replace previous result */
937 prevResult->opcname_tmp = NameStr(opcform->opcname);
938 prevResult->pathpos = pathpos;
939 prevResult->oid = HeapTupleGetOid(opctup);
940 prevResult->opcintype = opcform->opcintype;
941 prevResult->opcdefault = opcform->opcdefault;
942 prevResult->opckeytype = opcform->opckeytype;
948 * Okay to add it to result list
950 newResult = (OpclassCandidateList)
951 palloc(sizeof(struct _OpclassCandidateList));
952 newResult->opcname_tmp = NameStr(opcform->opcname);
953 newResult->pathpos = pathpos;
954 newResult->oid = HeapTupleGetOid(opctup);
955 newResult->opcintype = opcform->opcintype;
956 newResult->opcdefault = opcform->opcdefault;
957 newResult->opckeytype = opcform->opckeytype;
958 newResult->next = resultList;
959 resultList = newResult;
962 ReleaseSysCacheList(catlist);
968 * OpclassnameGetOpcid
969 * Try to resolve an unqualified index opclass name.
970 * Returns OID if opclass found in search path, else InvalidOid.
972 * This is essentially the same as TypenameGetTypid, but we have to have
973 * an extra argument for the index AM OID.
976 OpclassnameGetOpcid(Oid amid, const char *opcname)
981 recomputeNamespacePath();
983 foreach(lptr, namespaceSearchPath)
985 Oid namespaceId = lfirsto(lptr);
987 opcid = GetSysCacheOid(CLAAMNAMENSP,
988 ObjectIdGetDatum(amid),
989 PointerGetDatum(opcname),
990 ObjectIdGetDatum(namespaceId),
992 if (OidIsValid(opcid))
996 /* Not found in path */
1002 * Determine whether an opclass (identified by OID) is visible in the
1003 * current search path. Visible means "would be found by searching
1004 * for the unqualified opclass name".
1007 OpclassIsVisible(Oid opcid)
1010 Form_pg_opclass opcform;
1014 opctup = SearchSysCache(CLAOID,
1015 ObjectIdGetDatum(opcid),
1017 if (!HeapTupleIsValid(opctup))
1018 elog(ERROR, "cache lookup failed for opclass %u", opcid);
1019 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1021 recomputeNamespacePath();
1024 * Quick check: if it ain't in the path at all, it ain't visible.
1025 * Items in the system namespace are surely in the path and so we
1026 * needn't even do oidMember() for them.
1028 opcnamespace = opcform->opcnamespace;
1029 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1030 !oidMember(opcnamespace, namespaceSearchPath))
1035 * If it is in the path, it might still not be visible; it could
1036 * be hidden by another opclass of the same name earlier in the
1037 * path. So we must do a slow check to see if this opclass would
1038 * be found by OpclassnameGetOpcid.
1040 char *opcname = NameStr(opcform->opcname);
1042 visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
1045 ReleaseSysCache(opctup);
1051 * ConversionGetConid
1052 * Try to resolve an unqualified conversion name.
1053 * Returns OID if conversion found in search path, else InvalidOid.
1055 * This is essentially the same as RelnameGetRelid.
1058 ConversionGetConid(const char *conname)
1063 recomputeNamespacePath();
1065 foreach(lptr, namespaceSearchPath)
1067 Oid namespaceId = lfirsto(lptr);
1069 conid = GetSysCacheOid(CONNAMENSP,
1070 PointerGetDatum(conname),
1071 ObjectIdGetDatum(namespaceId),
1073 if (OidIsValid(conid))
1077 /* Not found in path */
1082 * ConversionIsVisible
1083 * Determine whether a conversion (identified by OID) is visible in the
1084 * current search path. Visible means "would be found by searching
1085 * for the unqualified conversion name".
1088 ConversionIsVisible(Oid conid)
1091 Form_pg_conversion conform;
1095 contup = SearchSysCache(CONOID,
1096 ObjectIdGetDatum(conid),
1098 if (!HeapTupleIsValid(contup))
1099 elog(ERROR, "cache lookup failed for conversion %u", conid);
1100 conform = (Form_pg_conversion) GETSTRUCT(contup);
1102 recomputeNamespacePath();
1105 * Quick check: if it ain't in the path at all, it ain't visible.
1106 * Items in the system namespace are surely in the path and so we
1107 * needn't even do oidMember() for them.
1109 connamespace = conform->connamespace;
1110 if (connamespace != PG_CATALOG_NAMESPACE &&
1111 !oidMember(connamespace, namespaceSearchPath))
1116 * If it is in the path, it might still not be visible; it could
1117 * be hidden by another conversion of the same name earlier in the
1118 * path. So we must do a slow check to see if this conversion
1119 * would be found by ConversionGetConid.
1121 char *conname = NameStr(conform->conname);
1123 visible = (ConversionGetConid(conname) == conid);
1126 ReleaseSysCache(contup);
1132 * DeconstructQualifiedName
1133 * Given a possibly-qualified name expressed as a list of String nodes,
1134 * extract the schema name and object name.
1136 * *nspname_p is set to NULL if there is no explicit schema name.
1139 DeconstructQualifiedName(List *names,
1144 char *schemaname = NULL;
1145 char *objname = NULL;
1147 switch (length(names))
1150 objname = strVal(lfirst(names));
1153 schemaname = strVal(lfirst(names));
1154 objname = strVal(lsecond(names));
1157 catalogname = strVal(lfirst(names));
1158 schemaname = strVal(lsecond(names));
1159 objname = strVal(lthird(names));
1162 * We check the catalog name and then ignore it.
1164 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
1166 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1167 errmsg("cross-database references are not implemented")));
1171 (errcode(ERRCODE_SYNTAX_ERROR),
1172 errmsg("improper qualified name (too many dotted names): %s",
1173 NameListToString(names))));
1177 *nspname_p = schemaname;
1178 *objname_p = objname;
1182 * LookupExplicitNamespace
1183 * Process an explicitly-specified schema name: look up the schema
1184 * and verify we have USAGE (lookup) rights in it.
1186 * Returns the namespace OID. Raises ereport if any problem.
1189 LookupExplicitNamespace(const char *nspname)
1192 AclResult aclresult;
1194 namespaceId = GetSysCacheOid(NAMESPACENAME,
1195 CStringGetDatum(nspname),
1197 if (!OidIsValid(namespaceId))
1199 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1200 errmsg("schema \"%s\" does not exist", nspname)));
1202 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
1203 if (aclresult != ACLCHECK_OK)
1204 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1211 * QualifiedNameGetCreationNamespace
1212 * Given a possibly-qualified name for an object (in List-of-Values
1213 * format), determine what namespace the object should be created in.
1214 * Also extract and return the object name (last component of list).
1216 * This is *not* used for tables. Hence, the TEMP table namespace is
1217 * never selected as the creation target.
1220 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1226 /* deconstruct the name list */
1227 DeconstructQualifiedName(names, &schemaname, &objname);
1231 /* use exact schema given */
1232 namespaceId = GetSysCacheOid(NAMESPACENAME,
1233 CStringGetDatum(schemaname),
1235 if (!OidIsValid(namespaceId))
1237 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1238 errmsg("schema \"%s\" does not exist", schemaname)));
1239 /* we do not check for USAGE rights here! */
1243 /* use the default creation namespace */
1244 recomputeNamespacePath();
1245 namespaceId = defaultCreationNamespace;
1246 if (!OidIsValid(namespaceId))
1248 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1249 errmsg("no schema has been selected to create in")));
1252 /* Note: callers will check for CREATE rights when appropriate */
1254 *objname_p = objname;
1259 * makeRangeVarFromNameList
1260 * Utility routine to convert a qualified-name list into RangeVar form.
1263 makeRangeVarFromNameList(List *names)
1265 RangeVar *rel = makeRangeVar(NULL, NULL);
1267 switch (length(names))
1270 rel->relname = strVal(lfirst(names));
1273 rel->schemaname = strVal(lfirst(names));
1274 rel->relname = strVal(lsecond(names));
1277 rel->catalogname = strVal(lfirst(names));
1278 rel->schemaname = strVal(lsecond(names));
1279 rel->relname = strVal(lthird(names));
1283 (errcode(ERRCODE_SYNTAX_ERROR),
1284 errmsg("improper relation name (too many dotted names): %s",
1285 NameListToString(names))));
1294 * Utility routine to convert a qualified-name list into a string.
1296 * This is used primarily to form error messages, and so we do not quote
1297 * the list elements, for the sake of legibility.
1300 NameListToString(List *names)
1302 StringInfoData string;
1305 initStringInfo(&string);
1310 appendStringInfoChar(&string, '.');
1311 appendStringInfoString(&string, strVal(lfirst(l)));
1318 * NameListToQuotedString
1319 * Utility routine to convert a qualified-name list into a string.
1321 * Same as above except that names will be double-quoted where necessary,
1322 * so the string could be re-parsed (eg, by textToQualifiedNameList).
1325 NameListToQuotedString(List *names)
1327 StringInfoData string;
1330 initStringInfo(&string);
1335 appendStringInfoChar(&string, '.');
1336 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
1343 * isTempNamespace - is the given namespace my temporary-table namespace?
1346 isTempNamespace(Oid namespaceId)
1348 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1354 * isOtherTempNamespace - is the given namespace some other backend's
1355 * temporary-table namespace?
1358 isOtherTempNamespace(Oid namespaceId)
1363 /* If it's my own temp namespace, say "false" */
1364 if (isTempNamespace(namespaceId))
1366 /* Else, if the namespace name starts with "pg_temp_", say "true" */
1367 nspname = get_namespace_name(namespaceId);
1369 return false; /* no such namespace? */
1370 result = (strncmp(nspname, "pg_temp_", 8) == 0);
1376 * PushSpecialNamespace - push a "special" namespace onto the front of the
1379 * This is a slightly messy hack intended only for support of CREATE SCHEMA.
1380 * Although the API is defined to allow a stack of pushed namespaces, we
1381 * presently only support one at a time.
1383 * The pushed namespace will be removed from the search path at end of
1384 * transaction, whether commit or abort.
1387 PushSpecialNamespace(Oid namespaceId)
1389 Assert(!OidIsValid(mySpecialNamespace));
1390 mySpecialNamespace = namespaceId;
1391 namespaceSearchPathValid = false;
1395 * PopSpecialNamespace - remove previously pushed special namespace.
1398 PopSpecialNamespace(Oid namespaceId)
1400 Assert(mySpecialNamespace == namespaceId);
1401 mySpecialNamespace = InvalidOid;
1402 namespaceSearchPathValid = false;
1406 * FindConversionByName - find a conversion by possibly qualified name
1409 FindConversionByName(List *name)
1412 char *conversion_name;
1417 /* deconstruct the name list */
1418 DeconstructQualifiedName(name, &schemaname, &conversion_name);
1422 /* use exact schema given */
1423 namespaceId = LookupExplicitNamespace(schemaname);
1424 return FindConversion(conversion_name, namespaceId);
1428 /* search for it in search path */
1429 recomputeNamespacePath();
1431 foreach(lptr, namespaceSearchPath)
1433 namespaceId = lfirsto(lptr);
1434 conoid = FindConversion(conversion_name, namespaceId);
1435 if (OidIsValid(conoid))
1440 /* Not found in path */
1445 * FindDefaultConversionProc - find default encoding conversion proc
1448 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
1453 recomputeNamespacePath();
1455 foreach(lptr, namespaceSearchPath)
1457 Oid namespaceId = lfirsto(lptr);
1459 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
1460 if (OidIsValid(proc))
1464 /* Not found in path */
1469 * recomputeNamespacePath - recompute path derived variables if needed.
1472 recomputeNamespacePath(void)
1474 AclId userId = GetUserId();
1481 MemoryContext oldcxt;
1484 * Do nothing if path is already valid.
1486 if (namespaceSearchPathValid && namespaceUser == userId)
1489 /* Need a modifiable copy of namespace_search_path string */
1490 rawname = pstrdup(namespace_search_path);
1492 /* Parse string into list of identifiers */
1493 if (!SplitIdentifierString(rawname, ',', &namelist))
1495 /* syntax error in name list */
1496 /* this should not happen if GUC checked check_search_path */
1497 elog(ERROR, "invalid list syntax");
1501 * Convert the list of names to a list of OIDs. If any names are not
1502 * recognizable or we don't have read access, just leave them out of
1503 * the list. (We can't raise an error, since the search_path setting
1504 * has already been accepted.) Don't make duplicate entries, either.
1507 foreach(l, namelist)
1509 char *curname = (char *) lfirst(l);
1512 if (strcmp(curname, "$user") == 0)
1514 /* $user --- substitute namespace matching user name, if any */
1517 tuple = SearchSysCache(SHADOWSYSID,
1518 ObjectIdGetDatum(userId),
1520 if (HeapTupleIsValid(tuple))
1524 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1525 namespaceId = GetSysCacheOid(NAMESPACENAME,
1526 CStringGetDatum(uname),
1528 ReleaseSysCache(tuple);
1529 if (OidIsValid(namespaceId) &&
1530 !oidMember(namespaceId, oidlist) &&
1531 pg_namespace_aclcheck(namespaceId, userId,
1532 ACL_USAGE) == ACLCHECK_OK)
1533 oidlist = lappendo(oidlist, namespaceId);
1538 /* normal namespace reference */
1539 namespaceId = GetSysCacheOid(NAMESPACENAME,
1540 CStringGetDatum(curname),
1542 if (OidIsValid(namespaceId) &&
1543 !oidMember(namespaceId, oidlist) &&
1544 pg_namespace_aclcheck(namespaceId, userId,
1545 ACL_USAGE) == ACLCHECK_OK)
1546 oidlist = lappendo(oidlist, namespaceId);
1551 * Remember the first member of the explicit list.
1554 firstNS = InvalidOid;
1556 firstNS = lfirsto(oidlist);
1559 * Add any implicitly-searched namespaces to the list. Note these go
1560 * on the front, not the back; also notice that we do not check USAGE
1561 * permissions for these.
1563 if (!oidMember(PG_CATALOG_NAMESPACE, oidlist))
1564 oidlist = lconso(PG_CATALOG_NAMESPACE, oidlist);
1566 if (OidIsValid(myTempNamespace) &&
1567 !oidMember(myTempNamespace, oidlist))
1568 oidlist = lconso(myTempNamespace, oidlist);
1570 if (OidIsValid(mySpecialNamespace) &&
1571 !oidMember(mySpecialNamespace, oidlist))
1572 oidlist = lconso(mySpecialNamespace, oidlist);
1575 * Now that we've successfully built the new list of namespace OIDs,
1576 * save it in permanent storage.
1578 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1579 newpath = listCopy(oidlist);
1580 MemoryContextSwitchTo(oldcxt);
1582 /* Now safe to assign to state variable. */
1583 freeList(namespaceSearchPath);
1584 namespaceSearchPath = newpath;
1587 * Update info derived from search path.
1589 firstExplicitNamespace = firstNS;
1590 if (OidIsValid(mySpecialNamespace))
1591 defaultCreationNamespace = mySpecialNamespace;
1593 defaultCreationNamespace = firstNS;
1595 /* Mark the path valid. */
1596 namespaceSearchPathValid = true;
1597 namespaceUser = userId;
1606 * InitTempTableNamespace
1607 * Initialize temp table namespace on first use in a particular backend
1610 InitTempTableNamespace(void)
1612 char namespaceName[NAMEDATALEN];
1616 * First, do permission check to see if we are authorized to make temp
1617 * tables. We use a nonstandard error message here since
1618 * "databasename: permission denied" might be a tad cryptic.
1620 * Note we apply the check to the session user, not the currently active
1621 * userid, since we are not going to change our minds about temp table
1622 * availability during the session.
1624 if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
1625 ACL_CREATE_TEMP) != ACLCHECK_OK)
1627 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1628 errmsg("permission denied to create temporary tables in database \"%s\"",
1629 get_database_name(MyDatabaseId))));
1631 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
1633 namespaceId = GetSysCacheOid(NAMESPACENAME,
1634 CStringGetDatum(namespaceName),
1636 if (!OidIsValid(namespaceId))
1639 * First use of this temp namespace in this database; create it.
1640 * The temp namespaces are always owned by the superuser. We
1641 * leave their permissions at default --- i.e., no access except
1642 * to superuser --- to ensure that unprivileged users can't peek
1643 * at other backends' temp tables. This works because the places
1644 * that access the temp namespace for my own backend skip
1645 * permissions checks on it.
1647 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
1648 /* Advance command counter to make namespace visible */
1649 CommandCounterIncrement();
1654 * If the namespace already exists, clean it out (in case the
1655 * former owner crashed without doing so).
1657 RemoveTempRelations(namespaceId);
1661 * Okay, we've prepared the temp namespace ... but it's not committed
1662 * yet, so all our work could be undone by transaction rollback. Set
1663 * flag for AtEOXact_Namespace to know what to do.
1665 myTempNamespace = namespaceId;
1667 firstTempTransaction = true;
1669 namespaceSearchPathValid = false; /* need to rebuild list */
1673 * End-of-transaction cleanup for namespaces.
1676 AtEOXact_Namespace(bool isCommit)
1679 * If we abort the transaction in which a temp namespace was selected,
1680 * we'll have to do any creation or cleanout work over again. So,
1681 * just forget the namespace entirely until next time. On the other
1682 * hand, if we commit then register an exit callback to clean out the
1683 * temp tables at backend shutdown. (We only want to register the
1684 * callback once per session, so this is a good place to do it.)
1686 if (firstTempTransaction)
1689 on_shmem_exit(RemoveTempRelationsCallback, 0);
1692 myTempNamespace = InvalidOid;
1693 namespaceSearchPathValid = false; /* need to rebuild list */
1695 firstTempTransaction = false;
1699 * Clean up if someone failed to do PopSpecialNamespace
1701 if (OidIsValid(mySpecialNamespace))
1703 mySpecialNamespace = InvalidOid;
1704 namespaceSearchPathValid = false; /* need to rebuild list */
1709 * Remove all relations in the specified temp namespace.
1711 * This is called at backend shutdown (if we made any temp relations).
1712 * It is also called when we begin using a pre-existing temp namespace,
1713 * in order to clean out any relations that might have been created by
1714 * a crashed backend.
1717 RemoveTempRelations(Oid tempNamespaceId)
1719 ObjectAddress object;
1722 * We want to get rid of everything in the target namespace, but not
1723 * the namespace itself (deleting it only to recreate it later would
1724 * be a waste of cycles). We do this by finding everything that has a
1725 * dependency on the namespace.
1727 object.classId = get_system_catalog_relid(NamespaceRelationName);
1728 object.objectId = tempNamespaceId;
1729 object.objectSubId = 0;
1731 deleteWhatDependsOn(&object, false);
1735 * Callback to remove temp relations at backend exit.
1738 RemoveTempRelationsCallback(int code, Datum arg)
1740 if (OidIsValid(myTempNamespace)) /* should always be true */
1742 /* Need to ensure we have a usable transaction. */
1743 AbortOutOfAnyTransaction();
1744 StartTransactionCommand();
1746 RemoveTempRelations(myTempNamespace);
1748 CommitTransactionCommand();
1754 * Routines for handling the GUC variable 'search_path'.
1757 /* assign_hook: validate new search_path, do extra actions as needed */
1759 assign_search_path(const char *newval, bool doit, bool interactive)
1765 /* Need a modifiable copy of string */
1766 rawname = pstrdup(newval);
1768 /* Parse string into list of identifiers */
1769 if (!SplitIdentifierString(rawname, ',', &namelist))
1771 /* syntax error in name list */
1778 * If we aren't inside a transaction, we cannot do database access so
1779 * cannot verify the individual names. Must accept the list on faith.
1781 if (interactive && IsTransactionState())
1784 * Verify that all the names are either valid namespace names or
1785 * "$user". We do not require $user to correspond to a valid
1786 * namespace. We do not check for USAGE rights, either; should
1789 foreach(l, namelist)
1791 char *curname = (char *) lfirst(l);
1793 if (strcmp(curname, "$user") == 0)
1795 if (!SearchSysCacheExists(NAMESPACENAME,
1796 CStringGetDatum(curname),
1799 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1800 errmsg("schema \"%s\" does not exist", curname)));
1808 * We mark the path as needing recomputation, but don't do anything
1809 * until it's needed. This avoids trying to do database access during
1810 * GUC initialization.
1813 namespaceSearchPathValid = false;
1819 * InitializeSearchPath: initialize module during InitPostgres.
1821 * This is called after we are up enough to be able to do catalog lookups.
1824 InitializeSearchPath(void)
1826 if (IsBootstrapProcessingMode())
1829 * In bootstrap mode, the search path must be 'pg_catalog' so that
1830 * tables are created in the proper namespace; ignore the GUC
1833 MemoryContext oldcxt;
1835 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1836 namespaceSearchPath = makeListo1(PG_CATALOG_NAMESPACE);
1837 MemoryContextSwitchTo(oldcxt);
1838 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1839 firstExplicitNamespace = PG_CATALOG_NAMESPACE;
1840 namespaceSearchPathValid = true;
1841 namespaceUser = GetUserId();
1846 * In normal mode, arrange for a callback on any syscache
1847 * invalidation of pg_namespace rows.
1849 CacheRegisterSyscacheCallback(NAMESPACEOID,
1852 /* Force search path to be recomputed on next use */
1853 namespaceSearchPathValid = false;
1859 * Syscache inval callback function
1862 NamespaceCallback(Datum arg, Oid relid)
1864 /* Force search path to be recomputed on next use */
1865 namespaceSearchPathValid = false;
1869 * Fetch the active search path, expressed as a List of OIDs.
1871 * The returned list includes the implicitly-prepended namespaces only if
1872 * includeImplicit is true.
1874 * NB: caller must treat the list as read-only!
1877 fetch_search_path(bool includeImplicit)
1881 recomputeNamespacePath();
1883 result = namespaceSearchPath;
1884 if (!includeImplicit)
1886 while (result && lfirsto(result) != firstExplicitNamespace)
1887 result = lnext(result);
1894 * Export the FooIsVisible functions as SQL-callable functions.
1898 pg_table_is_visible(PG_FUNCTION_ARGS)
1900 Oid oid = PG_GETARG_OID(0);
1902 PG_RETURN_BOOL(RelationIsVisible(oid));
1906 pg_type_is_visible(PG_FUNCTION_ARGS)
1908 Oid oid = PG_GETARG_OID(0);
1910 PG_RETURN_BOOL(TypeIsVisible(oid));
1914 pg_function_is_visible(PG_FUNCTION_ARGS)
1916 Oid oid = PG_GETARG_OID(0);
1918 PG_RETURN_BOOL(FunctionIsVisible(oid));
1922 pg_operator_is_visible(PG_FUNCTION_ARGS)
1924 Oid oid = PG_GETARG_OID(0);
1926 PG_RETURN_BOOL(OperatorIsVisible(oid));
1930 pg_opclass_is_visible(PG_FUNCTION_ARGS)
1932 Oid oid = PG_GETARG_OID(0);
1934 PG_RETURN_BOOL(OpclassIsVisible(oid));
1938 pg_conversion_is_visible(PG_FUNCTION_ARGS)
1940 Oid oid = PG_GETARG_OID(0);
1942 PG_RETURN_BOOL(ConversionIsVisible(oid));