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.112 2008/09/09 18:58:08 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 * We search a single namespace if the function name is qualified, else
575 * all namespaces in the search path. The return list will never contain
576 * multiple entries with identical argument lists --- in the multiple-
577 * namespace case, we arrange for entries in earlier namespaces to mask
578 * identical entries in later namespaces. We also arrange for non-variadic
579 * functions to mask variadic ones if the expanded argument list is the same.
582 FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
584 FuncCandidateList resultList = NULL;
585 bool any_variadic = false;
592 /* check for caller error */
593 Assert(nargs >= 0 || !expand_variadic);
595 /* deconstruct the name list */
596 DeconstructQualifiedName(names, &schemaname, &funcname);
600 /* use exact schema given */
601 namespaceId = LookupExplicitNamespace(schemaname);
605 /* flag to indicate we need namespace search */
606 namespaceId = InvalidOid;
607 recomputeNamespacePath();
610 /* Search syscache by name only */
611 catlist = SearchSysCacheList(PROCNAMEARGSNSP, 1,
612 CStringGetDatum(funcname),
615 for (i = 0; i < catlist->n_members; i++)
617 HeapTuple proctup = &catlist->members[i]->tuple;
618 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
619 int pronargs = procform->pronargs;
624 FuncCandidateList newResult;
627 * Check if function is variadic, and get variadic element type if so.
628 * If expand_variadic is false, we should just ignore variadic-ness.
632 va_elem_type = procform->provariadic;
633 variadic = OidIsValid(va_elem_type);
637 va_elem_type = InvalidOid;
641 /* Ignore if it doesn't match requested argument count */
643 (variadic ? (pronargs > nargs) : (pronargs != nargs)))
646 if (OidIsValid(namespaceId))
648 /* Consider only procs in specified namespace */
649 if (procform->pronamespace != namespaceId)
655 * Consider only procs that are in the search path and are not in
656 * the temp namespace.
660 foreach(nsp, activeSearchPath)
662 if (procform->pronamespace == lfirst_oid(nsp) &&
663 procform->pronamespace != myTempNamespace)
668 continue; /* proc is not in search path */
672 * We must compute the effective argument list so that we can easily
673 * compare it to earlier results. We waste a palloc cycle if it gets
674 * masked by an earlier result, but really that's a pretty infrequent
675 * case so it's not worth worrying about.
677 effective_nargs = Max(pronargs, nargs);
678 newResult = (FuncCandidateList)
679 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
680 + effective_nargs * sizeof(Oid));
681 newResult->pathpos = pathpos;
682 newResult->oid = HeapTupleGetOid(proctup);
683 newResult->nargs = effective_nargs;
684 memcpy(newResult->args, procform->proargtypes.values,
685 pronargs * sizeof(Oid));
690 newResult->nvargs = effective_nargs - pronargs + 1;
691 /* Expand variadic argument into N copies of element type */
692 for (i = pronargs - 1; i < effective_nargs; i++)
693 newResult->args[i] = va_elem_type;
696 newResult->nvargs = 0;
699 * Does it have the same arguments as something we already accepted?
700 * If so, decide which one to keep. We can skip this check for the
701 * single-namespace case if no variadic match has been made, since
702 * then the unique index on pg_proc guarantees all the matches have
703 * different argument lists.
705 if (any_variadic || !OidIsValid(namespaceId))
708 * If we have an ordered list from SearchSysCacheList (the normal
709 * case), then any conflicting proc must immediately adjoin this
710 * one in the list, so we only need to look at the newest result
711 * item. If we have an unordered list, we have to scan the whole
712 * result list. Also, if either the current candidate or any
713 * previous candidate is a variadic match, we can't assume that
714 * conflicts are adjacent.
718 FuncCandidateList prevResult;
720 if (catlist->ordered && !any_variadic)
722 if (effective_nargs == resultList->nargs &&
723 memcmp(newResult->args,
725 effective_nargs * sizeof(Oid)) == 0)
726 prevResult = resultList;
732 for (prevResult = resultList;
734 prevResult = prevResult->next)
736 if (effective_nargs == prevResult->nargs &&
737 memcmp(newResult->args,
739 effective_nargs * sizeof(Oid)) == 0)
746 * We have a match with a previous result. Prefer the
747 * one that's earlier in the search path.
749 if (pathpos > prevResult->pathpos)
752 continue; /* keep previous result */
754 else if (pathpos == prevResult->pathpos)
757 * With variadic functions we could have, for example,
758 * both foo(numeric) and foo(variadic numeric[]) in
759 * the same namespace; if so we prefer the
760 * non-variadic match on efficiency grounds. It's
761 * also possible to have conflicting variadic
762 * functions, such as foo(numeric, variadic numeric[])
763 * and foo(variadic numeric[]). If you're silly
764 * enough to do that, we throw an error. (XXX It'd be
765 * better to detect such conflicts when the functions
770 if (prevResult->nvargs > 0)
772 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
773 errmsg("variadic function %s conflicts with another",
774 func_signature_string(names, pronargs,
775 procform->proargtypes.values))));
776 /* else, previous result wasn't variadic */
778 continue; /* keep previous result */
780 /* non-variadic can replace a previous variadic */
781 Assert(prevResult->nvargs > 0);
783 /* replace previous result */
784 prevResult->pathpos = pathpos;
785 prevResult->oid = newResult->oid;
786 prevResult->nvargs = newResult->nvargs;
788 continue; /* args are same, of course */
794 * Okay to add it to result list
796 newResult->next = resultList;
797 resultList = newResult;
800 ReleaseSysCacheList(catlist);
807 * Determine whether a function (identified by OID) is visible in the
808 * current search path. Visible means "would be found by searching
809 * for the unqualified function name with exact argument matches".
812 FunctionIsVisible(Oid funcid)
815 Form_pg_proc procform;
819 proctup = SearchSysCache(PROCOID,
820 ObjectIdGetDatum(funcid),
822 if (!HeapTupleIsValid(proctup))
823 elog(ERROR, "cache lookup failed for function %u", funcid);
824 procform = (Form_pg_proc) GETSTRUCT(proctup);
826 recomputeNamespacePath();
829 * Quick check: if it ain't in the path at all, it ain't visible. Items in
830 * the system namespace are surely in the path and so we needn't even do
831 * list_member_oid() for them.
833 pronamespace = procform->pronamespace;
834 if (pronamespace != PG_CATALOG_NAMESPACE &&
835 !list_member_oid(activeSearchPath, pronamespace))
840 * If it is in the path, it might still not be visible; it could be
841 * hidden by another proc of the same name and arguments earlier in
842 * the path. So we must do a slow check to see if this is the same
843 * proc that would be found by FuncnameGetCandidates.
845 char *proname = NameStr(procform->proname);
846 int nargs = procform->pronargs;
847 FuncCandidateList clist;
851 clist = FuncnameGetCandidates(list_make1(makeString(proname)),
854 for (; clist; clist = clist->next)
856 if (memcmp(clist->args, procform->proargtypes.values,
857 nargs * sizeof(Oid)) == 0)
859 /* Found the expected entry; is it the right proc? */
860 visible = (clist->oid == funcid);
866 ReleaseSysCache(proctup);
874 * Given a possibly-qualified operator name and exact input datatypes,
875 * look up the operator. Returns InvalidOid if not found.
877 * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
880 * If the operator name is not schema-qualified, it is sought in the current
881 * namespace search path.
884 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
891 /* deconstruct the name list */
892 DeconstructQualifiedName(names, &schemaname, &opername);
896 /* search only in exact schema given */
900 namespaceId = LookupExplicitNamespace(schemaname);
901 opertup = SearchSysCache(OPERNAMENSP,
902 CStringGetDatum(opername),
903 ObjectIdGetDatum(oprleft),
904 ObjectIdGetDatum(oprright),
905 ObjectIdGetDatum(namespaceId));
906 if (HeapTupleIsValid(opertup))
908 Oid result = HeapTupleGetOid(opertup);
910 ReleaseSysCache(opertup);
916 /* Search syscache by name and argument types */
917 catlist = SearchSysCacheList(OPERNAMENSP, 3,
918 CStringGetDatum(opername),
919 ObjectIdGetDatum(oprleft),
920 ObjectIdGetDatum(oprright),
923 if (catlist->n_members == 0)
925 /* no hope, fall out early */
926 ReleaseSysCacheList(catlist);
931 * We have to find the list member that is first in the search path, if
932 * there's more than one. This doubly-nested loop looks ugly, but in
933 * practice there should usually be few catlist members.
935 recomputeNamespacePath();
937 foreach(l, activeSearchPath)
939 Oid namespaceId = lfirst_oid(l);
942 if (namespaceId == myTempNamespace)
943 continue; /* do not look in temp namespace */
945 for (i = 0; i < catlist->n_members; i++)
947 HeapTuple opertup = &catlist->members[i]->tuple;
948 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
950 if (operform->oprnamespace == namespaceId)
952 Oid result = HeapTupleGetOid(opertup);
954 ReleaseSysCacheList(catlist);
960 ReleaseSysCacheList(catlist);
965 * OpernameGetCandidates
966 * Given a possibly-qualified operator name and operator kind,
967 * retrieve a list of the possible matches.
969 * If oprkind is '\0', we return all operators matching the given name,
970 * regardless of arguments.
972 * We search a single namespace if the operator name is qualified, else
973 * all namespaces in the search path. The return list will never contain
974 * multiple entries with identical argument lists --- in the multiple-
975 * namespace case, we arrange for entries in earlier namespaces to mask
976 * identical entries in later namespaces.
978 * The returned items always have two args[] entries --- one or the other
979 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
982 OpernameGetCandidates(List *names, char oprkind)
984 FuncCandidateList resultList = NULL;
985 char *resultSpace = NULL;
993 /* deconstruct the name list */
994 DeconstructQualifiedName(names, &schemaname, &opername);
998 /* use exact schema given */
999 namespaceId = LookupExplicitNamespace(schemaname);
1003 /* flag to indicate we need namespace search */
1004 namespaceId = InvalidOid;
1005 recomputeNamespacePath();
1008 /* Search syscache by name only */
1009 catlist = SearchSysCacheList(OPERNAMENSP, 1,
1010 CStringGetDatum(opername),
1014 * In typical scenarios, most if not all of the operators found by the
1015 * catcache search will end up getting returned; and there can be quite a
1016 * few, for common operator names such as '=' or '+'. To reduce the time
1017 * spent in palloc, we allocate the result space as an array large enough
1018 * to hold all the operators. The original coding of this routine did a
1019 * separate palloc for each operator, but profiling revealed that the
1020 * pallocs used an unreasonably large fraction of parsing time.
1022 #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
1024 if (catlist->n_members > 0)
1025 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1027 for (i = 0; i < catlist->n_members; i++)
1029 HeapTuple opertup = &catlist->members[i]->tuple;
1030 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1032 FuncCandidateList newResult;
1034 /* Ignore operators of wrong kind, if specific kind requested */
1035 if (oprkind && operform->oprkind != oprkind)
1038 if (OidIsValid(namespaceId))
1040 /* Consider only opers in specified namespace */
1041 if (operform->oprnamespace != namespaceId)
1043 /* No need to check args, they must all be different */
1048 * Consider only opers that are in the search path and are not in
1049 * the temp namespace.
1053 foreach(nsp, activeSearchPath)
1055 if (operform->oprnamespace == lfirst_oid(nsp) &&
1056 operform->oprnamespace != myTempNamespace)
1061 continue; /* oper is not in search path */
1064 * Okay, it's in the search path, but does it have the same
1065 * arguments as something we already accepted? If so, keep only
1066 * the one that appears earlier in the search path.
1068 * If we have an ordered list from SearchSysCacheList (the normal
1069 * case), then any conflicting oper must immediately adjoin this
1070 * one in the list, so we only need to look at the newest result
1071 * item. If we have an unordered list, we have to scan the whole
1076 FuncCandidateList prevResult;
1078 if (catlist->ordered)
1080 if (operform->oprleft == resultList->args[0] &&
1081 operform->oprright == resultList->args[1])
1082 prevResult = resultList;
1088 for (prevResult = resultList;
1090 prevResult = prevResult->next)
1092 if (operform->oprleft == prevResult->args[0] &&
1093 operform->oprright == prevResult->args[1])
1099 /* We have a match with a previous result */
1100 Assert(pathpos != prevResult->pathpos);
1101 if (pathpos > prevResult->pathpos)
1102 continue; /* keep previous result */
1103 /* replace previous result */
1104 prevResult->pathpos = pathpos;
1105 prevResult->oid = HeapTupleGetOid(opertup);
1106 continue; /* args are same, of course */
1112 * Okay to add it to result list
1114 newResult = (FuncCandidateList) (resultSpace + nextResult);
1115 nextResult += SPACE_PER_OP;
1117 newResult->pathpos = pathpos;
1118 newResult->oid = HeapTupleGetOid(opertup);
1119 newResult->nargs = 2;
1120 newResult->nvargs = 0;
1121 newResult->args[0] = operform->oprleft;
1122 newResult->args[1] = operform->oprright;
1123 newResult->next = resultList;
1124 resultList = newResult;
1127 ReleaseSysCacheList(catlist);
1134 * Determine whether an operator (identified by OID) is visible in the
1135 * current search path. Visible means "would be found by searching
1136 * for the unqualified operator name with exact argument matches".
1139 OperatorIsVisible(Oid oprid)
1142 Form_pg_operator oprform;
1146 oprtup = SearchSysCache(OPEROID,
1147 ObjectIdGetDatum(oprid),
1149 if (!HeapTupleIsValid(oprtup))
1150 elog(ERROR, "cache lookup failed for operator %u", oprid);
1151 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
1153 recomputeNamespacePath();
1156 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1157 * the system namespace are surely in the path and so we needn't even do
1158 * list_member_oid() for them.
1160 oprnamespace = oprform->oprnamespace;
1161 if (oprnamespace != PG_CATALOG_NAMESPACE &&
1162 !list_member_oid(activeSearchPath, oprnamespace))
1167 * If it is in the path, it might still not be visible; it could be
1168 * hidden by another operator of the same name and arguments earlier
1169 * in the path. So we must do a slow check to see if this is the same
1170 * operator that would be found by OpernameGetOprId.
1172 char *oprname = NameStr(oprform->oprname);
1174 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
1175 oprform->oprleft, oprform->oprright)
1179 ReleaseSysCache(oprtup);
1186 * OpclassnameGetOpcid
1187 * Try to resolve an unqualified index opclass name.
1188 * Returns OID if opclass found in search path, else InvalidOid.
1190 * This is essentially the same as TypenameGetTypid, but we have to have
1191 * an extra argument for the index AM OID.
1194 OpclassnameGetOpcid(Oid amid, const char *opcname)
1199 recomputeNamespacePath();
1201 foreach(l, activeSearchPath)
1203 Oid namespaceId = lfirst_oid(l);
1205 if (namespaceId == myTempNamespace)
1206 continue; /* do not look in temp namespace */
1208 opcid = GetSysCacheOid(CLAAMNAMENSP,
1209 ObjectIdGetDatum(amid),
1210 PointerGetDatum(opcname),
1211 ObjectIdGetDatum(namespaceId),
1213 if (OidIsValid(opcid))
1217 /* Not found in path */
1223 * Determine whether an opclass (identified by OID) is visible in the
1224 * current search path. Visible means "would be found by searching
1225 * for the unqualified opclass name".
1228 OpclassIsVisible(Oid opcid)
1231 Form_pg_opclass opcform;
1235 opctup = SearchSysCache(CLAOID,
1236 ObjectIdGetDatum(opcid),
1238 if (!HeapTupleIsValid(opctup))
1239 elog(ERROR, "cache lookup failed for opclass %u", opcid);
1240 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1242 recomputeNamespacePath();
1245 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1246 * the system namespace are surely in the path and so we needn't even do
1247 * list_member_oid() for them.
1249 opcnamespace = opcform->opcnamespace;
1250 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1251 !list_member_oid(activeSearchPath, opcnamespace))
1256 * If it is in the path, it might still not be visible; it could be
1257 * hidden by another opclass of the same name earlier in the path. So
1258 * we must do a slow check to see if this opclass would be found by
1259 * OpclassnameGetOpcid.
1261 char *opcname = NameStr(opcform->opcname);
1263 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
1266 ReleaseSysCache(opctup);
1272 * OpfamilynameGetOpfid
1273 * Try to resolve an unqualified index opfamily name.
1274 * Returns OID if opfamily found in search path, else InvalidOid.
1276 * This is essentially the same as TypenameGetTypid, but we have to have
1277 * an extra argument for the index AM OID.
1280 OpfamilynameGetOpfid(Oid amid, const char *opfname)
1285 recomputeNamespacePath();
1287 foreach(l, activeSearchPath)
1289 Oid namespaceId = lfirst_oid(l);
1291 if (namespaceId == myTempNamespace)
1292 continue; /* do not look in temp namespace */
1294 opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
1295 ObjectIdGetDatum(amid),
1296 PointerGetDatum(opfname),
1297 ObjectIdGetDatum(namespaceId),
1299 if (OidIsValid(opfid))
1303 /* Not found in path */
1309 * Determine whether an opfamily (identified by OID) is visible in the
1310 * current search path. Visible means "would be found by searching
1311 * for the unqualified opfamily name".
1314 OpfamilyIsVisible(Oid opfid)
1317 Form_pg_opfamily opfform;
1321 opftup = SearchSysCache(OPFAMILYOID,
1322 ObjectIdGetDatum(opfid),
1324 if (!HeapTupleIsValid(opftup))
1325 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
1326 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
1328 recomputeNamespacePath();
1331 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1332 * the system namespace are surely in the path and so we needn't even do
1333 * list_member_oid() for them.
1335 opfnamespace = opfform->opfnamespace;
1336 if (opfnamespace != PG_CATALOG_NAMESPACE &&
1337 !list_member_oid(activeSearchPath, opfnamespace))
1342 * If it is in the path, it might still not be visible; it could be
1343 * hidden by another opfamily of the same name earlier in the path. So
1344 * we must do a slow check to see if this opfamily would be found by
1345 * OpfamilynameGetOpfid.
1347 char *opfname = NameStr(opfform->opfname);
1349 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
1352 ReleaseSysCache(opftup);
1358 * ConversionGetConid
1359 * Try to resolve an unqualified conversion name.
1360 * Returns OID if conversion found in search path, else InvalidOid.
1362 * This is essentially the same as RelnameGetRelid.
1365 ConversionGetConid(const char *conname)
1370 recomputeNamespacePath();
1372 foreach(l, activeSearchPath)
1374 Oid namespaceId = lfirst_oid(l);
1376 if (namespaceId == myTempNamespace)
1377 continue; /* do not look in temp namespace */
1379 conid = GetSysCacheOid(CONNAMENSP,
1380 PointerGetDatum(conname),
1381 ObjectIdGetDatum(namespaceId),
1383 if (OidIsValid(conid))
1387 /* Not found in path */
1392 * ConversionIsVisible
1393 * Determine whether a conversion (identified by OID) is visible in the
1394 * current search path. Visible means "would be found by searching
1395 * for the unqualified conversion name".
1398 ConversionIsVisible(Oid conid)
1401 Form_pg_conversion conform;
1405 contup = SearchSysCache(CONVOID,
1406 ObjectIdGetDatum(conid),
1408 if (!HeapTupleIsValid(contup))
1409 elog(ERROR, "cache lookup failed for conversion %u", conid);
1410 conform = (Form_pg_conversion) GETSTRUCT(contup);
1412 recomputeNamespacePath();
1415 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1416 * the system namespace are surely in the path and so we needn't even do
1417 * list_member_oid() for them.
1419 connamespace = conform->connamespace;
1420 if (connamespace != PG_CATALOG_NAMESPACE &&
1421 !list_member_oid(activeSearchPath, connamespace))
1426 * If it is in the path, it might still not be visible; it could be
1427 * hidden by another conversion of the same name earlier in the path.
1428 * So we must do a slow check to see if this conversion would be found
1429 * by ConversionGetConid.
1431 char *conname = NameStr(conform->conname);
1433 visible = (ConversionGetConid(conname) == conid);
1436 ReleaseSysCache(contup);
1442 * TSParserGetPrsid - find a TS parser by possibly qualified name
1444 * If not found, returns InvalidOid if failOK, else throws error
1447 TSParserGetPrsid(List *names, bool failOK)
1452 Oid prsoid = InvalidOid;
1455 /* deconstruct the name list */
1456 DeconstructQualifiedName(names, &schemaname, &parser_name);
1460 /* use exact schema given */
1461 namespaceId = LookupExplicitNamespace(schemaname);
1462 prsoid = GetSysCacheOid(TSPARSERNAMENSP,
1463 PointerGetDatum(parser_name),
1464 ObjectIdGetDatum(namespaceId),
1469 /* search for it in search path */
1470 recomputeNamespacePath();
1472 foreach(l, activeSearchPath)
1474 namespaceId = lfirst_oid(l);
1476 if (namespaceId == myTempNamespace)
1477 continue; /* do not look in temp namespace */
1479 prsoid = GetSysCacheOid(TSPARSERNAMENSP,
1480 PointerGetDatum(parser_name),
1481 ObjectIdGetDatum(namespaceId),
1483 if (OidIsValid(prsoid))
1488 if (!OidIsValid(prsoid) && !failOK)
1490 (errcode(ERRCODE_UNDEFINED_OBJECT),
1491 errmsg("text search parser \"%s\" does not exist",
1492 NameListToString(names))));
1499 * Determine whether a parser (identified by OID) is visible in the
1500 * current search path. Visible means "would be found by searching
1501 * for the unqualified parser name".
1504 TSParserIsVisible(Oid prsId)
1507 Form_pg_ts_parser form;
1511 tup = SearchSysCache(TSPARSEROID,
1512 ObjectIdGetDatum(prsId),
1514 if (!HeapTupleIsValid(tup))
1515 elog(ERROR, "cache lookup failed for text search parser %u", prsId);
1516 form = (Form_pg_ts_parser) GETSTRUCT(tup);
1518 recomputeNamespacePath();
1521 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1522 * the system namespace are surely in the path and so we needn't even do
1523 * list_member_oid() for them.
1525 namespace = form->prsnamespace;
1526 if (namespace != PG_CATALOG_NAMESPACE &&
1527 !list_member_oid(activeSearchPath, namespace))
1532 * If it is in the path, it might still not be visible; it could be
1533 * hidden by another parser of the same name earlier in the path. So
1534 * we must do a slow check for conflicting parsers.
1536 char *name = NameStr(form->prsname);
1540 foreach(l, activeSearchPath)
1542 Oid namespaceId = lfirst_oid(l);
1544 if (namespaceId == myTempNamespace)
1545 continue; /* do not look in temp namespace */
1547 if (namespaceId == namespace)
1549 /* Found it first in path */
1553 if (SearchSysCacheExists(TSPARSERNAMENSP,
1554 PointerGetDatum(name),
1555 ObjectIdGetDatum(namespaceId),
1558 /* Found something else first in path */
1564 ReleaseSysCache(tup);
1570 * TSDictionaryGetDictid - find a TS dictionary by possibly qualified name
1572 * If not found, returns InvalidOid if failOK, else throws error
1575 TSDictionaryGetDictid(List *names, bool failOK)
1580 Oid dictoid = InvalidOid;
1583 /* deconstruct the name list */
1584 DeconstructQualifiedName(names, &schemaname, &dict_name);
1588 /* use exact schema given */
1589 namespaceId = LookupExplicitNamespace(schemaname);
1590 dictoid = GetSysCacheOid(TSDICTNAMENSP,
1591 PointerGetDatum(dict_name),
1592 ObjectIdGetDatum(namespaceId),
1597 /* search for it in search path */
1598 recomputeNamespacePath();
1600 foreach(l, activeSearchPath)
1602 namespaceId = lfirst_oid(l);
1604 if (namespaceId == myTempNamespace)
1605 continue; /* do not look in temp namespace */
1607 dictoid = GetSysCacheOid(TSDICTNAMENSP,
1608 PointerGetDatum(dict_name),
1609 ObjectIdGetDatum(namespaceId),
1611 if (OidIsValid(dictoid))
1616 if (!OidIsValid(dictoid) && !failOK)
1618 (errcode(ERRCODE_UNDEFINED_OBJECT),
1619 errmsg("text search dictionary \"%s\" does not exist",
1620 NameListToString(names))));
1626 * TSDictionaryIsVisible
1627 * Determine whether a dictionary (identified by OID) is visible in the
1628 * current search path. Visible means "would be found by searching
1629 * for the unqualified dictionary name".
1632 TSDictionaryIsVisible(Oid dictId)
1635 Form_pg_ts_dict form;
1639 tup = SearchSysCache(TSDICTOID,
1640 ObjectIdGetDatum(dictId),
1642 if (!HeapTupleIsValid(tup))
1643 elog(ERROR, "cache lookup failed for text search dictionary %u",
1645 form = (Form_pg_ts_dict) GETSTRUCT(tup);
1647 recomputeNamespacePath();
1650 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1651 * the system namespace are surely in the path and so we needn't even do
1652 * list_member_oid() for them.
1654 namespace = form->dictnamespace;
1655 if (namespace != PG_CATALOG_NAMESPACE &&
1656 !list_member_oid(activeSearchPath, namespace))
1661 * If it is in the path, it might still not be visible; it could be
1662 * hidden by another dictionary of the same name earlier in the path.
1663 * So we must do a slow check for conflicting dictionaries.
1665 char *name = NameStr(form->dictname);
1669 foreach(l, activeSearchPath)
1671 Oid namespaceId = lfirst_oid(l);
1673 if (namespaceId == myTempNamespace)
1674 continue; /* do not look in temp namespace */
1676 if (namespaceId == namespace)
1678 /* Found it first in path */
1682 if (SearchSysCacheExists(TSDICTNAMENSP,
1683 PointerGetDatum(name),
1684 ObjectIdGetDatum(namespaceId),
1687 /* Found something else first in path */
1693 ReleaseSysCache(tup);
1699 * TSTemplateGetTmplid - find a TS template by possibly qualified name
1701 * If not found, returns InvalidOid if failOK, else throws error
1704 TSTemplateGetTmplid(List *names, bool failOK)
1707 char *template_name;
1709 Oid tmploid = InvalidOid;
1712 /* deconstruct the name list */
1713 DeconstructQualifiedName(names, &schemaname, &template_name);
1717 /* use exact schema given */
1718 namespaceId = LookupExplicitNamespace(schemaname);
1719 tmploid = GetSysCacheOid(TSTEMPLATENAMENSP,
1720 PointerGetDatum(template_name),
1721 ObjectIdGetDatum(namespaceId),
1726 /* search for it in search path */
1727 recomputeNamespacePath();
1729 foreach(l, activeSearchPath)
1731 namespaceId = lfirst_oid(l);
1733 if (namespaceId == myTempNamespace)
1734 continue; /* do not look in temp namespace */
1736 tmploid = GetSysCacheOid(TSTEMPLATENAMENSP,
1737 PointerGetDatum(template_name),
1738 ObjectIdGetDatum(namespaceId),
1740 if (OidIsValid(tmploid))
1745 if (!OidIsValid(tmploid) && !failOK)
1747 (errcode(ERRCODE_UNDEFINED_OBJECT),
1748 errmsg("text search template \"%s\" does not exist",
1749 NameListToString(names))));
1755 * TSTemplateIsVisible
1756 * Determine whether a template (identified by OID) is visible in the
1757 * current search path. Visible means "would be found by searching
1758 * for the unqualified template name".
1761 TSTemplateIsVisible(Oid tmplId)
1764 Form_pg_ts_template form;
1768 tup = SearchSysCache(TSTEMPLATEOID,
1769 ObjectIdGetDatum(tmplId),
1771 if (!HeapTupleIsValid(tup))
1772 elog(ERROR, "cache lookup failed for text search template %u", tmplId);
1773 form = (Form_pg_ts_template) GETSTRUCT(tup);
1775 recomputeNamespacePath();
1778 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1779 * the system namespace are surely in the path and so we needn't even do
1780 * list_member_oid() for them.
1782 namespace = form->tmplnamespace;
1783 if (namespace != PG_CATALOG_NAMESPACE &&
1784 !list_member_oid(activeSearchPath, namespace))
1789 * If it is in the path, it might still not be visible; it could be
1790 * hidden by another template of the same name earlier in the path. So
1791 * we must do a slow check for conflicting templates.
1793 char *name = NameStr(form->tmplname);
1797 foreach(l, activeSearchPath)
1799 Oid namespaceId = lfirst_oid(l);
1801 if (namespaceId == myTempNamespace)
1802 continue; /* do not look in temp namespace */
1804 if (namespaceId == namespace)
1806 /* Found it first in path */
1810 if (SearchSysCacheExists(TSTEMPLATENAMENSP,
1811 PointerGetDatum(name),
1812 ObjectIdGetDatum(namespaceId),
1815 /* Found something else first in path */
1821 ReleaseSysCache(tup);
1827 * TSConfigGetCfgid - find a TS config by possibly qualified name
1829 * If not found, returns InvalidOid if failOK, else throws error
1832 TSConfigGetCfgid(List *names, bool failOK)
1837 Oid cfgoid = InvalidOid;
1840 /* deconstruct the name list */
1841 DeconstructQualifiedName(names, &schemaname, &config_name);
1845 /* use exact schema given */
1846 namespaceId = LookupExplicitNamespace(schemaname);
1847 cfgoid = GetSysCacheOid(TSCONFIGNAMENSP,
1848 PointerGetDatum(config_name),
1849 ObjectIdGetDatum(namespaceId),
1854 /* search for it in search path */
1855 recomputeNamespacePath();
1857 foreach(l, activeSearchPath)
1859 namespaceId = lfirst_oid(l);
1861 if (namespaceId == myTempNamespace)
1862 continue; /* do not look in temp namespace */
1864 cfgoid = GetSysCacheOid(TSCONFIGNAMENSP,
1865 PointerGetDatum(config_name),
1866 ObjectIdGetDatum(namespaceId),
1868 if (OidIsValid(cfgoid))
1873 if (!OidIsValid(cfgoid) && !failOK)
1875 (errcode(ERRCODE_UNDEFINED_OBJECT),
1876 errmsg("text search configuration \"%s\" does not exist",
1877 NameListToString(names))));
1884 * Determine whether a text search configuration (identified by OID)
1885 * is visible in the current search path. Visible means "would be found
1886 * by searching for the unqualified text search configuration name".
1889 TSConfigIsVisible(Oid cfgid)
1892 Form_pg_ts_config form;
1896 tup = SearchSysCache(TSCONFIGOID,
1897 ObjectIdGetDatum(cfgid),
1899 if (!HeapTupleIsValid(tup))
1900 elog(ERROR, "cache lookup failed for text search configuration %u",
1902 form = (Form_pg_ts_config) GETSTRUCT(tup);
1904 recomputeNamespacePath();
1907 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1908 * the system namespace are surely in the path and so we needn't even do
1909 * list_member_oid() for them.
1911 namespace = form->cfgnamespace;
1912 if (namespace != PG_CATALOG_NAMESPACE &&
1913 !list_member_oid(activeSearchPath, namespace))
1918 * If it is in the path, it might still not be visible; it could be
1919 * hidden by another configuration of the same name earlier in the
1920 * path. So we must do a slow check for conflicting configurations.
1922 char *name = NameStr(form->cfgname);
1926 foreach(l, activeSearchPath)
1928 Oid namespaceId = lfirst_oid(l);
1930 if (namespaceId == myTempNamespace)
1931 continue; /* do not look in temp namespace */
1933 if (namespaceId == namespace)
1935 /* Found it first in path */
1939 if (SearchSysCacheExists(TSCONFIGNAMENSP,
1940 PointerGetDatum(name),
1941 ObjectIdGetDatum(namespaceId),
1944 /* Found something else first in path */
1950 ReleaseSysCache(tup);
1957 * DeconstructQualifiedName
1958 * Given a possibly-qualified name expressed as a list of String nodes,
1959 * extract the schema name and object name.
1961 * *nspname_p is set to NULL if there is no explicit schema name.
1964 DeconstructQualifiedName(List *names,
1969 char *schemaname = NULL;
1970 char *objname = NULL;
1972 switch (list_length(names))
1975 objname = strVal(linitial(names));
1978 schemaname = strVal(linitial(names));
1979 objname = strVal(lsecond(names));
1982 catalogname = strVal(linitial(names));
1983 schemaname = strVal(lsecond(names));
1984 objname = strVal(lthird(names));
1987 * We check the catalog name and then ignore it.
1989 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
1991 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1992 errmsg("cross-database references are not implemented: %s",
1993 NameListToString(names))));
1997 (errcode(ERRCODE_SYNTAX_ERROR),
1998 errmsg("improper qualified name (too many dotted names): %s",
1999 NameListToString(names))));
2003 *nspname_p = schemaname;
2004 *objname_p = objname;
2008 * LookupExplicitNamespace
2009 * Process an explicitly-specified schema name: look up the schema
2010 * and verify we have USAGE (lookup) rights in it.
2012 * Returns the namespace OID. Raises ereport if any problem.
2015 LookupExplicitNamespace(const char *nspname)
2018 AclResult aclresult;
2020 /* check for pg_temp alias */
2021 if (strcmp(nspname, "pg_temp") == 0)
2023 if (OidIsValid(myTempNamespace))
2024 return myTempNamespace;
2027 * Since this is used only for looking up existing objects, there is
2028 * no point in trying to initialize the temp namespace here; and doing
2029 * so might create problems for some callers. Just fall through and
2030 * give the "does not exist" error.
2034 namespaceId = GetSysCacheOid(NAMESPACENAME,
2035 CStringGetDatum(nspname),
2037 if (!OidIsValid(namespaceId))
2039 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2040 errmsg("schema \"%s\" does not exist", nspname)));
2042 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
2043 if (aclresult != ACLCHECK_OK)
2044 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2051 * LookupCreationNamespace
2052 * Look up the schema and verify we have CREATE rights on it.
2054 * This is just like LookupExplicitNamespace except for the permission check,
2055 * and that we are willing to create pg_temp if needed.
2057 * Note: calling this may result in a CommandCounterIncrement operation,
2058 * if we have to create or clean out the temp namespace.
2061 LookupCreationNamespace(const char *nspname)
2064 AclResult aclresult;
2066 /* check for pg_temp alias */
2067 if (strcmp(nspname, "pg_temp") == 0)
2069 /* Initialize temp namespace if first time through */
2070 if (!OidIsValid(myTempNamespace))
2071 InitTempTableNamespace();
2072 return myTempNamespace;
2075 namespaceId = GetSysCacheOid(NAMESPACENAME,
2076 CStringGetDatum(nspname),
2078 if (!OidIsValid(namespaceId))
2080 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2081 errmsg("schema \"%s\" does not exist", nspname)));
2083 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
2084 if (aclresult != ACLCHECK_OK)
2085 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2092 * QualifiedNameGetCreationNamespace
2093 * Given a possibly-qualified name for an object (in List-of-Values
2094 * format), determine what namespace the object should be created in.
2095 * Also extract and return the object name (last component of list).
2097 * Note: this does not apply any permissions check. Callers must check
2098 * for CREATE rights on the selected namespace when appropriate.
2100 * Note: calling this may result in a CommandCounterIncrement operation,
2101 * if we have to create or clean out the temp namespace.
2104 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
2109 /* deconstruct the name list */
2110 DeconstructQualifiedName(names, &schemaname, objname_p);
2114 /* check for pg_temp alias */
2115 if (strcmp(schemaname, "pg_temp") == 0)
2117 /* Initialize temp namespace if first time through */
2118 if (!OidIsValid(myTempNamespace))
2119 InitTempTableNamespace();
2120 return myTempNamespace;
2122 /* use exact schema given */
2123 namespaceId = GetSysCacheOid(NAMESPACENAME,
2124 CStringGetDatum(schemaname),
2126 if (!OidIsValid(namespaceId))
2128 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2129 errmsg("schema \"%s\" does not exist", schemaname)));
2130 /* we do not check for USAGE rights here! */
2134 /* use the default creation namespace */
2135 recomputeNamespacePath();
2136 if (activeTempCreationPending)
2138 /* Need to initialize temp namespace */
2139 InitTempTableNamespace();
2140 return myTempNamespace;
2142 namespaceId = activeCreationNamespace;
2143 if (!OidIsValid(namespaceId))
2145 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2146 errmsg("no schema has been selected to create in")));
2153 * makeRangeVarFromNameList
2154 * Utility routine to convert a qualified-name list into RangeVar form.
2157 makeRangeVarFromNameList(List *names)
2159 RangeVar *rel = makeRangeVar(NULL, NULL, -1);
2161 switch (list_length(names))
2164 rel->relname = strVal(linitial(names));
2167 rel->schemaname = strVal(linitial(names));
2168 rel->relname = strVal(lsecond(names));
2171 rel->catalogname = strVal(linitial(names));
2172 rel->schemaname = strVal(lsecond(names));
2173 rel->relname = strVal(lthird(names));
2177 (errcode(ERRCODE_SYNTAX_ERROR),
2178 errmsg("improper relation name (too many dotted names): %s",
2179 NameListToString(names))));
2188 * Utility routine to convert a qualified-name list into a string.
2190 * This is used primarily to form error messages, and so we do not quote
2191 * the list elements, for the sake of legibility.
2193 * In most scenarios the list elements should always be Value strings,
2194 * but we also allow A_Star for the convenience of ColumnRef processing.
2197 NameListToString(List *names)
2199 StringInfoData string;
2202 initStringInfo(&string);
2206 Node *name = (Node *) lfirst(l);
2208 if (l != list_head(names))
2209 appendStringInfoChar(&string, '.');
2211 if (IsA(name, String))
2212 appendStringInfoString(&string, strVal(name));
2213 else if (IsA(name, A_Star))
2214 appendStringInfoString(&string, "*");
2216 elog(ERROR, "unexpected node type in name list: %d",
2217 (int) nodeTag(name));
2224 * NameListToQuotedString
2225 * Utility routine to convert a qualified-name list into a string.
2227 * Same as above except that names will be double-quoted where necessary,
2228 * so the string could be re-parsed (eg, by textToQualifiedNameList).
2231 NameListToQuotedString(List *names)
2233 StringInfoData string;
2236 initStringInfo(&string);
2240 if (l != list_head(names))
2241 appendStringInfoChar(&string, '.');
2242 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
2249 * isTempNamespace - is the given namespace my temporary-table namespace?
2252 isTempNamespace(Oid namespaceId)
2254 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
2260 * isTempToastNamespace - is the given namespace my temporary-toast-table
2264 isTempToastNamespace(Oid namespaceId)
2266 if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
2272 * isTempOrToastNamespace - is the given namespace my temporary-table
2273 * namespace or my temporary-toast-table namespace?
2276 isTempOrToastNamespace(Oid namespaceId)
2278 if (OidIsValid(myTempNamespace) &&
2279 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
2285 * isAnyTempNamespace - is the given namespace a temporary-table namespace
2286 * (either my own, or another backend's)? Temporary-toast-table namespaces
2287 * are included, too.
2290 isAnyTempNamespace(Oid namespaceId)
2295 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2296 nspname = get_namespace_name(namespaceId);
2298 return false; /* no such namespace? */
2299 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
2300 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
2306 * isOtherTempNamespace - is the given namespace some other backend's
2307 * temporary-table namespace (including temporary-toast-table namespaces)?
2310 isOtherTempNamespace(Oid namespaceId)
2312 /* If it's my own temp namespace, say "false" */
2313 if (isTempOrToastNamespace(namespaceId))
2315 /* Else, if it's any temp namespace, say "true" */
2316 return isAnyTempNamespace(namespaceId);
2320 * GetTempNamespaceBackendId - if the given namespace is a temporary-table
2321 * namespace (either my own, or another backend's), return the BackendId
2322 * that owns it. Temporary-toast-table namespaces are included, too.
2323 * If it isn't a temp namespace, return -1.
2326 GetTempNamespaceBackendId(Oid namespaceId)
2331 /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2332 nspname = get_namespace_name(namespaceId);
2334 return -1; /* no such namespace? */
2335 if (strncmp(nspname, "pg_temp_", 8) == 0)
2336 result = atoi(nspname + 8);
2337 else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
2338 result = atoi(nspname + 14);
2346 * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
2347 * which must already be assigned. (This is only used when creating a toast
2348 * table for a temp table, so we must have already done InitTempTableNamespace)
2351 GetTempToastNamespace(void)
2353 Assert(OidIsValid(myTempToastNamespace));
2354 return myTempToastNamespace;
2359 * GetOverrideSearchPath - fetch current search path definition in form
2360 * used by PushOverrideSearchPath.
2362 * The result structure is allocated in the specified memory context
2363 * (which might or might not be equal to CurrentMemoryContext); but any
2364 * junk created by revalidation calculations will be in CurrentMemoryContext.
2366 OverrideSearchPath *
2367 GetOverrideSearchPath(MemoryContext context)
2369 OverrideSearchPath *result;
2371 MemoryContext oldcxt;
2373 recomputeNamespacePath();
2375 oldcxt = MemoryContextSwitchTo(context);
2377 result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
2378 schemas = list_copy(activeSearchPath);
2379 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
2381 if (linitial_oid(schemas) == myTempNamespace)
2382 result->addTemp = true;
2385 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
2386 result->addCatalog = true;
2388 schemas = list_delete_first(schemas);
2390 result->schemas = schemas;
2392 MemoryContextSwitchTo(oldcxt);
2398 * PushOverrideSearchPath - temporarily override the search path
2400 * We allow nested overrides, hence the push/pop terminology. The GUC
2401 * search_path variable is ignored while an override is active.
2404 PushOverrideSearchPath(OverrideSearchPath *newpath)
2406 OverrideStackEntry *entry;
2409 MemoryContext oldcxt;
2412 * Copy the list for safekeeping, and insert implicitly-searched
2413 * namespaces as needed. This code should track recomputeNamespacePath.
2415 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2417 oidlist = list_copy(newpath->schemas);
2420 * Remember the first member of the explicit list.
2423 firstNS = InvalidOid;
2425 firstNS = linitial_oid(oidlist);
2428 * Add any implicitly-searched namespaces to the list. Note these go on
2429 * the front, not the back; also notice that we do not check USAGE
2430 * permissions for these.
2432 if (newpath->addCatalog)
2433 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2435 if (newpath->addTemp)
2437 Assert(OidIsValid(myTempNamespace));
2438 oidlist = lcons_oid(myTempNamespace, oidlist);
2442 * Build the new stack entry, then insert it at the head of the list.
2444 entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
2445 entry->searchPath = oidlist;
2446 entry->creationNamespace = firstNS;
2447 entry->nestLevel = GetCurrentTransactionNestLevel();
2449 overrideStack = lcons(entry, overrideStack);
2451 /* And make it active. */
2452 activeSearchPath = entry->searchPath;
2453 activeCreationNamespace = entry->creationNamespace;
2454 activeTempCreationPending = false; /* XXX is this OK? */
2456 MemoryContextSwitchTo(oldcxt);
2460 * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
2462 * Any push during a (sub)transaction will be popped automatically at abort.
2463 * But it's caller error if a push isn't popped in normal control flow.
2466 PopOverrideSearchPath(void)
2468 OverrideStackEntry *entry;
2470 /* Sanity checks. */
2471 if (overrideStack == NIL)
2472 elog(ERROR, "bogus PopOverrideSearchPath call");
2473 entry = (OverrideStackEntry *) linitial(overrideStack);
2474 if (entry->nestLevel != GetCurrentTransactionNestLevel())
2475 elog(ERROR, "bogus PopOverrideSearchPath call");
2477 /* Pop the stack and free storage. */
2478 overrideStack = list_delete_first(overrideStack);
2479 list_free(entry->searchPath);
2482 /* Activate the next level down. */
2485 entry = (OverrideStackEntry *) linitial(overrideStack);
2486 activeSearchPath = entry->searchPath;
2487 activeCreationNamespace = entry->creationNamespace;
2488 activeTempCreationPending = false; /* XXX is this OK? */
2492 /* If not baseSearchPathValid, this is useless but harmless */
2493 activeSearchPath = baseSearchPath;
2494 activeCreationNamespace = baseCreationNamespace;
2495 activeTempCreationPending = baseTempCreationPending;
2501 * FindConversionByName - find a conversion by possibly qualified name
2504 FindConversionByName(List *name)
2507 char *conversion_name;
2512 /* deconstruct the name list */
2513 DeconstructQualifiedName(name, &schemaname, &conversion_name);
2517 /* use exact schema given */
2518 namespaceId = LookupExplicitNamespace(schemaname);
2519 return FindConversion(conversion_name, namespaceId);
2523 /* search for it in search path */
2524 recomputeNamespacePath();
2526 foreach(l, activeSearchPath)
2528 namespaceId = lfirst_oid(l);
2530 if (namespaceId == myTempNamespace)
2531 continue; /* do not look in temp namespace */
2533 conoid = FindConversion(conversion_name, namespaceId);
2534 if (OidIsValid(conoid))
2539 /* Not found in path */
2544 * FindDefaultConversionProc - find default encoding conversion proc
2547 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
2552 recomputeNamespacePath();
2554 foreach(l, activeSearchPath)
2556 Oid namespaceId = lfirst_oid(l);
2558 if (namespaceId == myTempNamespace)
2559 continue; /* do not look in temp namespace */
2561 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
2562 if (OidIsValid(proc))
2566 /* Not found in path */
2571 * recomputeNamespacePath - recompute path derived variables if needed.
2574 recomputeNamespacePath(void)
2576 Oid roleid = GetUserId();
2584 MemoryContext oldcxt;
2586 /* Do nothing if an override search spec is active. */
2590 /* Do nothing if path is already valid. */
2591 if (baseSearchPathValid && namespaceUser == roleid)
2594 /* Need a modifiable copy of namespace_search_path string */
2595 rawname = pstrdup(namespace_search_path);
2597 /* Parse string into list of identifiers */
2598 if (!SplitIdentifierString(rawname, ',', &namelist))
2600 /* syntax error in name list */
2601 /* this should not happen if GUC checked check_search_path */
2602 elog(ERROR, "invalid list syntax");
2606 * Convert the list of names to a list of OIDs. If any names are not
2607 * recognizable or we don't have read access, just leave them out of the
2608 * list. (We can't raise an error, since the search_path setting has
2609 * already been accepted.) Don't make duplicate entries, either.
2612 temp_missing = false;
2613 foreach(l, namelist)
2615 char *curname = (char *) lfirst(l);
2618 if (strcmp(curname, "$user") == 0)
2620 /* $user --- substitute namespace matching user name, if any */
2623 tuple = SearchSysCache(AUTHOID,
2624 ObjectIdGetDatum(roleid),
2626 if (HeapTupleIsValid(tuple))
2630 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
2631 namespaceId = GetSysCacheOid(NAMESPACENAME,
2632 CStringGetDatum(rname),
2634 ReleaseSysCache(tuple);
2635 if (OidIsValid(namespaceId) &&
2636 !list_member_oid(oidlist, namespaceId) &&
2637 pg_namespace_aclcheck(namespaceId, roleid,
2638 ACL_USAGE) == ACLCHECK_OK)
2639 oidlist = lappend_oid(oidlist, namespaceId);
2642 else if (strcmp(curname, "pg_temp") == 0)
2644 /* pg_temp --- substitute temp namespace, if any */
2645 if (OidIsValid(myTempNamespace))
2647 if (!list_member_oid(oidlist, myTempNamespace))
2648 oidlist = lappend_oid(oidlist, myTempNamespace);
2652 /* If it ought to be the creation namespace, set flag */
2654 temp_missing = true;
2659 /* normal namespace reference */
2660 namespaceId = GetSysCacheOid(NAMESPACENAME,
2661 CStringGetDatum(curname),
2663 if (OidIsValid(namespaceId) &&
2664 !list_member_oid(oidlist, namespaceId) &&
2665 pg_namespace_aclcheck(namespaceId, roleid,
2666 ACL_USAGE) == ACLCHECK_OK)
2667 oidlist = lappend_oid(oidlist, namespaceId);
2672 * Remember the first member of the explicit list. (Note: this is
2673 * nominally wrong if temp_missing, but we need it anyway to distinguish
2674 * explicit from implicit mention of pg_catalog.)
2677 firstNS = InvalidOid;
2679 firstNS = linitial_oid(oidlist);
2682 * Add any implicitly-searched namespaces to the list. Note these go on
2683 * the front, not the back; also notice that we do not check USAGE
2684 * permissions for these.
2686 if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
2687 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2689 if (OidIsValid(myTempNamespace) &&
2690 !list_member_oid(oidlist, myTempNamespace))
2691 oidlist = lcons_oid(myTempNamespace, oidlist);
2694 * Now that we've successfully built the new list of namespace OIDs, save
2695 * it in permanent storage.
2697 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2698 newpath = list_copy(oidlist);
2699 MemoryContextSwitchTo(oldcxt);
2701 /* Now safe to assign to state variables. */
2702 list_free(baseSearchPath);
2703 baseSearchPath = newpath;
2704 baseCreationNamespace = firstNS;
2705 baseTempCreationPending = temp_missing;
2707 /* Mark the path valid. */
2708 baseSearchPathValid = true;
2709 namespaceUser = roleid;
2711 /* And make it active. */
2712 activeSearchPath = baseSearchPath;
2713 activeCreationNamespace = baseCreationNamespace;
2714 activeTempCreationPending = baseTempCreationPending;
2718 list_free(namelist);
2723 * InitTempTableNamespace
2724 * Initialize temp table namespace on first use in a particular backend
2727 InitTempTableNamespace(void)
2729 char namespaceName[NAMEDATALEN];
2733 Assert(!OidIsValid(myTempNamespace));
2736 * First, do permission check to see if we are authorized to make temp
2737 * tables. We use a nonstandard error message here since "databasename:
2738 * permission denied" might be a tad cryptic.
2740 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
2741 * that's necessary since current user ID could change during the session.
2742 * But there's no need to make the namespace in the first place until a
2743 * temp table creation request is made by someone with appropriate rights.
2745 if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
2746 ACL_CREATE_TEMP) != ACLCHECK_OK)
2748 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2749 errmsg("permission denied to create temporary tables in database \"%s\"",
2750 get_database_name(MyDatabaseId))));
2752 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
2754 namespaceId = GetSysCacheOid(NAMESPACENAME,
2755 CStringGetDatum(namespaceName),
2757 if (!OidIsValid(namespaceId))
2760 * First use of this temp namespace in this database; create it. The
2761 * temp namespaces are always owned by the superuser. We leave their
2762 * permissions at default --- i.e., no access except to superuser ---
2763 * to ensure that unprivileged users can't peek at other backends'
2764 * temp tables. This works because the places that access the temp
2765 * namespace for my own backend skip permissions checks on it.
2767 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2768 /* Advance command counter to make namespace visible */
2769 CommandCounterIncrement();
2774 * If the namespace already exists, clean it out (in case the former
2775 * owner crashed without doing so).
2777 RemoveTempRelations(namespaceId);
2781 * If the corresponding toast-table namespace doesn't exist yet, create it.
2782 * (We assume there is no need to clean it out if it does exist, since
2783 * dropping a parent table should make its toast table go away.)
2785 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
2788 toastspaceId = GetSysCacheOid(NAMESPACENAME,
2789 CStringGetDatum(namespaceName),
2791 if (!OidIsValid(toastspaceId))
2793 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2794 /* Advance command counter to make namespace visible */
2795 CommandCounterIncrement();
2799 * Okay, we've prepared the temp namespace ... but it's not committed yet,
2800 * so all our work could be undone by transaction rollback. Set flag for
2801 * AtEOXact_Namespace to know what to do.
2803 myTempNamespace = namespaceId;
2804 myTempToastNamespace = toastspaceId;
2806 /* It should not be done already. */
2807 AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
2808 myTempNamespaceSubID = GetCurrentSubTransactionId();
2810 baseSearchPathValid = false; /* need to rebuild list */
2814 * End-of-transaction cleanup for namespaces.
2817 AtEOXact_Namespace(bool isCommit)
2820 * If we abort the transaction in which a temp namespace was selected,
2821 * we'll have to do any creation or cleanout work over again. So, just
2822 * forget the namespace entirely until next time. On the other hand, if
2823 * we commit then register an exit callback to clean out the temp tables
2824 * at backend shutdown. (We only want to register the callback once per
2825 * session, so this is a good place to do it.)
2827 if (myTempNamespaceSubID != InvalidSubTransactionId)
2830 on_shmem_exit(RemoveTempRelationsCallback, 0);
2833 myTempNamespace = InvalidOid;
2834 myTempToastNamespace = InvalidOid;
2835 baseSearchPathValid = false; /* need to rebuild list */
2837 myTempNamespaceSubID = InvalidSubTransactionId;
2841 * Clean up if someone failed to do PopOverrideSearchPath
2846 elog(WARNING, "leaked override search path");
2847 while (overrideStack)
2849 OverrideStackEntry *entry;
2851 entry = (OverrideStackEntry *) linitial(overrideStack);
2852 overrideStack = list_delete_first(overrideStack);
2853 list_free(entry->searchPath);
2856 /* If not baseSearchPathValid, this is useless but harmless */
2857 activeSearchPath = baseSearchPath;
2858 activeCreationNamespace = baseCreationNamespace;
2859 activeTempCreationPending = baseTempCreationPending;
2864 * AtEOSubXact_Namespace
2866 * At subtransaction commit, propagate the temp-namespace-creation
2867 * flag to the parent subtransaction.
2869 * At subtransaction abort, forget the flag if we set it up.
2872 AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
2873 SubTransactionId parentSubid)
2875 OverrideStackEntry *entry;
2877 if (myTempNamespaceSubID == mySubid)
2880 myTempNamespaceSubID = parentSubid;
2883 myTempNamespaceSubID = InvalidSubTransactionId;
2884 /* TEMP namespace creation failed, so reset state */
2885 myTempNamespace = InvalidOid;
2886 myTempToastNamespace = InvalidOid;
2887 baseSearchPathValid = false; /* need to rebuild list */
2892 * Clean up if someone failed to do PopOverrideSearchPath
2894 while (overrideStack)
2896 entry = (OverrideStackEntry *) linitial(overrideStack);
2897 if (entry->nestLevel < GetCurrentTransactionNestLevel())
2900 elog(WARNING, "leaked override search path");
2901 overrideStack = list_delete_first(overrideStack);
2902 list_free(entry->searchPath);
2906 /* Activate the next level down. */
2909 entry = (OverrideStackEntry *) linitial(overrideStack);
2910 activeSearchPath = entry->searchPath;
2911 activeCreationNamespace = entry->creationNamespace;
2912 activeTempCreationPending = false; /* XXX is this OK? */
2916 /* If not baseSearchPathValid, this is useless but harmless */
2917 activeSearchPath = baseSearchPath;
2918 activeCreationNamespace = baseCreationNamespace;
2919 activeTempCreationPending = baseTempCreationPending;
2924 * Remove all relations in the specified temp namespace.
2926 * This is called at backend shutdown (if we made any temp relations).
2927 * It is also called when we begin using a pre-existing temp namespace,
2928 * in order to clean out any relations that might have been created by
2929 * a crashed backend.
2932 RemoveTempRelations(Oid tempNamespaceId)
2934 ObjectAddress object;
2937 * We want to get rid of everything in the target namespace, but not the
2938 * namespace itself (deleting it only to recreate it later would be a
2939 * waste of cycles). We do this by finding everything that has a
2940 * dependency on the namespace.
2942 object.classId = NamespaceRelationId;
2943 object.objectId = tempNamespaceId;
2944 object.objectSubId = 0;
2946 deleteWhatDependsOn(&object, false);
2950 * Callback to remove temp relations at backend exit.
2953 RemoveTempRelationsCallback(int code, Datum arg)
2955 if (OidIsValid(myTempNamespace)) /* should always be true */
2957 /* Need to ensure we have a usable transaction. */
2958 AbortOutOfAnyTransaction();
2959 StartTransactionCommand();
2961 RemoveTempRelations(myTempNamespace);
2963 CommitTransactionCommand();
2968 * Remove all temp tables from the temporary namespace.
2971 ResetTempTableNamespace(void)
2973 if (OidIsValid(myTempNamespace))
2974 RemoveTempRelations(myTempNamespace);
2979 * Routines for handling the GUC variable 'search_path'.
2982 /* assign_hook: validate new search_path, do extra actions as needed */
2984 assign_search_path(const char *newval, bool doit, GucSource source)
2990 /* Need a modifiable copy of string */
2991 rawname = pstrdup(newval);
2993 /* Parse string into list of identifiers */
2994 if (!SplitIdentifierString(rawname, ',', &namelist))
2996 /* syntax error in name list */
2998 list_free(namelist);
3003 * If we aren't inside a transaction, we cannot do database access so
3004 * cannot verify the individual names. Must accept the list on faith.
3006 if (source >= PGC_S_INTERACTIVE && IsTransactionState())
3009 * Verify that all the names are either valid namespace names or
3010 * "$user" or "pg_temp". We do not require $user to correspond to a
3011 * valid namespace, and pg_temp might not exist yet. We do not check
3012 * for USAGE rights, either; should we?
3014 * When source == PGC_S_TEST, we are checking the argument of an ALTER
3015 * DATABASE SET or ALTER USER SET command. It could be that the
3016 * intended use of the search path is for some other database, so we
3017 * should not error out if it mentions schemas not present in the
3018 * current database. We reduce the message to NOTICE instead.
3020 foreach(l, namelist)
3022 char *curname = (char *) lfirst(l);
3024 if (strcmp(curname, "$user") == 0)
3026 if (strcmp(curname, "pg_temp") == 0)
3028 if (!SearchSysCacheExists(NAMESPACENAME,
3029 CStringGetDatum(curname),
3031 ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
3032 (errcode(ERRCODE_UNDEFINED_SCHEMA),
3033 errmsg("schema \"%s\" does not exist", curname)));
3038 list_free(namelist);
3041 * We mark the path as needing recomputation, but don't do anything until
3042 * it's needed. This avoids trying to do database access during GUC
3046 baseSearchPathValid = false;
3052 * InitializeSearchPath: initialize module during InitPostgres.
3054 * This is called after we are up enough to be able to do catalog lookups.
3057 InitializeSearchPath(void)
3059 if (IsBootstrapProcessingMode())
3062 * In bootstrap mode, the search path must be 'pg_catalog' so that
3063 * tables are created in the proper namespace; ignore the GUC setting.
3065 MemoryContext oldcxt;
3067 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
3068 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
3069 MemoryContextSwitchTo(oldcxt);
3070 baseCreationNamespace = PG_CATALOG_NAMESPACE;
3071 baseTempCreationPending = false;
3072 baseSearchPathValid = true;
3073 namespaceUser = GetUserId();
3074 activeSearchPath = baseSearchPath;
3075 activeCreationNamespace = baseCreationNamespace;
3076 activeTempCreationPending = baseTempCreationPending;
3081 * In normal mode, arrange for a callback on any syscache invalidation
3082 * of pg_namespace rows.
3084 CacheRegisterSyscacheCallback(NAMESPACEOID,
3087 /* Force search path to be recomputed on next use */
3088 baseSearchPathValid = false;
3094 * Syscache inval callback function
3097 NamespaceCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
3099 /* Force search path to be recomputed on next use */
3100 baseSearchPathValid = false;
3104 * Fetch the active search path. The return value is a palloc'ed list
3105 * of OIDs; the caller is responsible for freeing this storage as
3108 * The returned list includes the implicitly-prepended namespaces only if
3109 * includeImplicit is true.
3111 * Note: calling this may result in a CommandCounterIncrement operation,
3112 * if we have to create or clean out the temp namespace.
3115 fetch_search_path(bool includeImplicit)
3119 recomputeNamespacePath();
3122 * If the temp namespace should be first, force it to exist. This is so
3123 * that callers can trust the result to reflect the actual default
3124 * creation namespace. It's a bit bogus to do this here, since
3125 * current_schema() is supposedly a stable function without side-effects,
3126 * but the alternatives seem worse.
3128 if (activeTempCreationPending)
3130 InitTempTableNamespace();
3131 recomputeNamespacePath();
3134 result = list_copy(activeSearchPath);
3135 if (!includeImplicit)
3137 while (result && linitial_oid(result) != activeCreationNamespace)
3138 result = list_delete_first(result);
3145 * Fetch the active search path into a caller-allocated array of OIDs.
3146 * Returns the number of path entries. (If this is more than sarray_len,
3147 * then the data didn't fit and is not all stored.)
3149 * The returned list always includes the implicitly-prepended namespaces,
3150 * but never includes the temp namespace. (This is suitable for existing
3151 * users, which would want to ignore the temp namespace anyway.) This
3152 * definition allows us to not worry about initializing the temp namespace.
3155 fetch_search_path_array(Oid *sarray, int sarray_len)
3160 recomputeNamespacePath();
3162 foreach(l, activeSearchPath)
3164 Oid namespaceId = lfirst_oid(l);
3166 if (namespaceId == myTempNamespace)
3167 continue; /* do not include temp namespace */
3169 if (count < sarray_len)
3170 sarray[count] = namespaceId;
3179 * Export the FooIsVisible functions as SQL-callable functions.
3183 pg_table_is_visible(PG_FUNCTION_ARGS)
3185 Oid oid = PG_GETARG_OID(0);
3187 PG_RETURN_BOOL(RelationIsVisible(oid));
3191 pg_type_is_visible(PG_FUNCTION_ARGS)
3193 Oid oid = PG_GETARG_OID(0);
3195 PG_RETURN_BOOL(TypeIsVisible(oid));
3199 pg_function_is_visible(PG_FUNCTION_ARGS)
3201 Oid oid = PG_GETARG_OID(0);
3203 PG_RETURN_BOOL(FunctionIsVisible(oid));
3207 pg_operator_is_visible(PG_FUNCTION_ARGS)
3209 Oid oid = PG_GETARG_OID(0);
3211 PG_RETURN_BOOL(OperatorIsVisible(oid));
3215 pg_opclass_is_visible(PG_FUNCTION_ARGS)
3217 Oid oid = PG_GETARG_OID(0);
3219 PG_RETURN_BOOL(OpclassIsVisible(oid));
3223 pg_conversion_is_visible(PG_FUNCTION_ARGS)
3225 Oid oid = PG_GETARG_OID(0);
3227 PG_RETURN_BOOL(ConversionIsVisible(oid));
3231 pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
3233 Oid oid = PG_GETARG_OID(0);
3235 PG_RETURN_BOOL(TSParserIsVisible(oid));
3239 pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
3241 Oid oid = PG_GETARG_OID(0);
3243 PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
3247 pg_ts_template_is_visible(PG_FUNCTION_ARGS)
3249 Oid oid = PG_GETARG_OID(0);
3251 PG_RETURN_BOOL(TSTemplateIsVisible(oid));
3255 pg_ts_config_is_visible(PG_FUNCTION_ARGS)
3257 Oid oid = PG_GETARG_OID(0);
3259 PG_RETURN_BOOL(TSConfigIsVisible(oid));
3263 pg_my_temp_schema(PG_FUNCTION_ARGS)
3265 PG_RETURN_OID(myTempNamespace);
3269 pg_is_other_temp_schema(PG_FUNCTION_ARGS)
3271 Oid oid = PG_GETARG_OID(0);
3273 PG_RETURN_BOOL(isOtherTempNamespace(oid));