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-2008, 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.114 2008/12/15 18:09:40 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_conversion_fn.h"
28 #include "catalog/pg_namespace.h"
29 #include "catalog/pg_opclass.h"
30 #include "catalog/pg_operator.h"
31 #include "catalog/pg_opfamily.h"
32 #include "catalog/pg_proc.h"
33 #include "catalog/pg_ts_config.h"
34 #include "catalog/pg_ts_dict.h"
35 #include "catalog/pg_ts_parser.h"
36 #include "catalog/pg_ts_template.h"
37 #include "catalog/pg_type.h"
38 #include "commands/dbcommands.h"
39 #include "miscadmin.h"
40 #include "nodes/makefuncs.h"
41 #include "parser/parse_func.h"
42 #include "storage/backendid.h"
43 #include "storage/ipc.h"
44 #include "utils/acl.h"
45 #include "utils/builtins.h"
46 #include "utils/guc.h"
47 #include "utils/inval.h"
48 #include "utils/lsyscache.h"
49 #include "utils/memutils.h"
50 #include "utils/rel.h"
51 #include "utils/syscache.h"
55 * The namespace search path is a possibly-empty list of namespace OIDs.
56 * In addition to the explicit list, implicitly-searched namespaces
59 * 1. If a TEMP table namespace has been initialized in this session, it
60 * is implicitly searched first. (The only time this doesn't happen is
61 * when we are obeying an override search path spec that says not to use the
62 * temp namespace, or the temp namespace is included in the explicit list.)
64 * 2. The system catalog namespace is always searched. If the system
65 * namespace is present in the explicit path then it will be searched in
66 * the specified order; otherwise it will be searched after TEMP tables and
67 * *before* the explicit list. (It might seem that the system namespace
68 * should be implicitly last, but this behavior appears to be required by
69 * SQL99. Also, this provides a way to search the system namespace first
70 * without thereby making it the default creation target namespace.)
72 * For security reasons, searches using the search path will ignore the temp
73 * namespace when searching for any object type other than relations and
74 * types. (We must allow types since temp tables have rowtypes.)
76 * The default creation target namespace is always the first element of the
77 * explicit list. If the explicit list is empty, there is no default target.
79 * The textual specification of search_path can include "$user" to refer to
80 * the namespace named the same as the current user, if any. (This is just
81 * ignored if there is no such namespace.) Also, it can include "pg_temp"
82 * to refer to the current backend's temp namespace. This is usually also
83 * ignorable if the temp namespace hasn't been set up, but there's a special
84 * case: if "pg_temp" appears first then it should be the default creation
85 * target. We kluge this case a little bit so that the temp namespace isn't
86 * set up until the first attempt to create something in it. (The reason for
87 * klugery is that we can't create the temp namespace outside a transaction,
88 * but initial GUC processing of search_path happens outside a transaction.)
89 * activeTempCreationPending is TRUE if "pg_temp" appears first in the string
90 * but is not reflected in activeCreationNamespace because the namespace isn't
93 * In bootstrap mode, the search path is set equal to "pg_catalog", so that
94 * the system namespace is the only one searched or inserted into.
95 * initdb is also careful to set search_path to "pg_catalog" for its
96 * post-bootstrap standalone backend runs. Otherwise the default search
97 * path is determined by GUC. The factory default path contains the PUBLIC
98 * namespace (if it exists), preceded by the user's personal namespace
101 * We support a stack of "override" search path settings for use within
102 * specific sections of backend code. namespace_search_path is ignored
103 * whenever the override stack is nonempty. activeSearchPath is always
104 * the actually active path; it points either to the search list of the
105 * topmost stack entry, or to baseSearchPath which is the list derived
106 * from namespace_search_path.
108 * If baseSearchPathValid is false, then baseSearchPath (and other
109 * derived variables) need to be recomputed from namespace_search_path.
110 * We mark it invalid upon an assignment to namespace_search_path or receipt
111 * of a syscache invalidation event for pg_namespace. The recomputation
112 * is done during the next non-overridden lookup attempt. Note that an
113 * override spec is never subject to recomputation.
115 * Any namespaces mentioned in namespace_search_path that are not readable
116 * by the current user ID are simply left out of baseSearchPath; so
117 * we have to be willing to recompute the path when current userid changes.
118 * namespaceUser is the userid the path has been computed for.
120 * Note: all data pointed to by these List variables is in TopMemoryContext.
123 /* These variables define the actually active state: */
125 static List *activeSearchPath = NIL;
127 /* default place to create stuff; if InvalidOid, no default */
128 static Oid activeCreationNamespace = InvalidOid;
130 /* if TRUE, activeCreationNamespace is wrong, it should be temp namespace */
131 static bool activeTempCreationPending = false;
133 /* These variables are the values last derived from namespace_search_path: */
135 static List *baseSearchPath = NIL;
137 static Oid baseCreationNamespace = InvalidOid;
139 static bool baseTempCreationPending = false;
141 static Oid namespaceUser = InvalidOid;
143 /* The above four values are valid only if baseSearchPathValid */
144 static bool baseSearchPathValid = true;
146 /* Override requests are remembered in a stack of OverrideStackEntry structs */
150 List *searchPath; /* the desired search path */
151 Oid creationNamespace; /* the desired creation namespace */
152 int nestLevel; /* subtransaction nesting level */
153 } OverrideStackEntry;
155 static List *overrideStack = NIL;
158 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
159 * in a particular backend session (this happens when a CREATE TEMP TABLE
160 * command is first executed). Thereafter it's the OID of the temp namespace.
162 * myTempToastNamespace is the OID of the namespace for my temp tables' toast
163 * tables. It is set when myTempNamespace is, and is InvalidOid before that.
165 * myTempNamespaceSubID shows whether we've created the TEMP namespace in the
166 * current subtransaction. The flag propagates up the subtransaction tree,
167 * so the main transaction will correctly recognize the flag if all
168 * intermediate subtransactions commit. When it is InvalidSubTransactionId,
169 * we either haven't made the TEMP namespace yet, or have successfully
170 * committed its creation, depending on whether myTempNamespace is valid.
172 static Oid myTempNamespace = InvalidOid;
174 static Oid myTempToastNamespace = InvalidOid;
176 static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
179 * This is the user's textual search path specification --- it's the value
180 * of the GUC variable 'search_path'.
182 char *namespace_search_path = NULL;
185 /* Local functions */
186 static void recomputeNamespacePath(void);
187 static void InitTempTableNamespace(void);
188 static void RemoveTempRelations(Oid tempNamespaceId);
189 static void RemoveTempRelationsCallback(int code, Datum arg);
190 static void NamespaceCallback(Datum arg, int cacheid, ItemPointer tuplePtr);
192 /* These don't really need to appear in any header file */
193 Datum pg_table_is_visible(PG_FUNCTION_ARGS);
194 Datum pg_type_is_visible(PG_FUNCTION_ARGS);
195 Datum pg_function_is_visible(PG_FUNCTION_ARGS);
196 Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
197 Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
198 Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
199 Datum pg_ts_parser_is_visible(PG_FUNCTION_ARGS);
200 Datum pg_ts_dict_is_visible(PG_FUNCTION_ARGS);
201 Datum pg_ts_template_is_visible(PG_FUNCTION_ARGS);
202 Datum pg_ts_config_is_visible(PG_FUNCTION_ARGS);
203 Datum pg_my_temp_schema(PG_FUNCTION_ARGS);
204 Datum pg_is_other_temp_schema(PG_FUNCTION_ARGS);
209 * Given a RangeVar describing an existing relation,
210 * select the proper namespace and look up the relation OID.
212 * If the relation is not found, return InvalidOid if failOK = true,
213 * otherwise raise an error.
216 RangeVarGetRelid(const RangeVar *relation, bool failOK)
222 * We check the catalog name and then ignore it.
224 if (relation->catalogname)
226 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
228 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
229 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
230 relation->catalogname, relation->schemaname,
231 relation->relname)));
235 * If istemp is set, this is a reference to a temp relation. The parser
236 * never generates such a RangeVar in simple DML, but it can happen in
237 * contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY KEY)". Such a
238 * command will generate an added CREATE INDEX operation, which must be
239 * careful to find the temp table, even when pg_temp is not first in the
242 if (relation->istemp)
244 if (relation->schemaname)
246 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
247 errmsg("temporary tables cannot specify a schema name")));
248 if (OidIsValid(myTempNamespace))
249 relId = get_relname_relid(relation->relname, myTempNamespace);
250 else /* this probably can't happen? */
253 else if (relation->schemaname)
255 /* use exact schema given */
256 namespaceId = LookupExplicitNamespace(relation->schemaname);
257 relId = get_relname_relid(relation->relname, namespaceId);
261 /* search the namespace path */
262 relId = RelnameGetRelid(relation->relname);
265 if (!OidIsValid(relId) && !failOK)
267 if (relation->schemaname)
269 (errcode(ERRCODE_UNDEFINED_TABLE),
270 errmsg("relation \"%s.%s\" does not exist",
271 relation->schemaname, relation->relname)));
274 (errcode(ERRCODE_UNDEFINED_TABLE),
275 errmsg("relation \"%s\" does not exist",
276 relation->relname)));
282 * RangeVarGetCreationNamespace
283 * Given a RangeVar describing a to-be-created relation,
284 * choose which namespace to create it in.
286 * Note: calling this may result in a CommandCounterIncrement operation.
287 * That will happen on the first request for a temp table in any particular
288 * backend run; we will need to either create or clean out the temp schema.
291 RangeVarGetCreationNamespace(const RangeVar *newRelation)
296 * We check the catalog name and then ignore it.
298 if (newRelation->catalogname)
300 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
302 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
303 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
304 newRelation->catalogname, newRelation->schemaname,
305 newRelation->relname)));
308 if (newRelation->istemp)
310 /* TEMP tables are created in our backend-local temp namespace */
311 if (newRelation->schemaname)
313 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
314 errmsg("temporary tables cannot specify a schema name")));
315 /* Initialize temp namespace if first time through */
316 if (!OidIsValid(myTempNamespace))
317 InitTempTableNamespace();
318 return myTempNamespace;
321 if (newRelation->schemaname)
323 /* check for pg_temp alias */
324 if (strcmp(newRelation->schemaname, "pg_temp") == 0)
326 /* Initialize temp namespace if first time through */
327 if (!OidIsValid(myTempNamespace))
328 InitTempTableNamespace();
329 return myTempNamespace;
331 /* use exact schema given */
332 namespaceId = GetSysCacheOid(NAMESPACENAME,
333 CStringGetDatum(newRelation->schemaname),
335 if (!OidIsValid(namespaceId))
337 (errcode(ERRCODE_UNDEFINED_SCHEMA),
338 errmsg("schema \"%s\" does not exist",
339 newRelation->schemaname)));
340 /* we do not check for USAGE rights here! */
344 /* use the default creation namespace */
345 recomputeNamespacePath();
346 if (activeTempCreationPending)
348 /* Need to initialize temp namespace */
349 InitTempTableNamespace();
350 return myTempNamespace;
352 namespaceId = activeCreationNamespace;
353 if (!OidIsValid(namespaceId))
355 (errcode(ERRCODE_UNDEFINED_SCHEMA),
356 errmsg("no schema has been selected to create in")));
359 /* Note: callers will check for CREATE rights when appropriate */
366 * Try to resolve an unqualified relation name.
367 * Returns OID if relation found in search path, else InvalidOid.
370 RelnameGetRelid(const char *relname)
375 recomputeNamespacePath();
377 foreach(l, activeSearchPath)
379 Oid namespaceId = lfirst_oid(l);
381 relid = get_relname_relid(relname, namespaceId);
382 if (OidIsValid(relid))
386 /* Not found in path */
393 * Determine whether a relation (identified by OID) is visible in the
394 * current search path. Visible means "would be found by searching
395 * for the unqualified relation name".
398 RelationIsVisible(Oid relid)
401 Form_pg_class relform;
405 reltup = SearchSysCache(RELOID,
406 ObjectIdGetDatum(relid),
408 if (!HeapTupleIsValid(reltup))
409 elog(ERROR, "cache lookup failed for relation %u", relid);
410 relform = (Form_pg_class) GETSTRUCT(reltup);
412 recomputeNamespacePath();
415 * Quick check: if it ain't in the path at all, it ain't visible. Items in
416 * the system namespace are surely in the path and so we needn't even do
417 * list_member_oid() for them.
419 relnamespace = relform->relnamespace;
420 if (relnamespace != PG_CATALOG_NAMESPACE &&
421 !list_member_oid(activeSearchPath, relnamespace))
426 * If it is in the path, it might still not be visible; it could be
427 * hidden by another relation of the same name earlier in the path. So
428 * we must do a slow check for conflicting relations.
430 char *relname = NameStr(relform->relname);
434 foreach(l, activeSearchPath)
436 Oid namespaceId = lfirst_oid(l);
438 if (namespaceId == relnamespace)
440 /* Found it first in path */
444 if (OidIsValid(get_relname_relid(relname, namespaceId)))
446 /* Found something else first in path */
452 ReleaseSysCache(reltup);
460 * Try to resolve an unqualified datatype name.
461 * Returns OID if type found in search path, else InvalidOid.
463 * This is essentially the same as RelnameGetRelid.
466 TypenameGetTypid(const char *typname)
471 recomputeNamespacePath();
473 foreach(l, activeSearchPath)
475 Oid namespaceId = lfirst_oid(l);
477 typid = GetSysCacheOid(TYPENAMENSP,
478 PointerGetDatum(typname),
479 ObjectIdGetDatum(namespaceId),
481 if (OidIsValid(typid))
485 /* Not found in path */
491 * Determine whether a type (identified by OID) is visible in the
492 * current search path. Visible means "would be found by searching
493 * for the unqualified type name".
496 TypeIsVisible(Oid typid)
499 Form_pg_type typform;
503 typtup = SearchSysCache(TYPEOID,
504 ObjectIdGetDatum(typid),
506 if (!HeapTupleIsValid(typtup))
507 elog(ERROR, "cache lookup failed for type %u", typid);
508 typform = (Form_pg_type) GETSTRUCT(typtup);
510 recomputeNamespacePath();
513 * Quick check: if it ain't in the path at all, it ain't visible. Items in
514 * the system namespace are surely in the path and so we needn't even do
515 * list_member_oid() for them.
517 typnamespace = typform->typnamespace;
518 if (typnamespace != PG_CATALOG_NAMESPACE &&
519 !list_member_oid(activeSearchPath, typnamespace))
524 * If it is in the path, it might still not be visible; it could be
525 * hidden by another type of the same name earlier in the path. So we
526 * must do a slow check for conflicting types.
528 char *typname = NameStr(typform->typname);
532 foreach(l, activeSearchPath)
534 Oid namespaceId = lfirst_oid(l);
536 if (namespaceId == typnamespace)
538 /* Found it first in path */
542 if (SearchSysCacheExists(TYPENAMENSP,
543 PointerGetDatum(typname),
544 ObjectIdGetDatum(namespaceId),
547 /* Found something else first in path */
553 ReleaseSysCache(typtup);
560 * FuncnameGetCandidates
561 * Given a possibly-qualified function name and argument count,
562 * retrieve a list of the possible matches.
564 * If nargs is -1, we return all functions matching the given name,
565 * regardless of argument count. (expand_variadic must be false in this case.)
567 * If expand_variadic is true, then variadic functions having the same number
568 * or fewer arguments will be retrieved, with the variadic argument and any
569 * additional argument positions filled with the variadic element type.
570 * nvargs in the returned struct is set to the number of such arguments.
571 * If expand_variadic is false, variadic arguments are not treated specially,
572 * and the returned nvargs will always be zero.
574 * If expand_variadic is true, functions with argument default values
575 * will also be retrieved. If expand_variadic is false, default
576 * values will not be taken into account and functions that do not
577 * have exactly nargs arguments in total will not be considered.
579 * We search a single namespace if the function name is qualified, else
580 * all namespaces in the search path. The return list will never contain
581 * multiple entries with identical argument lists --- in the multiple-
582 * namespace case, we arrange for entries in earlier namespaces to mask
583 * identical entries in later namespaces. We also arrange for non-variadic
584 * functions to mask variadic ones if the expanded argument list is the same.
587 FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
589 FuncCandidateList resultList = NULL;
590 bool any_variadic = false;
597 /* check for caller error */
598 Assert(nargs >= 0 || !expand_variadic);
600 /* deconstruct the name list */
601 DeconstructQualifiedName(names, &schemaname, &funcname);
605 /* use exact schema given */
606 namespaceId = LookupExplicitNamespace(schemaname);
610 /* flag to indicate we need namespace search */
611 namespaceId = InvalidOid;
612 recomputeNamespacePath();
615 /* Search syscache by name only */
616 catlist = SearchSysCacheList(PROCNAMEARGSNSP, 1,
617 CStringGetDatum(funcname),
620 for (i = 0; i < catlist->n_members; i++)
622 HeapTuple proctup = &catlist->members[i]->tuple;
623 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
624 int pronargs = procform->pronargs;
629 List *defaults = NIL;
630 FuncCandidateList newResult;
633 * Check if function has some parameter defaults if some
634 * parameters are missing.
636 if (pronargs > nargs && expand_variadic)
639 Datum proargdefaults;
642 /* skip when not enough default expressions */
643 if (nargs + procform->pronargdefaults < pronargs)
646 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
647 Anum_pg_proc_proargdefaults, &isnull);
649 str = TextDatumGetCString(proargdefaults);
650 defaults = (List *) stringToNode(str);
652 Assert(IsA(defaults, List));
655 * If we don't have to use all default parameters, we skip
656 * some cells from the left.
658 defaults = list_copy_tail(defaults, procform->pronargdefaults - pronargs + nargs);
664 * Check if function is variadic, and get variadic element type if so.
665 * If expand_variadic is false, we should just ignore variadic-ness.
667 if (pronargs <= nargs && expand_variadic)
669 va_elem_type = procform->provariadic;
670 variadic = OidIsValid(va_elem_type);
674 va_elem_type = InvalidOid;
678 Assert(!variadic || !defaults);
680 /* Ignore if it doesn't match requested argument count */
682 (variadic ? (pronargs > nargs) : (defaults ? (pronargs < nargs) : (pronargs != nargs))))
685 Assert(!variadic || (pronargs <= nargs));
686 Assert(!defaults || (pronargs > nargs));
688 if (OidIsValid(namespaceId))
690 /* Consider only procs in specified namespace */
691 if (procform->pronamespace != namespaceId)
697 * Consider only procs that are in the search path and are not in
698 * the temp namespace.
702 foreach(nsp, activeSearchPath)
704 if (procform->pronamespace == lfirst_oid(nsp) &&
705 procform->pronamespace != myTempNamespace)
710 continue; /* proc is not in search path */
714 * We must compute the effective argument list so that we can easily
715 * compare it to earlier results. We waste a palloc cycle if it gets
716 * masked by an earlier result, but really that's a pretty infrequent
717 * case so it's not worth worrying about.
719 effective_nargs = Max(pronargs, nargs);
720 newResult = (FuncCandidateList)
721 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
722 + effective_nargs * sizeof(Oid));
723 newResult->pathpos = pathpos;
724 newResult->oid = HeapTupleGetOid(proctup);
725 newResult->nargs = effective_nargs;
726 newResult->argdefaults = defaults;
727 memcpy(newResult->args, procform->proargtypes.values,
728 pronargs * sizeof(Oid));
733 newResult->nvargs = effective_nargs - pronargs + 1;
734 /* Expand variadic argument into N copies of element type */
735 for (i = pronargs - 1; i < effective_nargs; i++)
736 newResult->args[i] = va_elem_type;
739 newResult->nvargs = 0;
741 any_variadic = variadic || defaults;
744 * Does it have the same arguments as something we already accepted?
745 * If so, decide which one to keep. We can skip this check for the
746 * single-namespace case if no variadic match has been made, since
747 * then the unique index on pg_proc guarantees all the matches have
748 * different argument lists.
750 if (any_variadic || !OidIsValid(namespaceId))
753 effective_nargs = nargs;
756 * If we have an ordered list from SearchSysCacheList (the normal
757 * case), then any conflicting proc must immediately adjoin this
758 * one in the list, so we only need to look at the newest result
759 * item. If we have an unordered list, we have to scan the whole
760 * result list. Also, if either the current candidate or any
761 * previous candidate is a variadic match, we can't assume that
762 * conflicts are adjacent.
766 FuncCandidateList prevResult;
768 if (catlist->ordered && !any_variadic)
770 if (effective_nargs == resultList->nargs &&
771 memcmp(newResult->args,
773 effective_nargs * sizeof(Oid)) == 0)
774 prevResult = resultList;
780 for (prevResult = resultList;
782 prevResult = prevResult->next)
786 if (effective_nargs == prevResult->nargs &&
787 memcmp(newResult->args,
789 effective_nargs * sizeof(Oid)) == 0)
794 if (memcmp(newResult->args,
796 effective_nargs * sizeof(Oid)) == 0)
804 * We have a match with a previous result. Prefer the
805 * one that's earlier in the search path.
807 if (pathpos > prevResult->pathpos)
810 continue; /* keep previous result */
812 else if (pathpos == prevResult->pathpos)
815 * With variadic functions we could have, for example,
816 * both foo(numeric) and foo(variadic numeric[]) in
817 * the same namespace; if so we prefer the
818 * non-variadic match on efficiency grounds. It's
819 * also possible to have conflicting variadic
820 * functions, such as foo(numeric, variadic numeric[])
821 * and foo(variadic numeric[]). If you're silly
822 * enough to do that, we throw an error. (XXX It'd be
823 * better to detect such conflicts when the functions
828 if (prevResult->nvargs > 0)
830 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
831 errmsg("variadic function %s conflicts with another",
832 func_signature_string(names, pronargs,
833 procform->proargtypes.values))));
834 /* else, previous result wasn't variadic */
836 continue; /* keep previous result */
841 if (prevResult->argdefaults != NIL)
843 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
844 errmsg("functions with parameter defaults %s and %s are ambiguous",
845 func_signature_string(names, pronargs, procform->proargtypes.values),
846 func_signature_string(names, prevResult->nargs, prevResult->args))));
847 /* else, previous result didn't have defaults */
849 continue; /* keep previous result */
852 /* non-variadic can replace a previous variadic */
853 Assert(prevResult->nvargs > 0);
855 /* replace previous result */
856 prevResult->pathpos = pathpos;
857 prevResult->oid = newResult->oid;
858 prevResult->nvargs = newResult->nvargs;
859 prevResult->argdefaults = newResult->argdefaults;
861 continue; /* args are same, of course */
867 * Okay to add it to result list
869 newResult->next = resultList;
870 resultList = newResult;
873 ReleaseSysCacheList(catlist);
880 * Determine whether a function (identified by OID) is visible in the
881 * current search path. Visible means "would be found by searching
882 * for the unqualified function name with exact argument matches".
885 FunctionIsVisible(Oid funcid)
888 Form_pg_proc procform;
892 proctup = SearchSysCache(PROCOID,
893 ObjectIdGetDatum(funcid),
895 if (!HeapTupleIsValid(proctup))
896 elog(ERROR, "cache lookup failed for function %u", funcid);
897 procform = (Form_pg_proc) GETSTRUCT(proctup);
899 recomputeNamespacePath();
902 * Quick check: if it ain't in the path at all, it ain't visible. Items in
903 * the system namespace are surely in the path and so we needn't even do
904 * list_member_oid() for them.
906 pronamespace = procform->pronamespace;
907 if (pronamespace != PG_CATALOG_NAMESPACE &&
908 !list_member_oid(activeSearchPath, pronamespace))
913 * If it is in the path, it might still not be visible; it could be
914 * hidden by another proc of the same name and arguments earlier in
915 * the path. So we must do a slow check to see if this is the same
916 * proc that would be found by FuncnameGetCandidates.
918 char *proname = NameStr(procform->proname);
919 int nargs = procform->pronargs;
920 FuncCandidateList clist;
924 clist = FuncnameGetCandidates(list_make1(makeString(proname)),
927 for (; clist; clist = clist->next)
929 if (memcmp(clist->args, procform->proargtypes.values,
930 nargs * sizeof(Oid)) == 0)
932 /* Found the expected entry; is it the right proc? */
933 visible = (clist->oid == funcid);
939 ReleaseSysCache(proctup);
947 * Given a possibly-qualified operator name and exact input datatypes,
948 * look up the operator. Returns InvalidOid if not found.
950 * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
953 * If the operator name is not schema-qualified, it is sought in the current
954 * namespace search path.
957 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
964 /* deconstruct the name list */
965 DeconstructQualifiedName(names, &schemaname, &opername);
969 /* search only in exact schema given */
973 namespaceId = LookupExplicitNamespace(schemaname);
974 opertup = SearchSysCache(OPERNAMENSP,
975 CStringGetDatum(opername),
976 ObjectIdGetDatum(oprleft),
977 ObjectIdGetDatum(oprright),
978 ObjectIdGetDatum(namespaceId));
979 if (HeapTupleIsValid(opertup))
981 Oid result = HeapTupleGetOid(opertup);
983 ReleaseSysCache(opertup);
989 /* Search syscache by name and argument types */
990 catlist = SearchSysCacheList(OPERNAMENSP, 3,
991 CStringGetDatum(opername),
992 ObjectIdGetDatum(oprleft),
993 ObjectIdGetDatum(oprright),
996 if (catlist->n_members == 0)
998 /* no hope, fall out early */
999 ReleaseSysCacheList(catlist);
1004 * We have to find the list member that is first in the search path, if
1005 * there's more than one. This doubly-nested loop looks ugly, but in
1006 * practice there should usually be few catlist members.
1008 recomputeNamespacePath();
1010 foreach(l, activeSearchPath)
1012 Oid namespaceId = lfirst_oid(l);
1015 if (namespaceId == myTempNamespace)
1016 continue; /* do not look in temp namespace */
1018 for (i = 0; i < catlist->n_members; i++)
1020 HeapTuple opertup = &catlist->members[i]->tuple;
1021 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1023 if (operform->oprnamespace == namespaceId)
1025 Oid result = HeapTupleGetOid(opertup);
1027 ReleaseSysCacheList(catlist);
1033 ReleaseSysCacheList(catlist);
1038 * OpernameGetCandidates
1039 * Given a possibly-qualified operator name and operator kind,
1040 * retrieve a list of the possible matches.
1042 * If oprkind is '\0', we return all operators matching the given name,
1043 * regardless of arguments.
1045 * We search a single namespace if the operator name is qualified, else
1046 * all namespaces in the search path. The return list will never contain
1047 * multiple entries with identical argument lists --- in the multiple-
1048 * namespace case, we arrange for entries in earlier namespaces to mask
1049 * identical entries in later namespaces.
1051 * The returned items always have two args[] entries --- one or the other
1052 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
1055 OpernameGetCandidates(List *names, char oprkind)
1057 FuncCandidateList resultList = NULL;
1058 char *resultSpace = NULL;
1066 /* deconstruct the name list */
1067 DeconstructQualifiedName(names, &schemaname, &opername);
1071 /* use exact schema given */
1072 namespaceId = LookupExplicitNamespace(schemaname);
1076 /* flag to indicate we need namespace search */
1077 namespaceId = InvalidOid;
1078 recomputeNamespacePath();
1081 /* Search syscache by name only */
1082 catlist = SearchSysCacheList(OPERNAMENSP, 1,
1083 CStringGetDatum(opername),
1087 * In typical scenarios, most if not all of the operators found by the
1088 * catcache search will end up getting returned; and there can be quite a
1089 * few, for common operator names such as '=' or '+'. To reduce the time
1090 * spent in palloc, we allocate the result space as an array large enough
1091 * to hold all the operators. The original coding of this routine did a
1092 * separate palloc for each operator, but profiling revealed that the
1093 * pallocs used an unreasonably large fraction of parsing time.
1095 #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
1097 if (catlist->n_members > 0)
1098 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1100 for (i = 0; i < catlist->n_members; i++)
1102 HeapTuple opertup = &catlist->members[i]->tuple;
1103 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1105 FuncCandidateList newResult;
1107 /* Ignore operators of wrong kind, if specific kind requested */
1108 if (oprkind && operform->oprkind != oprkind)
1111 if (OidIsValid(namespaceId))
1113 /* Consider only opers in specified namespace */
1114 if (operform->oprnamespace != namespaceId)
1116 /* No need to check args, they must all be different */
1121 * Consider only opers that are in the search path and are not in
1122 * the temp namespace.
1126 foreach(nsp, activeSearchPath)
1128 if (operform->oprnamespace == lfirst_oid(nsp) &&
1129 operform->oprnamespace != myTempNamespace)
1134 continue; /* oper is not in search path */
1137 * Okay, it's in the search path, but does it have the same
1138 * arguments as something we already accepted? If so, keep only
1139 * the one that appears earlier in the search path.
1141 * If we have an ordered list from SearchSysCacheList (the normal
1142 * case), then any conflicting oper must immediately adjoin this
1143 * one in the list, so we only need to look at the newest result
1144 * item. If we have an unordered list, we have to scan the whole
1149 FuncCandidateList prevResult;
1151 if (catlist->ordered)
1153 if (operform->oprleft == resultList->args[0] &&
1154 operform->oprright == resultList->args[1])
1155 prevResult = resultList;
1161 for (prevResult = resultList;
1163 prevResult = prevResult->next)
1165 if (operform->oprleft == prevResult->args[0] &&
1166 operform->oprright == prevResult->args[1])
1172 /* We have a match with a previous result */
1173 Assert(pathpos != prevResult->pathpos);
1174 if (pathpos > prevResult->pathpos)
1175 continue; /* keep previous result */
1176 /* replace previous result */
1177 prevResult->pathpos = pathpos;
1178 prevResult->oid = HeapTupleGetOid(opertup);
1179 continue; /* args are same, of course */
1185 * Okay to add it to result list
1187 newResult = (FuncCandidateList) (resultSpace + nextResult);
1188 nextResult += SPACE_PER_OP;
1190 newResult->pathpos = pathpos;
1191 newResult->oid = HeapTupleGetOid(opertup);
1192 newResult->nargs = 2;
1193 newResult->nvargs = 0;
1194 newResult->args[0] = operform->oprleft;
1195 newResult->args[1] = operform->oprright;
1196 newResult->next = resultList;
1197 resultList = newResult;
1200 ReleaseSysCacheList(catlist);
1207 * Determine whether an operator (identified by OID) is visible in the
1208 * current search path. Visible means "would be found by searching
1209 * for the unqualified operator name with exact argument matches".
1212 OperatorIsVisible(Oid oprid)
1215 Form_pg_operator oprform;
1219 oprtup = SearchSysCache(OPEROID,
1220 ObjectIdGetDatum(oprid),
1222 if (!HeapTupleIsValid(oprtup))
1223 elog(ERROR, "cache lookup failed for operator %u", oprid);
1224 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
1226 recomputeNamespacePath();
1229 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1230 * the system namespace are surely in the path and so we needn't even do
1231 * list_member_oid() for them.
1233 oprnamespace = oprform->oprnamespace;
1234 if (oprnamespace != PG_CATALOG_NAMESPACE &&
1235 !list_member_oid(activeSearchPath, oprnamespace))
1240 * If it is in the path, it might still not be visible; it could be
1241 * hidden by another operator of the same name and arguments earlier
1242 * in the path. So we must do a slow check to see if this is the same
1243 * operator that would be found by OpernameGetOprId.
1245 char *oprname = NameStr(oprform->oprname);
1247 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
1248 oprform->oprleft, oprform->oprright)
1252 ReleaseSysCache(oprtup);
1259 * OpclassnameGetOpcid
1260 * Try to resolve an unqualified index opclass name.
1261 * Returns OID if opclass found in search path, else InvalidOid.
1263 * This is essentially the same as TypenameGetTypid, but we have to have
1264 * an extra argument for the index AM OID.
1267 OpclassnameGetOpcid(Oid amid, const char *opcname)
1272 recomputeNamespacePath();
1274 foreach(l, activeSearchPath)
1276 Oid namespaceId = lfirst_oid(l);
1278 if (namespaceId == myTempNamespace)
1279 continue; /* do not look in temp namespace */
1281 opcid = GetSysCacheOid(CLAAMNAMENSP,
1282 ObjectIdGetDatum(amid),
1283 PointerGetDatum(opcname),
1284 ObjectIdGetDatum(namespaceId),
1286 if (OidIsValid(opcid))
1290 /* Not found in path */
1296 * Determine whether an opclass (identified by OID) is visible in the
1297 * current search path. Visible means "would be found by searching
1298 * for the unqualified opclass name".
1301 OpclassIsVisible(Oid opcid)
1304 Form_pg_opclass opcform;
1308 opctup = SearchSysCache(CLAOID,
1309 ObjectIdGetDatum(opcid),
1311 if (!HeapTupleIsValid(opctup))
1312 elog(ERROR, "cache lookup failed for opclass %u", opcid);
1313 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1315 recomputeNamespacePath();
1318 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1319 * the system namespace are surely in the path and so we needn't even do
1320 * list_member_oid() for them.
1322 opcnamespace = opcform->opcnamespace;
1323 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1324 !list_member_oid(activeSearchPath, opcnamespace))
1329 * If it is in the path, it might still not be visible; it could be
1330 * hidden by another opclass of the same name earlier in the path. So
1331 * we must do a slow check to see if this opclass would be found by
1332 * OpclassnameGetOpcid.
1334 char *opcname = NameStr(opcform->opcname);
1336 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
1339 ReleaseSysCache(opctup);
1345 * OpfamilynameGetOpfid
1346 * Try to resolve an unqualified index opfamily name.
1347 * Returns OID if opfamily found in search path, else InvalidOid.
1349 * This is essentially the same as TypenameGetTypid, but we have to have
1350 * an extra argument for the index AM OID.
1353 OpfamilynameGetOpfid(Oid amid, const char *opfname)
1358 recomputeNamespacePath();
1360 foreach(l, activeSearchPath)
1362 Oid namespaceId = lfirst_oid(l);
1364 if (namespaceId == myTempNamespace)
1365 continue; /* do not look in temp namespace */
1367 opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
1368 ObjectIdGetDatum(amid),
1369 PointerGetDatum(opfname),
1370 ObjectIdGetDatum(namespaceId),
1372 if (OidIsValid(opfid))
1376 /* Not found in path */
1382 * Determine whether an opfamily (identified by OID) is visible in the
1383 * current search path. Visible means "would be found by searching
1384 * for the unqualified opfamily name".
1387 OpfamilyIsVisible(Oid opfid)
1390 Form_pg_opfamily opfform;
1394 opftup = SearchSysCache(OPFAMILYOID,
1395 ObjectIdGetDatum(opfid),
1397 if (!HeapTupleIsValid(opftup))
1398 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
1399 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
1401 recomputeNamespacePath();
1404 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1405 * the system namespace are surely in the path and so we needn't even do
1406 * list_member_oid() for them.
1408 opfnamespace = opfform->opfnamespace;
1409 if (opfnamespace != PG_CATALOG_NAMESPACE &&
1410 !list_member_oid(activeSearchPath, opfnamespace))
1415 * If it is in the path, it might still not be visible; it could be
1416 * hidden by another opfamily of the same name earlier in the path. So
1417 * we must do a slow check to see if this opfamily would be found by
1418 * OpfamilynameGetOpfid.
1420 char *opfname = NameStr(opfform->opfname);
1422 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
1425 ReleaseSysCache(opftup);
1431 * ConversionGetConid
1432 * Try to resolve an unqualified conversion name.
1433 * Returns OID if conversion found in search path, else InvalidOid.
1435 * This is essentially the same as RelnameGetRelid.
1438 ConversionGetConid(const char *conname)
1443 recomputeNamespacePath();
1445 foreach(l, activeSearchPath)
1447 Oid namespaceId = lfirst_oid(l);
1449 if (namespaceId == myTempNamespace)
1450 continue; /* do not look in temp namespace */
1452 conid = GetSysCacheOid(CONNAMENSP,
1453 PointerGetDatum(conname),
1454 ObjectIdGetDatum(namespaceId),
1456 if (OidIsValid(conid))
1460 /* Not found in path */
1465 * ConversionIsVisible
1466 * Determine whether a conversion (identified by OID) is visible in the
1467 * current search path. Visible means "would be found by searching
1468 * for the unqualified conversion name".
1471 ConversionIsVisible(Oid conid)
1474 Form_pg_conversion conform;
1478 contup = SearchSysCache(CONVOID,
1479 ObjectIdGetDatum(conid),
1481 if (!HeapTupleIsValid(contup))
1482 elog(ERROR, "cache lookup failed for conversion %u", conid);
1483 conform = (Form_pg_conversion) GETSTRUCT(contup);
1485 recomputeNamespacePath();
1488 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1489 * the system namespace are surely in the path and so we needn't even do
1490 * list_member_oid() for them.
1492 connamespace = conform->connamespace;
1493 if (connamespace != PG_CATALOG_NAMESPACE &&
1494 !list_member_oid(activeSearchPath, connamespace))
1499 * If it is in the path, it might still not be visible; it could be
1500 * hidden by another conversion of the same name earlier in the path.
1501 * So we must do a slow check to see if this conversion would be found
1502 * by ConversionGetConid.
1504 char *conname = NameStr(conform->conname);
1506 visible = (ConversionGetConid(conname) == conid);
1509 ReleaseSysCache(contup);
1515 * TSParserGetPrsid - find a TS parser by possibly qualified name
1517 * If not found, returns InvalidOid if failOK, else throws error
1520 TSParserGetPrsid(List *names, bool failOK)
1525 Oid prsoid = InvalidOid;
1528 /* deconstruct the name list */
1529 DeconstructQualifiedName(names, &schemaname, &parser_name);
1533 /* use exact schema given */
1534 namespaceId = LookupExplicitNamespace(schemaname);
1535 prsoid = GetSysCacheOid(TSPARSERNAMENSP,
1536 PointerGetDatum(parser_name),
1537 ObjectIdGetDatum(namespaceId),
1542 /* search for it in search path */
1543 recomputeNamespacePath();
1545 foreach(l, activeSearchPath)
1547 namespaceId = lfirst_oid(l);
1549 if (namespaceId == myTempNamespace)
1550 continue; /* do not look in temp namespace */
1552 prsoid = GetSysCacheOid(TSPARSERNAMENSP,
1553 PointerGetDatum(parser_name),
1554 ObjectIdGetDatum(namespaceId),
1556 if (OidIsValid(prsoid))
1561 if (!OidIsValid(prsoid) && !failOK)
1563 (errcode(ERRCODE_UNDEFINED_OBJECT),
1564 errmsg("text search parser \"%s\" does not exist",
1565 NameListToString(names))));
1572 * Determine whether a parser (identified by OID) is visible in the
1573 * current search path. Visible means "would be found by searching
1574 * for the unqualified parser name".
1577 TSParserIsVisible(Oid prsId)
1580 Form_pg_ts_parser form;
1584 tup = SearchSysCache(TSPARSEROID,
1585 ObjectIdGetDatum(prsId),
1587 if (!HeapTupleIsValid(tup))
1588 elog(ERROR, "cache lookup failed for text search parser %u", prsId);
1589 form = (Form_pg_ts_parser) GETSTRUCT(tup);
1591 recomputeNamespacePath();
1594 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1595 * the system namespace are surely in the path and so we needn't even do
1596 * list_member_oid() for them.
1598 namespace = form->prsnamespace;
1599 if (namespace != PG_CATALOG_NAMESPACE &&
1600 !list_member_oid(activeSearchPath, namespace))
1605 * If it is in the path, it might still not be visible; it could be
1606 * hidden by another parser of the same name earlier in the path. So
1607 * we must do a slow check for conflicting parsers.
1609 char *name = NameStr(form->prsname);
1613 foreach(l, activeSearchPath)
1615 Oid namespaceId = lfirst_oid(l);
1617 if (namespaceId == myTempNamespace)
1618 continue; /* do not look in temp namespace */
1620 if (namespaceId == namespace)
1622 /* Found it first in path */
1626 if (SearchSysCacheExists(TSPARSERNAMENSP,
1627 PointerGetDatum(name),
1628 ObjectIdGetDatum(namespaceId),
1631 /* Found something else first in path */
1637 ReleaseSysCache(tup);
1643 * TSDictionaryGetDictid - find a TS dictionary by possibly qualified name
1645 * If not found, returns InvalidOid if failOK, else throws error
1648 TSDictionaryGetDictid(List *names, bool failOK)
1653 Oid dictoid = InvalidOid;
1656 /* deconstruct the name list */
1657 DeconstructQualifiedName(names, &schemaname, &dict_name);
1661 /* use exact schema given */
1662 namespaceId = LookupExplicitNamespace(schemaname);
1663 dictoid = GetSysCacheOid(TSDICTNAMENSP,
1664 PointerGetDatum(dict_name),
1665 ObjectIdGetDatum(namespaceId),
1670 /* search for it in search path */
1671 recomputeNamespacePath();
1673 foreach(l, activeSearchPath)
1675 namespaceId = lfirst_oid(l);
1677 if (namespaceId == myTempNamespace)
1678 continue; /* do not look in temp namespace */
1680 dictoid = GetSysCacheOid(TSDICTNAMENSP,
1681 PointerGetDatum(dict_name),
1682 ObjectIdGetDatum(namespaceId),
1684 if (OidIsValid(dictoid))
1689 if (!OidIsValid(dictoid) && !failOK)
1691 (errcode(ERRCODE_UNDEFINED_OBJECT),
1692 errmsg("text search dictionary \"%s\" does not exist",
1693 NameListToString(names))));
1699 * TSDictionaryIsVisible
1700 * Determine whether a dictionary (identified by OID) is visible in the
1701 * current search path. Visible means "would be found by searching
1702 * for the unqualified dictionary name".
1705 TSDictionaryIsVisible(Oid dictId)
1708 Form_pg_ts_dict form;
1712 tup = SearchSysCache(TSDICTOID,
1713 ObjectIdGetDatum(dictId),
1715 if (!HeapTupleIsValid(tup))
1716 elog(ERROR, "cache lookup failed for text search dictionary %u",
1718 form = (Form_pg_ts_dict) GETSTRUCT(tup);
1720 recomputeNamespacePath();
1723 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1724 * the system namespace are surely in the path and so we needn't even do
1725 * list_member_oid() for them.
1727 namespace = form->dictnamespace;
1728 if (namespace != PG_CATALOG_NAMESPACE &&
1729 !list_member_oid(activeSearchPath, namespace))
1734 * If it is in the path, it might still not be visible; it could be
1735 * hidden by another dictionary of the same name earlier in the path.
1736 * So we must do a slow check for conflicting dictionaries.
1738 char *name = NameStr(form->dictname);
1742 foreach(l, activeSearchPath)
1744 Oid namespaceId = lfirst_oid(l);
1746 if (namespaceId == myTempNamespace)
1747 continue; /* do not look in temp namespace */
1749 if (namespaceId == namespace)
1751 /* Found it first in path */
1755 if (SearchSysCacheExists(TSDICTNAMENSP,
1756 PointerGetDatum(name),
1757 ObjectIdGetDatum(namespaceId),
1760 /* Found something else first in path */
1766 ReleaseSysCache(tup);
1772 * TSTemplateGetTmplid - find a TS template by possibly qualified name
1774 * If not found, returns InvalidOid if failOK, else throws error
1777 TSTemplateGetTmplid(List *names, bool failOK)
1780 char *template_name;
1782 Oid tmploid = InvalidOid;
1785 /* deconstruct the name list */
1786 DeconstructQualifiedName(names, &schemaname, &template_name);
1790 /* use exact schema given */
1791 namespaceId = LookupExplicitNamespace(schemaname);
1792 tmploid = GetSysCacheOid(TSTEMPLATENAMENSP,
1793 PointerGetDatum(template_name),
1794 ObjectIdGetDatum(namespaceId),
1799 /* search for it in search path */
1800 recomputeNamespacePath();
1802 foreach(l, activeSearchPath)
1804 namespaceId = lfirst_oid(l);
1806 if (namespaceId == myTempNamespace)
1807 continue; /* do not look in temp namespace */
1809 tmploid = GetSysCacheOid(TSTEMPLATENAMENSP,
1810 PointerGetDatum(template_name),
1811 ObjectIdGetDatum(namespaceId),
1813 if (OidIsValid(tmploid))
1818 if (!OidIsValid(tmploid) && !failOK)
1820 (errcode(ERRCODE_UNDEFINED_OBJECT),
1821 errmsg("text search template \"%s\" does not exist",
1822 NameListToString(names))));
1828 * TSTemplateIsVisible
1829 * Determine whether a template (identified by OID) is visible in the
1830 * current search path. Visible means "would be found by searching
1831 * for the unqualified template name".
1834 TSTemplateIsVisible(Oid tmplId)
1837 Form_pg_ts_template form;
1841 tup = SearchSysCache(TSTEMPLATEOID,
1842 ObjectIdGetDatum(tmplId),
1844 if (!HeapTupleIsValid(tup))
1845 elog(ERROR, "cache lookup failed for text search template %u", tmplId);
1846 form = (Form_pg_ts_template) GETSTRUCT(tup);
1848 recomputeNamespacePath();
1851 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1852 * the system namespace are surely in the path and so we needn't even do
1853 * list_member_oid() for them.
1855 namespace = form->tmplnamespace;
1856 if (namespace != PG_CATALOG_NAMESPACE &&
1857 !list_member_oid(activeSearchPath, namespace))
1862 * If it is in the path, it might still not be visible; it could be
1863 * hidden by another template of the same name earlier in the path. So
1864 * we must do a slow check for conflicting templates.
1866 char *name = NameStr(form->tmplname);
1870 foreach(l, activeSearchPath)
1872 Oid namespaceId = lfirst_oid(l);
1874 if (namespaceId == myTempNamespace)
1875 continue; /* do not look in temp namespace */
1877 if (namespaceId == namespace)
1879 /* Found it first in path */
1883 if (SearchSysCacheExists(TSTEMPLATENAMENSP,
1884 PointerGetDatum(name),
1885 ObjectIdGetDatum(namespaceId),
1888 /* Found something else first in path */
1894 ReleaseSysCache(tup);
1900 * TSConfigGetCfgid - find a TS config by possibly qualified name
1902 * If not found, returns InvalidOid if failOK, else throws error
1905 TSConfigGetCfgid(List *names, bool failOK)
1910 Oid cfgoid = InvalidOid;
1913 /* deconstruct the name list */
1914 DeconstructQualifiedName(names, &schemaname, &config_name);
1918 /* use exact schema given */
1919 namespaceId = LookupExplicitNamespace(schemaname);
1920 cfgoid = GetSysCacheOid(TSCONFIGNAMENSP,
1921 PointerGetDatum(config_name),
1922 ObjectIdGetDatum(namespaceId),
1927 /* search for it in search path */
1928 recomputeNamespacePath();
1930 foreach(l, activeSearchPath)
1932 namespaceId = lfirst_oid(l);
1934 if (namespaceId == myTempNamespace)
1935 continue; /* do not look in temp namespace */
1937 cfgoid = GetSysCacheOid(TSCONFIGNAMENSP,
1938 PointerGetDatum(config_name),
1939 ObjectIdGetDatum(namespaceId),
1941 if (OidIsValid(cfgoid))
1946 if (!OidIsValid(cfgoid) && !failOK)
1948 (errcode(ERRCODE_UNDEFINED_OBJECT),
1949 errmsg("text search configuration \"%s\" does not exist",
1950 NameListToString(names))));
1957 * Determine whether a text search configuration (identified by OID)
1958 * is visible in the current search path. Visible means "would be found
1959 * by searching for the unqualified text search configuration name".
1962 TSConfigIsVisible(Oid cfgid)
1965 Form_pg_ts_config form;
1969 tup = SearchSysCache(TSCONFIGOID,
1970 ObjectIdGetDatum(cfgid),
1972 if (!HeapTupleIsValid(tup))
1973 elog(ERROR, "cache lookup failed for text search configuration %u",
1975 form = (Form_pg_ts_config) GETSTRUCT(tup);
1977 recomputeNamespacePath();
1980 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1981 * the system namespace are surely in the path and so we needn't even do
1982 * list_member_oid() for them.
1984 namespace = form->cfgnamespace;
1985 if (namespace != PG_CATALOG_NAMESPACE &&
1986 !list_member_oid(activeSearchPath, namespace))
1991 * If it is in the path, it might still not be visible; it could be
1992 * hidden by another configuration of the same name earlier in the
1993 * path. So we must do a slow check for conflicting configurations.
1995 char *name = NameStr(form->cfgname);
1999 foreach(l, activeSearchPath)
2001 Oid namespaceId = lfirst_oid(l);
2003 if (namespaceId == myTempNamespace)
2004 continue; /* do not look in temp namespace */
2006 if (namespaceId == namespace)
2008 /* Found it first in path */
2012 if (SearchSysCacheExists(TSCONFIGNAMENSP,
2013 PointerGetDatum(name),
2014 ObjectIdGetDatum(namespaceId),
2017 /* Found something else first in path */
2023 ReleaseSysCache(tup);
2030 * DeconstructQualifiedName
2031 * Given a possibly-qualified name expressed as a list of String nodes,
2032 * extract the schema name and object name.
2034 * *nspname_p is set to NULL if there is no explicit schema name.
2037 DeconstructQualifiedName(List *names,
2042 char *schemaname = NULL;
2043 char *objname = NULL;
2045 switch (list_length(names))
2048 objname = strVal(linitial(names));
2051 schemaname = strVal(linitial(names));
2052 objname = strVal(lsecond(names));
2055 catalogname = strVal(linitial(names));
2056 schemaname = strVal(lsecond(names));
2057 objname = strVal(lthird(names));
2060 * We check the catalog name and then ignore it.
2062 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
2064 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2065 errmsg("cross-database references are not implemented: %s",
2066 NameListToString(names))));
2070 (errcode(ERRCODE_SYNTAX_ERROR),
2071 errmsg("improper qualified name (too many dotted names): %s",
2072 NameListToString(names))));
2076 *nspname_p = schemaname;
2077 *objname_p = objname;
2081 * LookupExplicitNamespace
2082 * Process an explicitly-specified schema name: look up the schema
2083 * and verify we have USAGE (lookup) rights in it.
2085 * Returns the namespace OID. Raises ereport if any problem.
2088 LookupExplicitNamespace(const char *nspname)
2091 AclResult aclresult;
2093 /* check for pg_temp alias */
2094 if (strcmp(nspname, "pg_temp") == 0)
2096 if (OidIsValid(myTempNamespace))
2097 return myTempNamespace;
2100 * Since this is used only for looking up existing objects, there is
2101 * no point in trying to initialize the temp namespace here; and doing
2102 * so might create problems for some callers. Just fall through and
2103 * give the "does not exist" error.
2107 namespaceId = GetSysCacheOid(NAMESPACENAME,
2108 CStringGetDatum(nspname),
2110 if (!OidIsValid(namespaceId))
2112 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2113 errmsg("schema \"%s\" does not exist", nspname)));
2115 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
2116 if (aclresult != ACLCHECK_OK)
2117 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2124 * LookupCreationNamespace
2125 * Look up the schema and verify we have CREATE rights on it.
2127 * This is just like LookupExplicitNamespace except for the permission check,
2128 * and that we are willing to create pg_temp if needed.
2130 * Note: calling this may result in a CommandCounterIncrement operation,
2131 * if we have to create or clean out the temp namespace.
2134 LookupCreationNamespace(const char *nspname)
2137 AclResult aclresult;
2139 /* check for pg_temp alias */
2140 if (strcmp(nspname, "pg_temp") == 0)
2142 /* Initialize temp namespace if first time through */
2143 if (!OidIsValid(myTempNamespace))
2144 InitTempTableNamespace();
2145 return myTempNamespace;
2148 namespaceId = GetSysCacheOid(NAMESPACENAME,
2149 CStringGetDatum(nspname),
2151 if (!OidIsValid(namespaceId))
2153 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2154 errmsg("schema \"%s\" does not exist", nspname)));
2156 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
2157 if (aclresult != ACLCHECK_OK)
2158 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2165 * QualifiedNameGetCreationNamespace
2166 * Given a possibly-qualified name for an object (in List-of-Values
2167 * format), determine what namespace the object should be created in.
2168 * Also extract and return the object name (last component of list).
2170 * Note: this does not apply any permissions check. Callers must check
2171 * for CREATE rights on the selected namespace when appropriate.
2173 * Note: calling this may result in a CommandCounterIncrement operation,
2174 * if we have to create or clean out the temp namespace.
2177 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
2182 /* deconstruct the name list */
2183 DeconstructQualifiedName(names, &schemaname, objname_p);
2187 /* check for pg_temp alias */
2188 if (strcmp(schemaname, "pg_temp") == 0)
2190 /* Initialize temp namespace if first time through */
2191 if (!OidIsValid(myTempNamespace))
2192 InitTempTableNamespace();
2193 return myTempNamespace;
2195 /* use exact schema given */
2196 namespaceId = GetSysCacheOid(NAMESPACENAME,
2197 CStringGetDatum(schemaname),
2199 if (!OidIsValid(namespaceId))
2201 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2202 errmsg("schema \"%s\" does not exist", schemaname)));
2203 /* we do not check for USAGE rights here! */
2207 /* use the default creation namespace */
2208 recomputeNamespacePath();
2209 if (activeTempCreationPending)
2211 /* Need to initialize temp namespace */
2212 InitTempTableNamespace();
2213 return myTempNamespace;
2215 namespaceId = activeCreationNamespace;
2216 if (!OidIsValid(namespaceId))
2218 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2219 errmsg("no schema has been selected to create in")));
2226 * makeRangeVarFromNameList
2227 * Utility routine to convert a qualified-name list into RangeVar form.
2230 makeRangeVarFromNameList(List *names)
2232 RangeVar *rel = makeRangeVar(NULL, NULL, -1);
2234 switch (list_length(names))
2237 rel->relname = strVal(linitial(names));
2240 rel->schemaname = strVal(linitial(names));
2241 rel->relname = strVal(lsecond(names));
2244 rel->catalogname = strVal(linitial(names));
2245 rel->schemaname = strVal(lsecond(names));
2246 rel->relname = strVal(lthird(names));
2250 (errcode(ERRCODE_SYNTAX_ERROR),
2251 errmsg("improper relation name (too many dotted names): %s",
2252 NameListToString(names))));
2261 * Utility routine to convert a qualified-name list into a string.
2263 * This is used primarily to form error messages, and so we do not quote
2264 * the list elements, for the sake of legibility.
2266 * In most scenarios the list elements should always be Value strings,
2267 * but we also allow A_Star for the convenience of ColumnRef processing.
2270 NameListToString(List *names)
2272 StringInfoData string;
2275 initStringInfo(&string);
2279 Node *name = (Node *) lfirst(l);
2281 if (l != list_head(names))
2282 appendStringInfoChar(&string, '.');
2284 if (IsA(name, String))
2285 appendStringInfoString(&string, strVal(name));
2286 else if (IsA(name, A_Star))
2287 appendStringInfoString(&string, "*");
2289 elog(ERROR, "unexpected node type in name list: %d",
2290 (int) nodeTag(name));
2297 * NameListToQuotedString
2298 * Utility routine to convert a qualified-name list into a string.
2300 * Same as above except that names will be double-quoted where necessary,
2301 * so the string could be re-parsed (eg, by textToQualifiedNameList).
2304 NameListToQuotedString(List *names)
2306 StringInfoData string;
2309 initStringInfo(&string);
2313 if (l != list_head(names))
2314 appendStringInfoChar(&string, '.');
2315 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
2322 * isTempNamespace - is the given namespace my temporary-table namespace?
2325 isTempNamespace(Oid namespaceId)
2327 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
2333 * isTempToastNamespace - is the given namespace my temporary-toast-table
2337 isTempToastNamespace(Oid namespaceId)
2339 if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
2345 * isTempOrToastNamespace - is the given namespace my temporary-table
2346 * namespace or my temporary-toast-table namespace?
2349 isTempOrToastNamespace(Oid namespaceId)
2351 if (OidIsValid(myTempNamespace) &&
2352 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
2358 * isAnyTempNamespace - is the given namespace a temporary-table namespace
2359 * (either my own, or another backend's)? Temporary-toast-table namespaces
2360 * are included, too.
2363 isAnyTempNamespace(Oid namespaceId)
2368 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2369 nspname = get_namespace_name(namespaceId);
2371 return false; /* no such namespace? */
2372 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
2373 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
2379 * isOtherTempNamespace - is the given namespace some other backend's
2380 * temporary-table namespace (including temporary-toast-table namespaces)?
2383 isOtherTempNamespace(Oid namespaceId)
2385 /* If it's my own temp namespace, say "false" */
2386 if (isTempOrToastNamespace(namespaceId))
2388 /* Else, if it's any temp namespace, say "true" */
2389 return isAnyTempNamespace(namespaceId);
2393 * GetTempNamespaceBackendId - if the given namespace is a temporary-table
2394 * namespace (either my own, or another backend's), return the BackendId
2395 * that owns it. Temporary-toast-table namespaces are included, too.
2396 * If it isn't a temp namespace, return -1.
2399 GetTempNamespaceBackendId(Oid namespaceId)
2404 /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2405 nspname = get_namespace_name(namespaceId);
2407 return -1; /* no such namespace? */
2408 if (strncmp(nspname, "pg_temp_", 8) == 0)
2409 result = atoi(nspname + 8);
2410 else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
2411 result = atoi(nspname + 14);
2419 * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
2420 * which must already be assigned. (This is only used when creating a toast
2421 * table for a temp table, so we must have already done InitTempTableNamespace)
2424 GetTempToastNamespace(void)
2426 Assert(OidIsValid(myTempToastNamespace));
2427 return myTempToastNamespace;
2432 * GetOverrideSearchPath - fetch current search path definition in form
2433 * used by PushOverrideSearchPath.
2435 * The result structure is allocated in the specified memory context
2436 * (which might or might not be equal to CurrentMemoryContext); but any
2437 * junk created by revalidation calculations will be in CurrentMemoryContext.
2439 OverrideSearchPath *
2440 GetOverrideSearchPath(MemoryContext context)
2442 OverrideSearchPath *result;
2444 MemoryContext oldcxt;
2446 recomputeNamespacePath();
2448 oldcxt = MemoryContextSwitchTo(context);
2450 result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
2451 schemas = list_copy(activeSearchPath);
2452 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
2454 if (linitial_oid(schemas) == myTempNamespace)
2455 result->addTemp = true;
2458 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
2459 result->addCatalog = true;
2461 schemas = list_delete_first(schemas);
2463 result->schemas = schemas;
2465 MemoryContextSwitchTo(oldcxt);
2471 * PushOverrideSearchPath - temporarily override the search path
2473 * We allow nested overrides, hence the push/pop terminology. The GUC
2474 * search_path variable is ignored while an override is active.
2477 PushOverrideSearchPath(OverrideSearchPath *newpath)
2479 OverrideStackEntry *entry;
2482 MemoryContext oldcxt;
2485 * Copy the list for safekeeping, and insert implicitly-searched
2486 * namespaces as needed. This code should track recomputeNamespacePath.
2488 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2490 oidlist = list_copy(newpath->schemas);
2493 * Remember the first member of the explicit list.
2496 firstNS = InvalidOid;
2498 firstNS = linitial_oid(oidlist);
2501 * Add any implicitly-searched namespaces to the list. Note these go on
2502 * the front, not the back; also notice that we do not check USAGE
2503 * permissions for these.
2505 if (newpath->addCatalog)
2506 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2508 if (newpath->addTemp)
2510 Assert(OidIsValid(myTempNamespace));
2511 oidlist = lcons_oid(myTempNamespace, oidlist);
2515 * Build the new stack entry, then insert it at the head of the list.
2517 entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
2518 entry->searchPath = oidlist;
2519 entry->creationNamespace = firstNS;
2520 entry->nestLevel = GetCurrentTransactionNestLevel();
2522 overrideStack = lcons(entry, overrideStack);
2524 /* And make it active. */
2525 activeSearchPath = entry->searchPath;
2526 activeCreationNamespace = entry->creationNamespace;
2527 activeTempCreationPending = false; /* XXX is this OK? */
2529 MemoryContextSwitchTo(oldcxt);
2533 * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
2535 * Any push during a (sub)transaction will be popped automatically at abort.
2536 * But it's caller error if a push isn't popped in normal control flow.
2539 PopOverrideSearchPath(void)
2541 OverrideStackEntry *entry;
2543 /* Sanity checks. */
2544 if (overrideStack == NIL)
2545 elog(ERROR, "bogus PopOverrideSearchPath call");
2546 entry = (OverrideStackEntry *) linitial(overrideStack);
2547 if (entry->nestLevel != GetCurrentTransactionNestLevel())
2548 elog(ERROR, "bogus PopOverrideSearchPath call");
2550 /* Pop the stack and free storage. */
2551 overrideStack = list_delete_first(overrideStack);
2552 list_free(entry->searchPath);
2555 /* Activate the next level down. */
2558 entry = (OverrideStackEntry *) linitial(overrideStack);
2559 activeSearchPath = entry->searchPath;
2560 activeCreationNamespace = entry->creationNamespace;
2561 activeTempCreationPending = false; /* XXX is this OK? */
2565 /* If not baseSearchPathValid, this is useless but harmless */
2566 activeSearchPath = baseSearchPath;
2567 activeCreationNamespace = baseCreationNamespace;
2568 activeTempCreationPending = baseTempCreationPending;
2574 * FindConversionByName - find a conversion by possibly qualified name
2577 FindConversionByName(List *name)
2580 char *conversion_name;
2585 /* deconstruct the name list */
2586 DeconstructQualifiedName(name, &schemaname, &conversion_name);
2590 /* use exact schema given */
2591 namespaceId = LookupExplicitNamespace(schemaname);
2592 return FindConversion(conversion_name, namespaceId);
2596 /* search for it in search path */
2597 recomputeNamespacePath();
2599 foreach(l, activeSearchPath)
2601 namespaceId = lfirst_oid(l);
2603 if (namespaceId == myTempNamespace)
2604 continue; /* do not look in temp namespace */
2606 conoid = FindConversion(conversion_name, namespaceId);
2607 if (OidIsValid(conoid))
2612 /* Not found in path */
2617 * FindDefaultConversionProc - find default encoding conversion proc
2620 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
2625 recomputeNamespacePath();
2627 foreach(l, activeSearchPath)
2629 Oid namespaceId = lfirst_oid(l);
2631 if (namespaceId == myTempNamespace)
2632 continue; /* do not look in temp namespace */
2634 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
2635 if (OidIsValid(proc))
2639 /* Not found in path */
2644 * recomputeNamespacePath - recompute path derived variables if needed.
2647 recomputeNamespacePath(void)
2649 Oid roleid = GetUserId();
2657 MemoryContext oldcxt;
2659 /* Do nothing if an override search spec is active. */
2663 /* Do nothing if path is already valid. */
2664 if (baseSearchPathValid && namespaceUser == roleid)
2667 /* Need a modifiable copy of namespace_search_path string */
2668 rawname = pstrdup(namespace_search_path);
2670 /* Parse string into list of identifiers */
2671 if (!SplitIdentifierString(rawname, ',', &namelist))
2673 /* syntax error in name list */
2674 /* this should not happen if GUC checked check_search_path */
2675 elog(ERROR, "invalid list syntax");
2679 * Convert the list of names to a list of OIDs. If any names are not
2680 * recognizable or we don't have read access, just leave them out of the
2681 * list. (We can't raise an error, since the search_path setting has
2682 * already been accepted.) Don't make duplicate entries, either.
2685 temp_missing = false;
2686 foreach(l, namelist)
2688 char *curname = (char *) lfirst(l);
2691 if (strcmp(curname, "$user") == 0)
2693 /* $user --- substitute namespace matching user name, if any */
2696 tuple = SearchSysCache(AUTHOID,
2697 ObjectIdGetDatum(roleid),
2699 if (HeapTupleIsValid(tuple))
2703 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
2704 namespaceId = GetSysCacheOid(NAMESPACENAME,
2705 CStringGetDatum(rname),
2707 ReleaseSysCache(tuple);
2708 if (OidIsValid(namespaceId) &&
2709 !list_member_oid(oidlist, namespaceId) &&
2710 pg_namespace_aclcheck(namespaceId, roleid,
2711 ACL_USAGE) == ACLCHECK_OK)
2712 oidlist = lappend_oid(oidlist, namespaceId);
2715 else if (strcmp(curname, "pg_temp") == 0)
2717 /* pg_temp --- substitute temp namespace, if any */
2718 if (OidIsValid(myTempNamespace))
2720 if (!list_member_oid(oidlist, myTempNamespace))
2721 oidlist = lappend_oid(oidlist, myTempNamespace);
2725 /* If it ought to be the creation namespace, set flag */
2727 temp_missing = true;
2732 /* normal namespace reference */
2733 namespaceId = GetSysCacheOid(NAMESPACENAME,
2734 CStringGetDatum(curname),
2736 if (OidIsValid(namespaceId) &&
2737 !list_member_oid(oidlist, namespaceId) &&
2738 pg_namespace_aclcheck(namespaceId, roleid,
2739 ACL_USAGE) == ACLCHECK_OK)
2740 oidlist = lappend_oid(oidlist, namespaceId);
2745 * Remember the first member of the explicit list. (Note: this is
2746 * nominally wrong if temp_missing, but we need it anyway to distinguish
2747 * explicit from implicit mention of pg_catalog.)
2750 firstNS = InvalidOid;
2752 firstNS = linitial_oid(oidlist);
2755 * Add any implicitly-searched namespaces to the list. Note these go on
2756 * the front, not the back; also notice that we do not check USAGE
2757 * permissions for these.
2759 if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
2760 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2762 if (OidIsValid(myTempNamespace) &&
2763 !list_member_oid(oidlist, myTempNamespace))
2764 oidlist = lcons_oid(myTempNamespace, oidlist);
2767 * Now that we've successfully built the new list of namespace OIDs, save
2768 * it in permanent storage.
2770 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2771 newpath = list_copy(oidlist);
2772 MemoryContextSwitchTo(oldcxt);
2774 /* Now safe to assign to state variables. */
2775 list_free(baseSearchPath);
2776 baseSearchPath = newpath;
2777 baseCreationNamespace = firstNS;
2778 baseTempCreationPending = temp_missing;
2780 /* Mark the path valid. */
2781 baseSearchPathValid = true;
2782 namespaceUser = roleid;
2784 /* And make it active. */
2785 activeSearchPath = baseSearchPath;
2786 activeCreationNamespace = baseCreationNamespace;
2787 activeTempCreationPending = baseTempCreationPending;
2791 list_free(namelist);
2796 * InitTempTableNamespace
2797 * Initialize temp table namespace on first use in a particular backend
2800 InitTempTableNamespace(void)
2802 char namespaceName[NAMEDATALEN];
2806 Assert(!OidIsValid(myTempNamespace));
2809 * First, do permission check to see if we are authorized to make temp
2810 * tables. We use a nonstandard error message here since "databasename:
2811 * permission denied" might be a tad cryptic.
2813 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
2814 * that's necessary since current user ID could change during the session.
2815 * But there's no need to make the namespace in the first place until a
2816 * temp table creation request is made by someone with appropriate rights.
2818 if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
2819 ACL_CREATE_TEMP) != ACLCHECK_OK)
2821 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2822 errmsg("permission denied to create temporary tables in database \"%s\"",
2823 get_database_name(MyDatabaseId))));
2825 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
2827 namespaceId = GetSysCacheOid(NAMESPACENAME,
2828 CStringGetDatum(namespaceName),
2830 if (!OidIsValid(namespaceId))
2833 * First use of this temp namespace in this database; create it. The
2834 * temp namespaces are always owned by the superuser. We leave their
2835 * permissions at default --- i.e., no access except to superuser ---
2836 * to ensure that unprivileged users can't peek at other backends'
2837 * temp tables. This works because the places that access the temp
2838 * namespace for my own backend skip permissions checks on it.
2840 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2841 /* Advance command counter to make namespace visible */
2842 CommandCounterIncrement();
2847 * If the namespace already exists, clean it out (in case the former
2848 * owner crashed without doing so).
2850 RemoveTempRelations(namespaceId);
2854 * If the corresponding toast-table namespace doesn't exist yet, create it.
2855 * (We assume there is no need to clean it out if it does exist, since
2856 * dropping a parent table should make its toast table go away.)
2858 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
2861 toastspaceId = GetSysCacheOid(NAMESPACENAME,
2862 CStringGetDatum(namespaceName),
2864 if (!OidIsValid(toastspaceId))
2866 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2867 /* Advance command counter to make namespace visible */
2868 CommandCounterIncrement();
2872 * Okay, we've prepared the temp namespace ... but it's not committed yet,
2873 * so all our work could be undone by transaction rollback. Set flag for
2874 * AtEOXact_Namespace to know what to do.
2876 myTempNamespace = namespaceId;
2877 myTempToastNamespace = toastspaceId;
2879 /* It should not be done already. */
2880 AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
2881 myTempNamespaceSubID = GetCurrentSubTransactionId();
2883 baseSearchPathValid = false; /* need to rebuild list */
2887 * End-of-transaction cleanup for namespaces.
2890 AtEOXact_Namespace(bool isCommit)
2893 * If we abort the transaction in which a temp namespace was selected,
2894 * we'll have to do any creation or cleanout work over again. So, just
2895 * forget the namespace entirely until next time. On the other hand, if
2896 * we commit then register an exit callback to clean out the temp tables
2897 * at backend shutdown. (We only want to register the callback once per
2898 * session, so this is a good place to do it.)
2900 if (myTempNamespaceSubID != InvalidSubTransactionId)
2903 on_shmem_exit(RemoveTempRelationsCallback, 0);
2906 myTempNamespace = InvalidOid;
2907 myTempToastNamespace = InvalidOid;
2908 baseSearchPathValid = false; /* need to rebuild list */
2910 myTempNamespaceSubID = InvalidSubTransactionId;
2914 * Clean up if someone failed to do PopOverrideSearchPath
2919 elog(WARNING, "leaked override search path");
2920 while (overrideStack)
2922 OverrideStackEntry *entry;
2924 entry = (OverrideStackEntry *) linitial(overrideStack);
2925 overrideStack = list_delete_first(overrideStack);
2926 list_free(entry->searchPath);
2929 /* If not baseSearchPathValid, this is useless but harmless */
2930 activeSearchPath = baseSearchPath;
2931 activeCreationNamespace = baseCreationNamespace;
2932 activeTempCreationPending = baseTempCreationPending;
2937 * AtEOSubXact_Namespace
2939 * At subtransaction commit, propagate the temp-namespace-creation
2940 * flag to the parent subtransaction.
2942 * At subtransaction abort, forget the flag if we set it up.
2945 AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
2946 SubTransactionId parentSubid)
2948 OverrideStackEntry *entry;
2950 if (myTempNamespaceSubID == mySubid)
2953 myTempNamespaceSubID = parentSubid;
2956 myTempNamespaceSubID = InvalidSubTransactionId;
2957 /* TEMP namespace creation failed, so reset state */
2958 myTempNamespace = InvalidOid;
2959 myTempToastNamespace = InvalidOid;
2960 baseSearchPathValid = false; /* need to rebuild list */
2965 * Clean up if someone failed to do PopOverrideSearchPath
2967 while (overrideStack)
2969 entry = (OverrideStackEntry *) linitial(overrideStack);
2970 if (entry->nestLevel < GetCurrentTransactionNestLevel())
2973 elog(WARNING, "leaked override search path");
2974 overrideStack = list_delete_first(overrideStack);
2975 list_free(entry->searchPath);
2979 /* Activate the next level down. */
2982 entry = (OverrideStackEntry *) linitial(overrideStack);
2983 activeSearchPath = entry->searchPath;
2984 activeCreationNamespace = entry->creationNamespace;
2985 activeTempCreationPending = false; /* XXX is this OK? */
2989 /* If not baseSearchPathValid, this is useless but harmless */
2990 activeSearchPath = baseSearchPath;
2991 activeCreationNamespace = baseCreationNamespace;
2992 activeTempCreationPending = baseTempCreationPending;
2997 * Remove all relations in the specified temp namespace.
2999 * This is called at backend shutdown (if we made any temp relations).
3000 * It is also called when we begin using a pre-existing temp namespace,
3001 * in order to clean out any relations that might have been created by
3002 * a crashed backend.
3005 RemoveTempRelations(Oid tempNamespaceId)
3007 ObjectAddress object;
3010 * We want to get rid of everything in the target namespace, but not the
3011 * namespace itself (deleting it only to recreate it later would be a
3012 * waste of cycles). We do this by finding everything that has a
3013 * dependency on the namespace.
3015 object.classId = NamespaceRelationId;
3016 object.objectId = tempNamespaceId;
3017 object.objectSubId = 0;
3019 deleteWhatDependsOn(&object, false);
3023 * Callback to remove temp relations at backend exit.
3026 RemoveTempRelationsCallback(int code, Datum arg)
3028 if (OidIsValid(myTempNamespace)) /* should always be true */
3030 /* Need to ensure we have a usable transaction. */
3031 AbortOutOfAnyTransaction();
3032 StartTransactionCommand();
3034 RemoveTempRelations(myTempNamespace);
3036 CommitTransactionCommand();
3041 * Remove all temp tables from the temporary namespace.
3044 ResetTempTableNamespace(void)
3046 if (OidIsValid(myTempNamespace))
3047 RemoveTempRelations(myTempNamespace);
3052 * Routines for handling the GUC variable 'search_path'.
3055 /* assign_hook: validate new search_path, do extra actions as needed */
3057 assign_search_path(const char *newval, bool doit, GucSource source)
3063 /* Need a modifiable copy of string */
3064 rawname = pstrdup(newval);
3066 /* Parse string into list of identifiers */
3067 if (!SplitIdentifierString(rawname, ',', &namelist))
3069 /* syntax error in name list */
3071 list_free(namelist);
3076 * If we aren't inside a transaction, we cannot do database access so
3077 * cannot verify the individual names. Must accept the list on faith.
3079 if (source >= PGC_S_INTERACTIVE && IsTransactionState())
3082 * Verify that all the names are either valid namespace names or
3083 * "$user" or "pg_temp". We do not require $user to correspond to a
3084 * valid namespace, and pg_temp might not exist yet. We do not check
3085 * for USAGE rights, either; should we?
3087 * When source == PGC_S_TEST, we are checking the argument of an ALTER
3088 * DATABASE SET or ALTER USER SET command. It could be that the
3089 * intended use of the search path is for some other database, so we
3090 * should not error out if it mentions schemas not present in the
3091 * current database. We reduce the message to NOTICE instead.
3093 foreach(l, namelist)
3095 char *curname = (char *) lfirst(l);
3097 if (strcmp(curname, "$user") == 0)
3099 if (strcmp(curname, "pg_temp") == 0)
3101 if (!SearchSysCacheExists(NAMESPACENAME,
3102 CStringGetDatum(curname),
3104 ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
3105 (errcode(ERRCODE_UNDEFINED_SCHEMA),
3106 errmsg("schema \"%s\" does not exist", curname)));
3111 list_free(namelist);
3114 * We mark the path as needing recomputation, but don't do anything until
3115 * it's needed. This avoids trying to do database access during GUC
3119 baseSearchPathValid = false;
3125 * InitializeSearchPath: initialize module during InitPostgres.
3127 * This is called after we are up enough to be able to do catalog lookups.
3130 InitializeSearchPath(void)
3132 if (IsBootstrapProcessingMode())
3135 * In bootstrap mode, the search path must be 'pg_catalog' so that
3136 * tables are created in the proper namespace; ignore the GUC setting.
3138 MemoryContext oldcxt;
3140 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
3141 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
3142 MemoryContextSwitchTo(oldcxt);
3143 baseCreationNamespace = PG_CATALOG_NAMESPACE;
3144 baseTempCreationPending = false;
3145 baseSearchPathValid = true;
3146 namespaceUser = GetUserId();
3147 activeSearchPath = baseSearchPath;
3148 activeCreationNamespace = baseCreationNamespace;
3149 activeTempCreationPending = baseTempCreationPending;
3154 * In normal mode, arrange for a callback on any syscache invalidation
3155 * of pg_namespace rows.
3157 CacheRegisterSyscacheCallback(NAMESPACEOID,
3160 /* Force search path to be recomputed on next use */
3161 baseSearchPathValid = false;
3167 * Syscache inval callback function
3170 NamespaceCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
3172 /* Force search path to be recomputed on next use */
3173 baseSearchPathValid = false;
3177 * Fetch the active search path. The return value is a palloc'ed list
3178 * of OIDs; the caller is responsible for freeing this storage as
3181 * The returned list includes the implicitly-prepended namespaces only if
3182 * includeImplicit is true.
3184 * Note: calling this may result in a CommandCounterIncrement operation,
3185 * if we have to create or clean out the temp namespace.
3188 fetch_search_path(bool includeImplicit)
3192 recomputeNamespacePath();
3195 * If the temp namespace should be first, force it to exist. This is so
3196 * that callers can trust the result to reflect the actual default
3197 * creation namespace. It's a bit bogus to do this here, since
3198 * current_schema() is supposedly a stable function without side-effects,
3199 * but the alternatives seem worse.
3201 if (activeTempCreationPending)
3203 InitTempTableNamespace();
3204 recomputeNamespacePath();
3207 result = list_copy(activeSearchPath);
3208 if (!includeImplicit)
3210 while (result && linitial_oid(result) != activeCreationNamespace)
3211 result = list_delete_first(result);
3218 * Fetch the active search path into a caller-allocated array of OIDs.
3219 * Returns the number of path entries. (If this is more than sarray_len,
3220 * then the data didn't fit and is not all stored.)
3222 * The returned list always includes the implicitly-prepended namespaces,
3223 * but never includes the temp namespace. (This is suitable for existing
3224 * users, which would want to ignore the temp namespace anyway.) This
3225 * definition allows us to not worry about initializing the temp namespace.
3228 fetch_search_path_array(Oid *sarray, int sarray_len)
3233 recomputeNamespacePath();
3235 foreach(l, activeSearchPath)
3237 Oid namespaceId = lfirst_oid(l);
3239 if (namespaceId == myTempNamespace)
3240 continue; /* do not include temp namespace */
3242 if (count < sarray_len)
3243 sarray[count] = namespaceId;
3252 * Export the FooIsVisible functions as SQL-callable functions.
3254 * Note: as of Postgres 8.4, these will silently return NULL if called on
3255 * a nonexistent object OID, rather than failing. This is to avoid race
3256 * condition errors when a query that's scanning a catalog using an MVCC
3257 * snapshot uses one of these functions. The underlying IsVisible functions
3258 * operate on SnapshotNow semantics and so might see the object as already
3259 * gone when it's still visible to the MVCC snapshot. (There is no race
3260 * condition in the current coding because we don't accept sinval messages
3261 * between the SearchSysCacheExists test and the subsequent lookup.)
3265 pg_table_is_visible(PG_FUNCTION_ARGS)
3267 Oid oid = PG_GETARG_OID(0);
3269 if (!SearchSysCacheExists(RELOID,
3270 ObjectIdGetDatum(oid),
3274 PG_RETURN_BOOL(RelationIsVisible(oid));
3278 pg_type_is_visible(PG_FUNCTION_ARGS)
3280 Oid oid = PG_GETARG_OID(0);
3282 if (!SearchSysCacheExists(TYPEOID,
3283 ObjectIdGetDatum(oid),
3287 PG_RETURN_BOOL(TypeIsVisible(oid));
3291 pg_function_is_visible(PG_FUNCTION_ARGS)
3293 Oid oid = PG_GETARG_OID(0);
3295 if (!SearchSysCacheExists(PROCOID,
3296 ObjectIdGetDatum(oid),
3300 PG_RETURN_BOOL(FunctionIsVisible(oid));
3304 pg_operator_is_visible(PG_FUNCTION_ARGS)
3306 Oid oid = PG_GETARG_OID(0);
3308 if (!SearchSysCacheExists(OPEROID,
3309 ObjectIdGetDatum(oid),
3313 PG_RETURN_BOOL(OperatorIsVisible(oid));
3317 pg_opclass_is_visible(PG_FUNCTION_ARGS)
3319 Oid oid = PG_GETARG_OID(0);
3321 if (!SearchSysCacheExists(CLAOID,
3322 ObjectIdGetDatum(oid),
3326 PG_RETURN_BOOL(OpclassIsVisible(oid));
3330 pg_conversion_is_visible(PG_FUNCTION_ARGS)
3332 Oid oid = PG_GETARG_OID(0);
3334 if (!SearchSysCacheExists(CONVOID,
3335 ObjectIdGetDatum(oid),
3339 PG_RETURN_BOOL(ConversionIsVisible(oid));
3343 pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
3345 Oid oid = PG_GETARG_OID(0);
3347 if (!SearchSysCacheExists(TSPARSEROID,
3348 ObjectIdGetDatum(oid),
3352 PG_RETURN_BOOL(TSParserIsVisible(oid));
3356 pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
3358 Oid oid = PG_GETARG_OID(0);
3360 if (!SearchSysCacheExists(TSDICTOID,
3361 ObjectIdGetDatum(oid),
3365 PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
3369 pg_ts_template_is_visible(PG_FUNCTION_ARGS)
3371 Oid oid = PG_GETARG_OID(0);
3373 if (!SearchSysCacheExists(TSTEMPLATEOID,
3374 ObjectIdGetDatum(oid),
3378 PG_RETURN_BOOL(TSTemplateIsVisible(oid));
3382 pg_ts_config_is_visible(PG_FUNCTION_ARGS)
3384 Oid oid = PG_GETARG_OID(0);
3386 if (!SearchSysCacheExists(TSCONFIGOID,
3387 ObjectIdGetDatum(oid),
3391 PG_RETURN_BOOL(TSConfigIsVisible(oid));
3395 pg_my_temp_schema(PG_FUNCTION_ARGS)
3397 PG_RETURN_OID(myTempNamespace);
3401 pg_is_other_temp_schema(PG_FUNCTION_ARGS)
3403 Oid oid = PG_GETARG_OID(0);
3405 PG_RETURN_BOOL(isOtherTempNamespace(oid));