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.108 2008/07/16 01:30:21 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, Oid relid);
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;
622 bool variadic = false;
623 Oid va_elem_type = InvalidOid;
624 FuncCandidateList newResult;
627 * Check if function is variadic, and get variadic element type if so.
628 * If expand_variadic is false, we can just ignore variadic-ness.
630 * XXX it's annoying to inject something as expensive as this even
631 * when there are no variadic functions involved. Find a better way.
638 proargmodes = SysCacheGetAttr(PROCOID, proctup,
639 Anum_pg_proc_proargmodes, &isnull);
642 ArrayType *ar = DatumGetArrayTypeP(proargmodes);
646 argmodes = ARR_DATA_PTR(ar);
647 j = ARR_DIMS(ar)[0] - 1;
648 if (j >= 0 && argmodes[j] == PROARGMODE_VARIADIC)
650 variadic = any_variadic = true;
651 switch (procform->proargtypes.values[j])
654 va_elem_type = ANYOID;
657 va_elem_type = ANYELEMENTOID;
660 va_elem_type = get_element_type(procform->proargtypes.values[j]);
661 Assert(OidIsValid(va_elem_type));
668 /* Ignore if it doesn't match requested argument count */
670 (variadic ? (pronargs > nargs) : (pronargs != nargs)))
673 if (OidIsValid(namespaceId))
675 /* Consider only procs in specified namespace */
676 if (procform->pronamespace != namespaceId)
682 * Consider only procs that are in the search path and are not in
683 * the temp namespace.
687 foreach(nsp, activeSearchPath)
689 if (procform->pronamespace == lfirst_oid(nsp) &&
690 procform->pronamespace != myTempNamespace)
695 continue; /* proc is not in search path */
699 * We must compute the effective argument list so that we can easily
700 * compare it to earlier results. We waste a palloc cycle if it gets
701 * masked by an earlier result, but really that's a pretty infrequent
702 * case so it's not worth worrying about.
704 effective_nargs = Max(pronargs, nargs);
705 newResult = (FuncCandidateList)
706 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
707 + effective_nargs * sizeof(Oid));
708 newResult->pathpos = pathpos;
709 newResult->oid = HeapTupleGetOid(proctup);
710 newResult->nargs = effective_nargs;
711 memcpy(newResult->args, procform->proargtypes.values,
712 pronargs * sizeof(Oid));
717 newResult->nvargs = effective_nargs - pronargs + 1;
718 /* Expand variadic argument into N copies of element type */
719 for (i = pronargs - 1; i < effective_nargs; i++)
720 newResult->args[i] = va_elem_type;
723 newResult->nvargs = 0;
726 * Does it have the same arguments as something we already accepted?
727 * If so, decide which one to keep. We can skip this check for the
728 * single-namespace case if no variadic match has been made, since
729 * then the unique index on pg_proc guarantees all the matches have
730 * different argument lists.
732 if (any_variadic || !OidIsValid(namespaceId))
735 * If we have an ordered list from SearchSysCacheList (the normal
736 * case), then any conflicting proc must immediately adjoin this
737 * one in the list, so we only need to look at the newest result
738 * item. If we have an unordered list, we have to scan the whole
739 * result list. Also, if either the current candidate or any
740 * previous candidate is a variadic match, we can't assume that
741 * conflicts are adjacent.
745 FuncCandidateList prevResult;
747 if (catlist->ordered && !any_variadic)
749 if (effective_nargs == resultList->nargs &&
750 memcmp(newResult->args,
752 effective_nargs * sizeof(Oid)) == 0)
753 prevResult = resultList;
759 for (prevResult = resultList;
761 prevResult = prevResult->next)
763 if (effective_nargs == prevResult->nargs &&
764 memcmp(newResult->args,
766 effective_nargs * sizeof(Oid)) == 0)
773 * We have a match with a previous result. Prefer the
774 * one that's earlier in the search path.
776 if (pathpos > prevResult->pathpos)
779 continue; /* keep previous result */
781 else if (pathpos == prevResult->pathpos)
784 * With variadic functions we could have, for example,
785 * both foo(numeric) and foo(variadic numeric[]) in
786 * the same namespace; if so we prefer the
787 * non-variadic match on efficiency grounds. It's
788 * also possible to have conflicting variadic
789 * functions, such as foo(numeric, variadic numeric[])
790 * and foo(variadic numeric[]). If you're silly
791 * enough to do that, we throw an error. (XXX It'd be
792 * better to detect such conflicts when the functions
797 if (prevResult->nvargs > 0)
799 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
800 errmsg("variadic function %s conflicts with another",
801 func_signature_string(names, pronargs,
802 procform->proargtypes.values))));
803 /* else, previous result wasn't variadic */
805 continue; /* keep previous result */
807 /* non-variadic can replace a previous variadic */
808 Assert(prevResult->nvargs > 0);
810 /* replace previous result */
811 prevResult->pathpos = pathpos;
812 prevResult->oid = newResult->oid;
813 prevResult->nvargs = newResult->nvargs;
815 continue; /* args are same, of course */
821 * Okay to add it to result list
823 newResult->next = resultList;
824 resultList = newResult;
827 ReleaseSysCacheList(catlist);
834 * Determine whether a function (identified by OID) is visible in the
835 * current search path. Visible means "would be found by searching
836 * for the unqualified function name with exact argument matches".
839 FunctionIsVisible(Oid funcid)
842 Form_pg_proc procform;
846 proctup = SearchSysCache(PROCOID,
847 ObjectIdGetDatum(funcid),
849 if (!HeapTupleIsValid(proctup))
850 elog(ERROR, "cache lookup failed for function %u", funcid);
851 procform = (Form_pg_proc) GETSTRUCT(proctup);
853 recomputeNamespacePath();
856 * Quick check: if it ain't in the path at all, it ain't visible. Items in
857 * the system namespace are surely in the path and so we needn't even do
858 * list_member_oid() for them.
860 pronamespace = procform->pronamespace;
861 if (pronamespace != PG_CATALOG_NAMESPACE &&
862 !list_member_oid(activeSearchPath, pronamespace))
867 * If it is in the path, it might still not be visible; it could be
868 * hidden by another proc of the same name and arguments earlier in
869 * the path. So we must do a slow check to see if this is the same
870 * proc that would be found by FuncnameGetCandidates.
872 char *proname = NameStr(procform->proname);
873 int nargs = procform->pronargs;
874 FuncCandidateList clist;
878 clist = FuncnameGetCandidates(list_make1(makeString(proname)),
881 for (; clist; clist = clist->next)
883 if (memcmp(clist->args, procform->proargtypes.values,
884 nargs * sizeof(Oid)) == 0)
886 /* Found the expected entry; is it the right proc? */
887 visible = (clist->oid == funcid);
893 ReleaseSysCache(proctup);
901 * Given a possibly-qualified operator name and exact input datatypes,
902 * look up the operator. Returns InvalidOid if not found.
904 * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
907 * If the operator name is not schema-qualified, it is sought in the current
908 * namespace search path.
911 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
918 /* deconstruct the name list */
919 DeconstructQualifiedName(names, &schemaname, &opername);
923 /* search only in exact schema given */
927 namespaceId = LookupExplicitNamespace(schemaname);
928 opertup = SearchSysCache(OPERNAMENSP,
929 CStringGetDatum(opername),
930 ObjectIdGetDatum(oprleft),
931 ObjectIdGetDatum(oprright),
932 ObjectIdGetDatum(namespaceId));
933 if (HeapTupleIsValid(opertup))
935 Oid result = HeapTupleGetOid(opertup);
937 ReleaseSysCache(opertup);
943 /* Search syscache by name and argument types */
944 catlist = SearchSysCacheList(OPERNAMENSP, 3,
945 CStringGetDatum(opername),
946 ObjectIdGetDatum(oprleft),
947 ObjectIdGetDatum(oprright),
950 if (catlist->n_members == 0)
952 /* no hope, fall out early */
953 ReleaseSysCacheList(catlist);
958 * We have to find the list member that is first in the search path, if
959 * there's more than one. This doubly-nested loop looks ugly, but in
960 * practice there should usually be few catlist members.
962 recomputeNamespacePath();
964 foreach(l, activeSearchPath)
966 Oid namespaceId = lfirst_oid(l);
969 if (namespaceId == myTempNamespace)
970 continue; /* do not look in temp namespace */
972 for (i = 0; i < catlist->n_members; i++)
974 HeapTuple opertup = &catlist->members[i]->tuple;
975 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
977 if (operform->oprnamespace == namespaceId)
979 Oid result = HeapTupleGetOid(opertup);
981 ReleaseSysCacheList(catlist);
987 ReleaseSysCacheList(catlist);
992 * OpernameGetCandidates
993 * Given a possibly-qualified operator name and operator kind,
994 * retrieve a list of the possible matches.
996 * If oprkind is '\0', we return all operators matching the given name,
997 * regardless of arguments.
999 * We search a single namespace if the operator name is qualified, else
1000 * all namespaces in the search path. The return list will never contain
1001 * multiple entries with identical argument lists --- in the multiple-
1002 * namespace case, we arrange for entries in earlier namespaces to mask
1003 * identical entries in later namespaces.
1005 * The returned items always have two args[] entries --- one or the other
1006 * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
1009 OpernameGetCandidates(List *names, char oprkind)
1011 FuncCandidateList resultList = NULL;
1012 char *resultSpace = NULL;
1020 /* deconstruct the name list */
1021 DeconstructQualifiedName(names, &schemaname, &opername);
1025 /* use exact schema given */
1026 namespaceId = LookupExplicitNamespace(schemaname);
1030 /* flag to indicate we need namespace search */
1031 namespaceId = InvalidOid;
1032 recomputeNamespacePath();
1035 /* Search syscache by name only */
1036 catlist = SearchSysCacheList(OPERNAMENSP, 1,
1037 CStringGetDatum(opername),
1041 * In typical scenarios, most if not all of the operators found by the
1042 * catcache search will end up getting returned; and there can be quite a
1043 * few, for common operator names such as '=' or '+'. To reduce the time
1044 * spent in palloc, we allocate the result space as an array large enough
1045 * to hold all the operators. The original coding of this routine did a
1046 * separate palloc for each operator, but profiling revealed that the
1047 * pallocs used an unreasonably large fraction of parsing time.
1049 #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
1051 if (catlist->n_members > 0)
1052 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1054 for (i = 0; i < catlist->n_members; i++)
1056 HeapTuple opertup = &catlist->members[i]->tuple;
1057 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1059 FuncCandidateList newResult;
1061 /* Ignore operators of wrong kind, if specific kind requested */
1062 if (oprkind && operform->oprkind != oprkind)
1065 if (OidIsValid(namespaceId))
1067 /* Consider only opers in specified namespace */
1068 if (operform->oprnamespace != namespaceId)
1070 /* No need to check args, they must all be different */
1075 * Consider only opers that are in the search path and are not in
1076 * the temp namespace.
1080 foreach(nsp, activeSearchPath)
1082 if (operform->oprnamespace == lfirst_oid(nsp) &&
1083 operform->oprnamespace != myTempNamespace)
1088 continue; /* oper is not in search path */
1091 * Okay, it's in the search path, but does it have the same
1092 * arguments as something we already accepted? If so, keep only
1093 * the one that appears earlier in the search path.
1095 * If we have an ordered list from SearchSysCacheList (the normal
1096 * case), then any conflicting oper must immediately adjoin this
1097 * one in the list, so we only need to look at the newest result
1098 * item. If we have an unordered list, we have to scan the whole
1103 FuncCandidateList prevResult;
1105 if (catlist->ordered)
1107 if (operform->oprleft == resultList->args[0] &&
1108 operform->oprright == resultList->args[1])
1109 prevResult = resultList;
1115 for (prevResult = resultList;
1117 prevResult = prevResult->next)
1119 if (operform->oprleft == prevResult->args[0] &&
1120 operform->oprright == prevResult->args[1])
1126 /* We have a match with a previous result */
1127 Assert(pathpos != prevResult->pathpos);
1128 if (pathpos > prevResult->pathpos)
1129 continue; /* keep previous result */
1130 /* replace previous result */
1131 prevResult->pathpos = pathpos;
1132 prevResult->oid = HeapTupleGetOid(opertup);
1133 continue; /* args are same, of course */
1139 * Okay to add it to result list
1141 newResult = (FuncCandidateList) (resultSpace + nextResult);
1142 nextResult += SPACE_PER_OP;
1144 newResult->pathpos = pathpos;
1145 newResult->oid = HeapTupleGetOid(opertup);
1146 newResult->nargs = 2;
1147 newResult->nvargs = 0;
1148 newResult->args[0] = operform->oprleft;
1149 newResult->args[1] = operform->oprright;
1150 newResult->next = resultList;
1151 resultList = newResult;
1154 ReleaseSysCacheList(catlist);
1161 * Determine whether an operator (identified by OID) is visible in the
1162 * current search path. Visible means "would be found by searching
1163 * for the unqualified operator name with exact argument matches".
1166 OperatorIsVisible(Oid oprid)
1169 Form_pg_operator oprform;
1173 oprtup = SearchSysCache(OPEROID,
1174 ObjectIdGetDatum(oprid),
1176 if (!HeapTupleIsValid(oprtup))
1177 elog(ERROR, "cache lookup failed for operator %u", oprid);
1178 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
1180 recomputeNamespacePath();
1183 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1184 * the system namespace are surely in the path and so we needn't even do
1185 * list_member_oid() for them.
1187 oprnamespace = oprform->oprnamespace;
1188 if (oprnamespace != PG_CATALOG_NAMESPACE &&
1189 !list_member_oid(activeSearchPath, oprnamespace))
1194 * If it is in the path, it might still not be visible; it could be
1195 * hidden by another operator of the same name and arguments earlier
1196 * in the path. So we must do a slow check to see if this is the same
1197 * operator that would be found by OpernameGetOprId.
1199 char *oprname = NameStr(oprform->oprname);
1201 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
1202 oprform->oprleft, oprform->oprright)
1206 ReleaseSysCache(oprtup);
1213 * OpclassnameGetOpcid
1214 * Try to resolve an unqualified index opclass name.
1215 * Returns OID if opclass found in search path, else InvalidOid.
1217 * This is essentially the same as TypenameGetTypid, but we have to have
1218 * an extra argument for the index AM OID.
1221 OpclassnameGetOpcid(Oid amid, const char *opcname)
1226 recomputeNamespacePath();
1228 foreach(l, activeSearchPath)
1230 Oid namespaceId = lfirst_oid(l);
1232 if (namespaceId == myTempNamespace)
1233 continue; /* do not look in temp namespace */
1235 opcid = GetSysCacheOid(CLAAMNAMENSP,
1236 ObjectIdGetDatum(amid),
1237 PointerGetDatum(opcname),
1238 ObjectIdGetDatum(namespaceId),
1240 if (OidIsValid(opcid))
1244 /* Not found in path */
1250 * Determine whether an opclass (identified by OID) is visible in the
1251 * current search path. Visible means "would be found by searching
1252 * for the unqualified opclass name".
1255 OpclassIsVisible(Oid opcid)
1258 Form_pg_opclass opcform;
1262 opctup = SearchSysCache(CLAOID,
1263 ObjectIdGetDatum(opcid),
1265 if (!HeapTupleIsValid(opctup))
1266 elog(ERROR, "cache lookup failed for opclass %u", opcid);
1267 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1269 recomputeNamespacePath();
1272 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1273 * the system namespace are surely in the path and so we needn't even do
1274 * list_member_oid() for them.
1276 opcnamespace = opcform->opcnamespace;
1277 if (opcnamespace != PG_CATALOG_NAMESPACE &&
1278 !list_member_oid(activeSearchPath, opcnamespace))
1283 * If it is in the path, it might still not be visible; it could be
1284 * hidden by another opclass of the same name earlier in the path. So
1285 * we must do a slow check to see if this opclass would be found by
1286 * OpclassnameGetOpcid.
1288 char *opcname = NameStr(opcform->opcname);
1290 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
1293 ReleaseSysCache(opctup);
1299 * OpfamilynameGetOpfid
1300 * Try to resolve an unqualified index opfamily name.
1301 * Returns OID if opfamily found in search path, else InvalidOid.
1303 * This is essentially the same as TypenameGetTypid, but we have to have
1304 * an extra argument for the index AM OID.
1307 OpfamilynameGetOpfid(Oid amid, const char *opfname)
1312 recomputeNamespacePath();
1314 foreach(l, activeSearchPath)
1316 Oid namespaceId = lfirst_oid(l);
1318 if (namespaceId == myTempNamespace)
1319 continue; /* do not look in temp namespace */
1321 opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
1322 ObjectIdGetDatum(amid),
1323 PointerGetDatum(opfname),
1324 ObjectIdGetDatum(namespaceId),
1326 if (OidIsValid(opfid))
1330 /* Not found in path */
1336 * Determine whether an opfamily (identified by OID) is visible in the
1337 * current search path. Visible means "would be found by searching
1338 * for the unqualified opfamily name".
1341 OpfamilyIsVisible(Oid opfid)
1344 Form_pg_opfamily opfform;
1348 opftup = SearchSysCache(OPFAMILYOID,
1349 ObjectIdGetDatum(opfid),
1351 if (!HeapTupleIsValid(opftup))
1352 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
1353 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
1355 recomputeNamespacePath();
1358 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1359 * the system namespace are surely in the path and so we needn't even do
1360 * list_member_oid() for them.
1362 opfnamespace = opfform->opfnamespace;
1363 if (opfnamespace != PG_CATALOG_NAMESPACE &&
1364 !list_member_oid(activeSearchPath, opfnamespace))
1369 * If it is in the path, it might still not be visible; it could be
1370 * hidden by another opfamily of the same name earlier in the path. So
1371 * we must do a slow check to see if this opfamily would be found by
1372 * OpfamilynameGetOpfid.
1374 char *opfname = NameStr(opfform->opfname);
1376 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
1379 ReleaseSysCache(opftup);
1385 * ConversionGetConid
1386 * Try to resolve an unqualified conversion name.
1387 * Returns OID if conversion found in search path, else InvalidOid.
1389 * This is essentially the same as RelnameGetRelid.
1392 ConversionGetConid(const char *conname)
1397 recomputeNamespacePath();
1399 foreach(l, activeSearchPath)
1401 Oid namespaceId = lfirst_oid(l);
1403 if (namespaceId == myTempNamespace)
1404 continue; /* do not look in temp namespace */
1406 conid = GetSysCacheOid(CONNAMENSP,
1407 PointerGetDatum(conname),
1408 ObjectIdGetDatum(namespaceId),
1410 if (OidIsValid(conid))
1414 /* Not found in path */
1419 * ConversionIsVisible
1420 * Determine whether a conversion (identified by OID) is visible in the
1421 * current search path. Visible means "would be found by searching
1422 * for the unqualified conversion name".
1425 ConversionIsVisible(Oid conid)
1428 Form_pg_conversion conform;
1432 contup = SearchSysCache(CONVOID,
1433 ObjectIdGetDatum(conid),
1435 if (!HeapTupleIsValid(contup))
1436 elog(ERROR, "cache lookup failed for conversion %u", conid);
1437 conform = (Form_pg_conversion) GETSTRUCT(contup);
1439 recomputeNamespacePath();
1442 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1443 * the system namespace are surely in the path and so we needn't even do
1444 * list_member_oid() for them.
1446 connamespace = conform->connamespace;
1447 if (connamespace != PG_CATALOG_NAMESPACE &&
1448 !list_member_oid(activeSearchPath, connamespace))
1453 * If it is in the path, it might still not be visible; it could be
1454 * hidden by another conversion of the same name earlier in the path.
1455 * So we must do a slow check to see if this conversion would be found
1456 * by ConversionGetConid.
1458 char *conname = NameStr(conform->conname);
1460 visible = (ConversionGetConid(conname) == conid);
1463 ReleaseSysCache(contup);
1469 * TSParserGetPrsid - find a TS parser by possibly qualified name
1471 * If not found, returns InvalidOid if failOK, else throws error
1474 TSParserGetPrsid(List *names, bool failOK)
1479 Oid prsoid = InvalidOid;
1482 /* deconstruct the name list */
1483 DeconstructQualifiedName(names, &schemaname, &parser_name);
1487 /* use exact schema given */
1488 namespaceId = LookupExplicitNamespace(schemaname);
1489 prsoid = GetSysCacheOid(TSPARSERNAMENSP,
1490 PointerGetDatum(parser_name),
1491 ObjectIdGetDatum(namespaceId),
1496 /* search for it in search path */
1497 recomputeNamespacePath();
1499 foreach(l, activeSearchPath)
1501 namespaceId = lfirst_oid(l);
1503 if (namespaceId == myTempNamespace)
1504 continue; /* do not look in temp namespace */
1506 prsoid = GetSysCacheOid(TSPARSERNAMENSP,
1507 PointerGetDatum(parser_name),
1508 ObjectIdGetDatum(namespaceId),
1510 if (OidIsValid(prsoid))
1515 if (!OidIsValid(prsoid) && !failOK)
1517 (errcode(ERRCODE_UNDEFINED_OBJECT),
1518 errmsg("text search parser \"%s\" does not exist",
1519 NameListToString(names))));
1526 * Determine whether a parser (identified by OID) is visible in the
1527 * current search path. Visible means "would be found by searching
1528 * for the unqualified parser name".
1531 TSParserIsVisible(Oid prsId)
1534 Form_pg_ts_parser form;
1538 tup = SearchSysCache(TSPARSEROID,
1539 ObjectIdGetDatum(prsId),
1541 if (!HeapTupleIsValid(tup))
1542 elog(ERROR, "cache lookup failed for text search parser %u", prsId);
1543 form = (Form_pg_ts_parser) GETSTRUCT(tup);
1545 recomputeNamespacePath();
1548 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1549 * the system namespace are surely in the path and so we needn't even do
1550 * list_member_oid() for them.
1552 namespace = form->prsnamespace;
1553 if (namespace != PG_CATALOG_NAMESPACE &&
1554 !list_member_oid(activeSearchPath, namespace))
1559 * If it is in the path, it might still not be visible; it could be
1560 * hidden by another parser of the same name earlier in the path. So
1561 * we must do a slow check for conflicting parsers.
1563 char *name = NameStr(form->prsname);
1567 foreach(l, activeSearchPath)
1569 Oid namespaceId = lfirst_oid(l);
1571 if (namespaceId == myTempNamespace)
1572 continue; /* do not look in temp namespace */
1574 if (namespaceId == namespace)
1576 /* Found it first in path */
1580 if (SearchSysCacheExists(TSPARSERNAMENSP,
1581 PointerGetDatum(name),
1582 ObjectIdGetDatum(namespaceId),
1585 /* Found something else first in path */
1591 ReleaseSysCache(tup);
1597 * TSDictionaryGetDictid - find a TS dictionary by possibly qualified name
1599 * If not found, returns InvalidOid if failOK, else throws error
1602 TSDictionaryGetDictid(List *names, bool failOK)
1607 Oid dictoid = InvalidOid;
1610 /* deconstruct the name list */
1611 DeconstructQualifiedName(names, &schemaname, &dict_name);
1615 /* use exact schema given */
1616 namespaceId = LookupExplicitNamespace(schemaname);
1617 dictoid = GetSysCacheOid(TSDICTNAMENSP,
1618 PointerGetDatum(dict_name),
1619 ObjectIdGetDatum(namespaceId),
1624 /* search for it in search path */
1625 recomputeNamespacePath();
1627 foreach(l, activeSearchPath)
1629 namespaceId = lfirst_oid(l);
1631 if (namespaceId == myTempNamespace)
1632 continue; /* do not look in temp namespace */
1634 dictoid = GetSysCacheOid(TSDICTNAMENSP,
1635 PointerGetDatum(dict_name),
1636 ObjectIdGetDatum(namespaceId),
1638 if (OidIsValid(dictoid))
1643 if (!OidIsValid(dictoid) && !failOK)
1645 (errcode(ERRCODE_UNDEFINED_OBJECT),
1646 errmsg("text search dictionary \"%s\" does not exist",
1647 NameListToString(names))));
1653 * TSDictionaryIsVisible
1654 * Determine whether a dictionary (identified by OID) is visible in the
1655 * current search path. Visible means "would be found by searching
1656 * for the unqualified dictionary name".
1659 TSDictionaryIsVisible(Oid dictId)
1662 Form_pg_ts_dict form;
1666 tup = SearchSysCache(TSDICTOID,
1667 ObjectIdGetDatum(dictId),
1669 if (!HeapTupleIsValid(tup))
1670 elog(ERROR, "cache lookup failed for text search dictionary %u",
1672 form = (Form_pg_ts_dict) GETSTRUCT(tup);
1674 recomputeNamespacePath();
1677 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1678 * the system namespace are surely in the path and so we needn't even do
1679 * list_member_oid() for them.
1681 namespace = form->dictnamespace;
1682 if (namespace != PG_CATALOG_NAMESPACE &&
1683 !list_member_oid(activeSearchPath, namespace))
1688 * If it is in the path, it might still not be visible; it could be
1689 * hidden by another dictionary of the same name earlier in the path.
1690 * So we must do a slow check for conflicting dictionaries.
1692 char *name = NameStr(form->dictname);
1696 foreach(l, activeSearchPath)
1698 Oid namespaceId = lfirst_oid(l);
1700 if (namespaceId == myTempNamespace)
1701 continue; /* do not look in temp namespace */
1703 if (namespaceId == namespace)
1705 /* Found it first in path */
1709 if (SearchSysCacheExists(TSDICTNAMENSP,
1710 PointerGetDatum(name),
1711 ObjectIdGetDatum(namespaceId),
1714 /* Found something else first in path */
1720 ReleaseSysCache(tup);
1726 * TSTemplateGetTmplid - find a TS template by possibly qualified name
1728 * If not found, returns InvalidOid if failOK, else throws error
1731 TSTemplateGetTmplid(List *names, bool failOK)
1734 char *template_name;
1736 Oid tmploid = InvalidOid;
1739 /* deconstruct the name list */
1740 DeconstructQualifiedName(names, &schemaname, &template_name);
1744 /* use exact schema given */
1745 namespaceId = LookupExplicitNamespace(schemaname);
1746 tmploid = GetSysCacheOid(TSTEMPLATENAMENSP,
1747 PointerGetDatum(template_name),
1748 ObjectIdGetDatum(namespaceId),
1753 /* search for it in search path */
1754 recomputeNamespacePath();
1756 foreach(l, activeSearchPath)
1758 namespaceId = lfirst_oid(l);
1760 if (namespaceId == myTempNamespace)
1761 continue; /* do not look in temp namespace */
1763 tmploid = GetSysCacheOid(TSTEMPLATENAMENSP,
1764 PointerGetDatum(template_name),
1765 ObjectIdGetDatum(namespaceId),
1767 if (OidIsValid(tmploid))
1772 if (!OidIsValid(tmploid) && !failOK)
1774 (errcode(ERRCODE_UNDEFINED_OBJECT),
1775 errmsg("text search template \"%s\" does not exist",
1776 NameListToString(names))));
1782 * TSTemplateIsVisible
1783 * Determine whether a template (identified by OID) is visible in the
1784 * current search path. Visible means "would be found by searching
1785 * for the unqualified template name".
1788 TSTemplateIsVisible(Oid tmplId)
1791 Form_pg_ts_template form;
1795 tup = SearchSysCache(TSTEMPLATEOID,
1796 ObjectIdGetDatum(tmplId),
1798 if (!HeapTupleIsValid(tup))
1799 elog(ERROR, "cache lookup failed for text search template %u", tmplId);
1800 form = (Form_pg_ts_template) GETSTRUCT(tup);
1802 recomputeNamespacePath();
1805 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1806 * the system namespace are surely in the path and so we needn't even do
1807 * list_member_oid() for them.
1809 namespace = form->tmplnamespace;
1810 if (namespace != PG_CATALOG_NAMESPACE &&
1811 !list_member_oid(activeSearchPath, namespace))
1816 * If it is in the path, it might still not be visible; it could be
1817 * hidden by another template of the same name earlier in the path. So
1818 * we must do a slow check for conflicting templates.
1820 char *name = NameStr(form->tmplname);
1824 foreach(l, activeSearchPath)
1826 Oid namespaceId = lfirst_oid(l);
1828 if (namespaceId == myTempNamespace)
1829 continue; /* do not look in temp namespace */
1831 if (namespaceId == namespace)
1833 /* Found it first in path */
1837 if (SearchSysCacheExists(TSTEMPLATENAMENSP,
1838 PointerGetDatum(name),
1839 ObjectIdGetDatum(namespaceId),
1842 /* Found something else first in path */
1848 ReleaseSysCache(tup);
1854 * TSConfigGetCfgid - find a TS config by possibly qualified name
1856 * If not found, returns InvalidOid if failOK, else throws error
1859 TSConfigGetCfgid(List *names, bool failOK)
1864 Oid cfgoid = InvalidOid;
1867 /* deconstruct the name list */
1868 DeconstructQualifiedName(names, &schemaname, &config_name);
1872 /* use exact schema given */
1873 namespaceId = LookupExplicitNamespace(schemaname);
1874 cfgoid = GetSysCacheOid(TSCONFIGNAMENSP,
1875 PointerGetDatum(config_name),
1876 ObjectIdGetDatum(namespaceId),
1881 /* search for it in search path */
1882 recomputeNamespacePath();
1884 foreach(l, activeSearchPath)
1886 namespaceId = lfirst_oid(l);
1888 if (namespaceId == myTempNamespace)
1889 continue; /* do not look in temp namespace */
1891 cfgoid = GetSysCacheOid(TSCONFIGNAMENSP,
1892 PointerGetDatum(config_name),
1893 ObjectIdGetDatum(namespaceId),
1895 if (OidIsValid(cfgoid))
1900 if (!OidIsValid(cfgoid) && !failOK)
1902 (errcode(ERRCODE_UNDEFINED_OBJECT),
1903 errmsg("text search configuration \"%s\" does not exist",
1904 NameListToString(names))));
1911 * Determine whether a text search configuration (identified by OID)
1912 * is visible in the current search path. Visible means "would be found
1913 * by searching for the unqualified text search configuration name".
1916 TSConfigIsVisible(Oid cfgid)
1919 Form_pg_ts_config form;
1923 tup = SearchSysCache(TSCONFIGOID,
1924 ObjectIdGetDatum(cfgid),
1926 if (!HeapTupleIsValid(tup))
1927 elog(ERROR, "cache lookup failed for text search configuration %u",
1929 form = (Form_pg_ts_config) GETSTRUCT(tup);
1931 recomputeNamespacePath();
1934 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1935 * the system namespace are surely in the path and so we needn't even do
1936 * list_member_oid() for them.
1938 namespace = form->cfgnamespace;
1939 if (namespace != PG_CATALOG_NAMESPACE &&
1940 !list_member_oid(activeSearchPath, namespace))
1945 * If it is in the path, it might still not be visible; it could be
1946 * hidden by another configuration of the same name earlier in the
1947 * path. So we must do a slow check for conflicting configurations.
1949 char *name = NameStr(form->cfgname);
1953 foreach(l, activeSearchPath)
1955 Oid namespaceId = lfirst_oid(l);
1957 if (namespaceId == myTempNamespace)
1958 continue; /* do not look in temp namespace */
1960 if (namespaceId == namespace)
1962 /* Found it first in path */
1966 if (SearchSysCacheExists(TSCONFIGNAMENSP,
1967 PointerGetDatum(name),
1968 ObjectIdGetDatum(namespaceId),
1971 /* Found something else first in path */
1977 ReleaseSysCache(tup);
1984 * DeconstructQualifiedName
1985 * Given a possibly-qualified name expressed as a list of String nodes,
1986 * extract the schema name and object name.
1988 * *nspname_p is set to NULL if there is no explicit schema name.
1991 DeconstructQualifiedName(List *names,
1996 char *schemaname = NULL;
1997 char *objname = NULL;
1999 switch (list_length(names))
2002 objname = strVal(linitial(names));
2005 schemaname = strVal(linitial(names));
2006 objname = strVal(lsecond(names));
2009 catalogname = strVal(linitial(names));
2010 schemaname = strVal(lsecond(names));
2011 objname = strVal(lthird(names));
2014 * We check the catalog name and then ignore it.
2016 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
2018 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2019 errmsg("cross-database references are not implemented: %s",
2020 NameListToString(names))));
2024 (errcode(ERRCODE_SYNTAX_ERROR),
2025 errmsg("improper qualified name (too many dotted names): %s",
2026 NameListToString(names))));
2030 *nspname_p = schemaname;
2031 *objname_p = objname;
2035 * LookupExplicitNamespace
2036 * Process an explicitly-specified schema name: look up the schema
2037 * and verify we have USAGE (lookup) rights in it.
2039 * Returns the namespace OID. Raises ereport if any problem.
2042 LookupExplicitNamespace(const char *nspname)
2045 AclResult aclresult;
2047 /* check for pg_temp alias */
2048 if (strcmp(nspname, "pg_temp") == 0)
2050 if (OidIsValid(myTempNamespace))
2051 return myTempNamespace;
2054 * Since this is used only for looking up existing objects, there is
2055 * no point in trying to initialize the temp namespace here; and doing
2056 * so might create problems for some callers. Just fall through and
2057 * give the "does not exist" error.
2061 namespaceId = GetSysCacheOid(NAMESPACENAME,
2062 CStringGetDatum(nspname),
2064 if (!OidIsValid(namespaceId))
2066 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2067 errmsg("schema \"%s\" does not exist", nspname)));
2069 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
2070 if (aclresult != ACLCHECK_OK)
2071 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2078 * LookupCreationNamespace
2079 * Look up the schema and verify we have CREATE rights on it.
2081 * This is just like LookupExplicitNamespace except for the permission check,
2082 * and that we are willing to create pg_temp if needed.
2084 * Note: calling this may result in a CommandCounterIncrement operation,
2085 * if we have to create or clean out the temp namespace.
2088 LookupCreationNamespace(const char *nspname)
2091 AclResult aclresult;
2093 /* check for pg_temp alias */
2094 if (strcmp(nspname, "pg_temp") == 0)
2096 /* Initialize temp namespace if first time through */
2097 if (!OidIsValid(myTempNamespace))
2098 InitTempTableNamespace();
2099 return myTempNamespace;
2102 namespaceId = GetSysCacheOid(NAMESPACENAME,
2103 CStringGetDatum(nspname),
2105 if (!OidIsValid(namespaceId))
2107 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2108 errmsg("schema \"%s\" does not exist", nspname)));
2110 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
2111 if (aclresult != ACLCHECK_OK)
2112 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2119 * QualifiedNameGetCreationNamespace
2120 * Given a possibly-qualified name for an object (in List-of-Values
2121 * format), determine what namespace the object should be created in.
2122 * Also extract and return the object name (last component of list).
2124 * Note: this does not apply any permissions check. Callers must check
2125 * for CREATE rights on the selected namespace when appropriate.
2127 * Note: calling this may result in a CommandCounterIncrement operation,
2128 * if we have to create or clean out the temp namespace.
2131 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
2136 /* deconstruct the name list */
2137 DeconstructQualifiedName(names, &schemaname, objname_p);
2141 /* check for pg_temp alias */
2142 if (strcmp(schemaname, "pg_temp") == 0)
2144 /* Initialize temp namespace if first time through */
2145 if (!OidIsValid(myTempNamespace))
2146 InitTempTableNamespace();
2147 return myTempNamespace;
2149 /* use exact schema given */
2150 namespaceId = GetSysCacheOid(NAMESPACENAME,
2151 CStringGetDatum(schemaname),
2153 if (!OidIsValid(namespaceId))
2155 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2156 errmsg("schema \"%s\" does not exist", schemaname)));
2157 /* we do not check for USAGE rights here! */
2161 /* use the default creation namespace */
2162 recomputeNamespacePath();
2163 if (activeTempCreationPending)
2165 /* Need to initialize temp namespace */
2166 InitTempTableNamespace();
2167 return myTempNamespace;
2169 namespaceId = activeCreationNamespace;
2170 if (!OidIsValid(namespaceId))
2172 (errcode(ERRCODE_UNDEFINED_SCHEMA),
2173 errmsg("no schema has been selected to create in")));
2180 * makeRangeVarFromNameList
2181 * Utility routine to convert a qualified-name list into RangeVar form.
2184 makeRangeVarFromNameList(List *names)
2186 RangeVar *rel = makeRangeVar(NULL, NULL);
2188 switch (list_length(names))
2191 rel->relname = strVal(linitial(names));
2194 rel->schemaname = strVal(linitial(names));
2195 rel->relname = strVal(lsecond(names));
2198 rel->catalogname = strVal(linitial(names));
2199 rel->schemaname = strVal(lsecond(names));
2200 rel->relname = strVal(lthird(names));
2204 (errcode(ERRCODE_SYNTAX_ERROR),
2205 errmsg("improper relation name (too many dotted names): %s",
2206 NameListToString(names))));
2215 * Utility routine to convert a qualified-name list into a string.
2217 * This is used primarily to form error messages, and so we do not quote
2218 * the list elements, for the sake of legibility.
2221 NameListToString(List *names)
2223 StringInfoData string;
2226 initStringInfo(&string);
2230 if (l != list_head(names))
2231 appendStringInfoChar(&string, '.');
2232 appendStringInfoString(&string, strVal(lfirst(l)));
2239 * NameListToQuotedString
2240 * Utility routine to convert a qualified-name list into a string.
2242 * Same as above except that names will be double-quoted where necessary,
2243 * so the string could be re-parsed (eg, by textToQualifiedNameList).
2246 NameListToQuotedString(List *names)
2248 StringInfoData string;
2251 initStringInfo(&string);
2255 if (l != list_head(names))
2256 appendStringInfoChar(&string, '.');
2257 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
2264 * isTempNamespace - is the given namespace my temporary-table namespace?
2267 isTempNamespace(Oid namespaceId)
2269 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
2275 * isTempToastNamespace - is the given namespace my temporary-toast-table
2279 isTempToastNamespace(Oid namespaceId)
2281 if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
2287 * isTempOrToastNamespace - is the given namespace my temporary-table
2288 * namespace or my temporary-toast-table namespace?
2291 isTempOrToastNamespace(Oid namespaceId)
2293 if (OidIsValid(myTempNamespace) &&
2294 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
2300 * isAnyTempNamespace - is the given namespace a temporary-table namespace
2301 * (either my own, or another backend's)? Temporary-toast-table namespaces
2302 * are included, too.
2305 isAnyTempNamespace(Oid namespaceId)
2310 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2311 nspname = get_namespace_name(namespaceId);
2313 return false; /* no such namespace? */
2314 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
2315 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
2321 * isOtherTempNamespace - is the given namespace some other backend's
2322 * temporary-table namespace (including temporary-toast-table namespaces)?
2325 isOtherTempNamespace(Oid namespaceId)
2327 /* If it's my own temp namespace, say "false" */
2328 if (isTempOrToastNamespace(namespaceId))
2330 /* Else, if it's any temp namespace, say "true" */
2331 return isAnyTempNamespace(namespaceId);
2335 * GetTempNamespaceBackendId - if the given namespace is a temporary-table
2336 * namespace (either my own, or another backend's), return the BackendId
2337 * that owns it. Temporary-toast-table namespaces are included, too.
2338 * If it isn't a temp namespace, return -1.
2341 GetTempNamespaceBackendId(Oid namespaceId)
2346 /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2347 nspname = get_namespace_name(namespaceId);
2349 return -1; /* no such namespace? */
2350 if (strncmp(nspname, "pg_temp_", 8) == 0)
2351 result = atoi(nspname + 8);
2352 else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
2353 result = atoi(nspname + 14);
2361 * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
2362 * which must already be assigned. (This is only used when creating a toast
2363 * table for a temp table, so we must have already done InitTempTableNamespace)
2366 GetTempToastNamespace(void)
2368 Assert(OidIsValid(myTempToastNamespace));
2369 return myTempToastNamespace;
2374 * GetOverrideSearchPath - fetch current search path definition in form
2375 * used by PushOverrideSearchPath.
2377 * The result structure is allocated in the specified memory context
2378 * (which might or might not be equal to CurrentMemoryContext); but any
2379 * junk created by revalidation calculations will be in CurrentMemoryContext.
2381 OverrideSearchPath *
2382 GetOverrideSearchPath(MemoryContext context)
2384 OverrideSearchPath *result;
2386 MemoryContext oldcxt;
2388 recomputeNamespacePath();
2390 oldcxt = MemoryContextSwitchTo(context);
2392 result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
2393 schemas = list_copy(activeSearchPath);
2394 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
2396 if (linitial_oid(schemas) == myTempNamespace)
2397 result->addTemp = true;
2400 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
2401 result->addCatalog = true;
2403 schemas = list_delete_first(schemas);
2405 result->schemas = schemas;
2407 MemoryContextSwitchTo(oldcxt);
2413 * PushOverrideSearchPath - temporarily override the search path
2415 * We allow nested overrides, hence the push/pop terminology. The GUC
2416 * search_path variable is ignored while an override is active.
2419 PushOverrideSearchPath(OverrideSearchPath *newpath)
2421 OverrideStackEntry *entry;
2424 MemoryContext oldcxt;
2427 * Copy the list for safekeeping, and insert implicitly-searched
2428 * namespaces as needed. This code should track recomputeNamespacePath.
2430 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2432 oidlist = list_copy(newpath->schemas);
2435 * Remember the first member of the explicit list.
2438 firstNS = InvalidOid;
2440 firstNS = linitial_oid(oidlist);
2443 * Add any implicitly-searched namespaces to the list. Note these go on
2444 * the front, not the back; also notice that we do not check USAGE
2445 * permissions for these.
2447 if (newpath->addCatalog)
2448 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2450 if (newpath->addTemp)
2452 Assert(OidIsValid(myTempNamespace));
2453 oidlist = lcons_oid(myTempNamespace, oidlist);
2457 * Build the new stack entry, then insert it at the head of the list.
2459 entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
2460 entry->searchPath = oidlist;
2461 entry->creationNamespace = firstNS;
2462 entry->nestLevel = GetCurrentTransactionNestLevel();
2464 overrideStack = lcons(entry, overrideStack);
2466 /* And make it active. */
2467 activeSearchPath = entry->searchPath;
2468 activeCreationNamespace = entry->creationNamespace;
2469 activeTempCreationPending = false; /* XXX is this OK? */
2471 MemoryContextSwitchTo(oldcxt);
2475 * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
2477 * Any push during a (sub)transaction will be popped automatically at abort.
2478 * But it's caller error if a push isn't popped in normal control flow.
2481 PopOverrideSearchPath(void)
2483 OverrideStackEntry *entry;
2485 /* Sanity checks. */
2486 if (overrideStack == NIL)
2487 elog(ERROR, "bogus PopOverrideSearchPath call");
2488 entry = (OverrideStackEntry *) linitial(overrideStack);
2489 if (entry->nestLevel != GetCurrentTransactionNestLevel())
2490 elog(ERROR, "bogus PopOverrideSearchPath call");
2492 /* Pop the stack and free storage. */
2493 overrideStack = list_delete_first(overrideStack);
2494 list_free(entry->searchPath);
2497 /* Activate the next level down. */
2500 entry = (OverrideStackEntry *) linitial(overrideStack);
2501 activeSearchPath = entry->searchPath;
2502 activeCreationNamespace = entry->creationNamespace;
2503 activeTempCreationPending = false; /* XXX is this OK? */
2507 /* If not baseSearchPathValid, this is useless but harmless */
2508 activeSearchPath = baseSearchPath;
2509 activeCreationNamespace = baseCreationNamespace;
2510 activeTempCreationPending = baseTempCreationPending;
2516 * FindConversionByName - find a conversion by possibly qualified name
2519 FindConversionByName(List *name)
2522 char *conversion_name;
2527 /* deconstruct the name list */
2528 DeconstructQualifiedName(name, &schemaname, &conversion_name);
2532 /* use exact schema given */
2533 namespaceId = LookupExplicitNamespace(schemaname);
2534 return FindConversion(conversion_name, namespaceId);
2538 /* search for it in search path */
2539 recomputeNamespacePath();
2541 foreach(l, activeSearchPath)
2543 namespaceId = lfirst_oid(l);
2545 if (namespaceId == myTempNamespace)
2546 continue; /* do not look in temp namespace */
2548 conoid = FindConversion(conversion_name, namespaceId);
2549 if (OidIsValid(conoid))
2554 /* Not found in path */
2559 * FindDefaultConversionProc - find default encoding conversion proc
2562 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
2567 recomputeNamespacePath();
2569 foreach(l, activeSearchPath)
2571 Oid namespaceId = lfirst_oid(l);
2573 if (namespaceId == myTempNamespace)
2574 continue; /* do not look in temp namespace */
2576 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
2577 if (OidIsValid(proc))
2581 /* Not found in path */
2586 * recomputeNamespacePath - recompute path derived variables if needed.
2589 recomputeNamespacePath(void)
2591 Oid roleid = GetUserId();
2599 MemoryContext oldcxt;
2601 /* Do nothing if an override search spec is active. */
2605 /* Do nothing if path is already valid. */
2606 if (baseSearchPathValid && namespaceUser == roleid)
2609 /* Need a modifiable copy of namespace_search_path string */
2610 rawname = pstrdup(namespace_search_path);
2612 /* Parse string into list of identifiers */
2613 if (!SplitIdentifierString(rawname, ',', &namelist))
2615 /* syntax error in name list */
2616 /* this should not happen if GUC checked check_search_path */
2617 elog(ERROR, "invalid list syntax");
2621 * Convert the list of names to a list of OIDs. If any names are not
2622 * recognizable or we don't have read access, just leave them out of the
2623 * list. (We can't raise an error, since the search_path setting has
2624 * already been accepted.) Don't make duplicate entries, either.
2627 temp_missing = false;
2628 foreach(l, namelist)
2630 char *curname = (char *) lfirst(l);
2633 if (strcmp(curname, "$user") == 0)
2635 /* $user --- substitute namespace matching user name, if any */
2638 tuple = SearchSysCache(AUTHOID,
2639 ObjectIdGetDatum(roleid),
2641 if (HeapTupleIsValid(tuple))
2645 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
2646 namespaceId = GetSysCacheOid(NAMESPACENAME,
2647 CStringGetDatum(rname),
2649 ReleaseSysCache(tuple);
2650 if (OidIsValid(namespaceId) &&
2651 !list_member_oid(oidlist, namespaceId) &&
2652 pg_namespace_aclcheck(namespaceId, roleid,
2653 ACL_USAGE) == ACLCHECK_OK)
2654 oidlist = lappend_oid(oidlist, namespaceId);
2657 else if (strcmp(curname, "pg_temp") == 0)
2659 /* pg_temp --- substitute temp namespace, if any */
2660 if (OidIsValid(myTempNamespace))
2662 if (!list_member_oid(oidlist, myTempNamespace))
2663 oidlist = lappend_oid(oidlist, myTempNamespace);
2667 /* If it ought to be the creation namespace, set flag */
2669 temp_missing = true;
2674 /* normal namespace reference */
2675 namespaceId = GetSysCacheOid(NAMESPACENAME,
2676 CStringGetDatum(curname),
2678 if (OidIsValid(namespaceId) &&
2679 !list_member_oid(oidlist, namespaceId) &&
2680 pg_namespace_aclcheck(namespaceId, roleid,
2681 ACL_USAGE) == ACLCHECK_OK)
2682 oidlist = lappend_oid(oidlist, namespaceId);
2687 * Remember the first member of the explicit list. (Note: this is
2688 * nominally wrong if temp_missing, but we need it anyway to distinguish
2689 * explicit from implicit mention of pg_catalog.)
2692 firstNS = InvalidOid;
2694 firstNS = linitial_oid(oidlist);
2697 * Add any implicitly-searched namespaces to the list. Note these go on
2698 * the front, not the back; also notice that we do not check USAGE
2699 * permissions for these.
2701 if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
2702 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
2704 if (OidIsValid(myTempNamespace) &&
2705 !list_member_oid(oidlist, myTempNamespace))
2706 oidlist = lcons_oid(myTempNamespace, oidlist);
2709 * Now that we've successfully built the new list of namespace OIDs, save
2710 * it in permanent storage.
2712 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
2713 newpath = list_copy(oidlist);
2714 MemoryContextSwitchTo(oldcxt);
2716 /* Now safe to assign to state variables. */
2717 list_free(baseSearchPath);
2718 baseSearchPath = newpath;
2719 baseCreationNamespace = firstNS;
2720 baseTempCreationPending = temp_missing;
2722 /* Mark the path valid. */
2723 baseSearchPathValid = true;
2724 namespaceUser = roleid;
2726 /* And make it active. */
2727 activeSearchPath = baseSearchPath;
2728 activeCreationNamespace = baseCreationNamespace;
2729 activeTempCreationPending = baseTempCreationPending;
2733 list_free(namelist);
2738 * InitTempTableNamespace
2739 * Initialize temp table namespace on first use in a particular backend
2742 InitTempTableNamespace(void)
2744 char namespaceName[NAMEDATALEN];
2748 Assert(!OidIsValid(myTempNamespace));
2751 * First, do permission check to see if we are authorized to make temp
2752 * tables. We use a nonstandard error message here since "databasename:
2753 * permission denied" might be a tad cryptic.
2755 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
2756 * that's necessary since current user ID could change during the session.
2757 * But there's no need to make the namespace in the first place until a
2758 * temp table creation request is made by someone with appropriate rights.
2760 if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
2761 ACL_CREATE_TEMP) != ACLCHECK_OK)
2763 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2764 errmsg("permission denied to create temporary tables in database \"%s\"",
2765 get_database_name(MyDatabaseId))));
2767 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
2769 namespaceId = GetSysCacheOid(NAMESPACENAME,
2770 CStringGetDatum(namespaceName),
2772 if (!OidIsValid(namespaceId))
2775 * First use of this temp namespace in this database; create it. The
2776 * temp namespaces are always owned by the superuser. We leave their
2777 * permissions at default --- i.e., no access except to superuser ---
2778 * to ensure that unprivileged users can't peek at other backends'
2779 * temp tables. This works because the places that access the temp
2780 * namespace for my own backend skip permissions checks on it.
2782 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2783 /* Advance command counter to make namespace visible */
2784 CommandCounterIncrement();
2789 * If the namespace already exists, clean it out (in case the former
2790 * owner crashed without doing so).
2792 RemoveTempRelations(namespaceId);
2796 * If the corresponding toast-table namespace doesn't exist yet, create it.
2797 * (We assume there is no need to clean it out if it does exist, since
2798 * dropping a parent table should make its toast table go away.)
2800 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
2803 toastspaceId = GetSysCacheOid(NAMESPACENAME,
2804 CStringGetDatum(namespaceName),
2806 if (!OidIsValid(toastspaceId))
2808 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
2809 /* Advance command counter to make namespace visible */
2810 CommandCounterIncrement();
2814 * Okay, we've prepared the temp namespace ... but it's not committed yet,
2815 * so all our work could be undone by transaction rollback. Set flag for
2816 * AtEOXact_Namespace to know what to do.
2818 myTempNamespace = namespaceId;
2819 myTempToastNamespace = toastspaceId;
2821 /* It should not be done already. */
2822 AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
2823 myTempNamespaceSubID = GetCurrentSubTransactionId();
2825 baseSearchPathValid = false; /* need to rebuild list */
2829 * End-of-transaction cleanup for namespaces.
2832 AtEOXact_Namespace(bool isCommit)
2835 * If we abort the transaction in which a temp namespace was selected,
2836 * we'll have to do any creation or cleanout work over again. So, just
2837 * forget the namespace entirely until next time. On the other hand, if
2838 * we commit then register an exit callback to clean out the temp tables
2839 * at backend shutdown. (We only want to register the callback once per
2840 * session, so this is a good place to do it.)
2842 if (myTempNamespaceSubID != InvalidSubTransactionId)
2845 on_shmem_exit(RemoveTempRelationsCallback, 0);
2848 myTempNamespace = InvalidOid;
2849 myTempToastNamespace = InvalidOid;
2850 baseSearchPathValid = false; /* need to rebuild list */
2852 myTempNamespaceSubID = InvalidSubTransactionId;
2856 * Clean up if someone failed to do PopOverrideSearchPath
2861 elog(WARNING, "leaked override search path");
2862 while (overrideStack)
2864 OverrideStackEntry *entry;
2866 entry = (OverrideStackEntry *) linitial(overrideStack);
2867 overrideStack = list_delete_first(overrideStack);
2868 list_free(entry->searchPath);
2871 /* If not baseSearchPathValid, this is useless but harmless */
2872 activeSearchPath = baseSearchPath;
2873 activeCreationNamespace = baseCreationNamespace;
2874 activeTempCreationPending = baseTempCreationPending;
2879 * AtEOSubXact_Namespace
2881 * At subtransaction commit, propagate the temp-namespace-creation
2882 * flag to the parent subtransaction.
2884 * At subtransaction abort, forget the flag if we set it up.
2887 AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
2888 SubTransactionId parentSubid)
2890 OverrideStackEntry *entry;
2892 if (myTempNamespaceSubID == mySubid)
2895 myTempNamespaceSubID = parentSubid;
2898 myTempNamespaceSubID = InvalidSubTransactionId;
2899 /* TEMP namespace creation failed, so reset state */
2900 myTempNamespace = InvalidOid;
2901 myTempToastNamespace = InvalidOid;
2902 baseSearchPathValid = false; /* need to rebuild list */
2907 * Clean up if someone failed to do PopOverrideSearchPath
2909 while (overrideStack)
2911 entry = (OverrideStackEntry *) linitial(overrideStack);
2912 if (entry->nestLevel < GetCurrentTransactionNestLevel())
2915 elog(WARNING, "leaked override search path");
2916 overrideStack = list_delete_first(overrideStack);
2917 list_free(entry->searchPath);
2921 /* Activate the next level down. */
2924 entry = (OverrideStackEntry *) linitial(overrideStack);
2925 activeSearchPath = entry->searchPath;
2926 activeCreationNamespace = entry->creationNamespace;
2927 activeTempCreationPending = false; /* XXX is this OK? */
2931 /* If not baseSearchPathValid, this is useless but harmless */
2932 activeSearchPath = baseSearchPath;
2933 activeCreationNamespace = baseCreationNamespace;
2934 activeTempCreationPending = baseTempCreationPending;
2939 * Remove all relations in the specified temp namespace.
2941 * This is called at backend shutdown (if we made any temp relations).
2942 * It is also called when we begin using a pre-existing temp namespace,
2943 * in order to clean out any relations that might have been created by
2944 * a crashed backend.
2947 RemoveTempRelations(Oid tempNamespaceId)
2949 ObjectAddress object;
2952 * We want to get rid of everything in the target namespace, but not the
2953 * namespace itself (deleting it only to recreate it later would be a
2954 * waste of cycles). We do this by finding everything that has a
2955 * dependency on the namespace.
2957 object.classId = NamespaceRelationId;
2958 object.objectId = tempNamespaceId;
2959 object.objectSubId = 0;
2961 deleteWhatDependsOn(&object, false);
2965 * Callback to remove temp relations at backend exit.
2968 RemoveTempRelationsCallback(int code, Datum arg)
2970 if (OidIsValid(myTempNamespace)) /* should always be true */
2972 /* Need to ensure we have a usable transaction. */
2973 AbortOutOfAnyTransaction();
2974 StartTransactionCommand();
2976 RemoveTempRelations(myTempNamespace);
2978 CommitTransactionCommand();
2983 * Remove all temp tables from the temporary namespace.
2986 ResetTempTableNamespace(void)
2988 if (OidIsValid(myTempNamespace))
2989 RemoveTempRelations(myTempNamespace);
2994 * Routines for handling the GUC variable 'search_path'.
2997 /* assign_hook: validate new search_path, do extra actions as needed */
2999 assign_search_path(const char *newval, bool doit, GucSource source)
3005 /* Need a modifiable copy of string */
3006 rawname = pstrdup(newval);
3008 /* Parse string into list of identifiers */
3009 if (!SplitIdentifierString(rawname, ',', &namelist))
3011 /* syntax error in name list */
3013 list_free(namelist);
3018 * If we aren't inside a transaction, we cannot do database access so
3019 * cannot verify the individual names. Must accept the list on faith.
3021 if (source >= PGC_S_INTERACTIVE && IsTransactionState())
3024 * Verify that all the names are either valid namespace names or
3025 * "$user" or "pg_temp". We do not require $user to correspond to a
3026 * valid namespace, and pg_temp might not exist yet. We do not check
3027 * for USAGE rights, either; should we?
3029 * When source == PGC_S_TEST, we are checking the argument of an ALTER
3030 * DATABASE SET or ALTER USER SET command. It could be that the
3031 * intended use of the search path is for some other database, so we
3032 * should not error out if it mentions schemas not present in the
3033 * current database. We reduce the message to NOTICE instead.
3035 foreach(l, namelist)
3037 char *curname = (char *) lfirst(l);
3039 if (strcmp(curname, "$user") == 0)
3041 if (strcmp(curname, "pg_temp") == 0)
3043 if (!SearchSysCacheExists(NAMESPACENAME,
3044 CStringGetDatum(curname),
3046 ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
3047 (errcode(ERRCODE_UNDEFINED_SCHEMA),
3048 errmsg("schema \"%s\" does not exist", curname)));
3053 list_free(namelist);
3056 * We mark the path as needing recomputation, but don't do anything until
3057 * it's needed. This avoids trying to do database access during GUC
3061 baseSearchPathValid = false;
3067 * InitializeSearchPath: initialize module during InitPostgres.
3069 * This is called after we are up enough to be able to do catalog lookups.
3072 InitializeSearchPath(void)
3074 if (IsBootstrapProcessingMode())
3077 * In bootstrap mode, the search path must be 'pg_catalog' so that
3078 * tables are created in the proper namespace; ignore the GUC setting.
3080 MemoryContext oldcxt;
3082 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
3083 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
3084 MemoryContextSwitchTo(oldcxt);
3085 baseCreationNamespace = PG_CATALOG_NAMESPACE;
3086 baseTempCreationPending = false;
3087 baseSearchPathValid = true;
3088 namespaceUser = GetUserId();
3089 activeSearchPath = baseSearchPath;
3090 activeCreationNamespace = baseCreationNamespace;
3091 activeTempCreationPending = baseTempCreationPending;
3096 * In normal mode, arrange for a callback on any syscache invalidation
3097 * of pg_namespace rows.
3099 CacheRegisterSyscacheCallback(NAMESPACEOID,
3102 /* Force search path to be recomputed on next use */
3103 baseSearchPathValid = false;
3109 * Syscache inval callback function
3112 NamespaceCallback(Datum arg, Oid relid)
3114 /* Force search path to be recomputed on next use */
3115 baseSearchPathValid = false;
3119 * Fetch the active search path. The return value is a palloc'ed list
3120 * of OIDs; the caller is responsible for freeing this storage as
3123 * The returned list includes the implicitly-prepended namespaces only if
3124 * includeImplicit is true.
3126 * Note: calling this may result in a CommandCounterIncrement operation,
3127 * if we have to create or clean out the temp namespace.
3130 fetch_search_path(bool includeImplicit)
3134 recomputeNamespacePath();
3137 * If the temp namespace should be first, force it to exist. This is so
3138 * that callers can trust the result to reflect the actual default
3139 * creation namespace. It's a bit bogus to do this here, since
3140 * current_schema() is supposedly a stable function without side-effects,
3141 * but the alternatives seem worse.
3143 if (activeTempCreationPending)
3145 InitTempTableNamespace();
3146 recomputeNamespacePath();
3149 result = list_copy(activeSearchPath);
3150 if (!includeImplicit)
3152 while (result && linitial_oid(result) != activeCreationNamespace)
3153 result = list_delete_first(result);
3160 * Fetch the active search path into a caller-allocated array of OIDs.
3161 * Returns the number of path entries. (If this is more than sarray_len,
3162 * then the data didn't fit and is not all stored.)
3164 * The returned list always includes the implicitly-prepended namespaces,
3165 * but never includes the temp namespace. (This is suitable for existing
3166 * users, which would want to ignore the temp namespace anyway.) This
3167 * definition allows us to not worry about initializing the temp namespace.
3170 fetch_search_path_array(Oid *sarray, int sarray_len)
3175 recomputeNamespacePath();
3177 foreach(l, activeSearchPath)
3179 Oid namespaceId = lfirst_oid(l);
3181 if (namespaceId == myTempNamespace)
3182 continue; /* do not include temp namespace */
3184 if (count < sarray_len)
3185 sarray[count] = namespaceId;
3194 * Export the FooIsVisible functions as SQL-callable functions.
3198 pg_table_is_visible(PG_FUNCTION_ARGS)
3200 Oid oid = PG_GETARG_OID(0);
3202 PG_RETURN_BOOL(RelationIsVisible(oid));
3206 pg_type_is_visible(PG_FUNCTION_ARGS)
3208 Oid oid = PG_GETARG_OID(0);
3210 PG_RETURN_BOOL(TypeIsVisible(oid));
3214 pg_function_is_visible(PG_FUNCTION_ARGS)
3216 Oid oid = PG_GETARG_OID(0);
3218 PG_RETURN_BOOL(FunctionIsVisible(oid));
3222 pg_operator_is_visible(PG_FUNCTION_ARGS)
3224 Oid oid = PG_GETARG_OID(0);
3226 PG_RETURN_BOOL(OperatorIsVisible(oid));
3230 pg_opclass_is_visible(PG_FUNCTION_ARGS)
3232 Oid oid = PG_GETARG_OID(0);
3234 PG_RETURN_BOOL(OpclassIsVisible(oid));
3238 pg_conversion_is_visible(PG_FUNCTION_ARGS)
3240 Oid oid = PG_GETARG_OID(0);
3242 PG_RETURN_BOOL(ConversionIsVisible(oid));
3246 pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
3248 Oid oid = PG_GETARG_OID(0);
3250 PG_RETURN_BOOL(TSParserIsVisible(oid));
3254 pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
3256 Oid oid = PG_GETARG_OID(0);
3258 PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
3262 pg_ts_template_is_visible(PG_FUNCTION_ARGS)
3264 Oid oid = PG_GETARG_OID(0);
3266 PG_RETURN_BOOL(TSTemplateIsVisible(oid));
3270 pg_ts_config_is_visible(PG_FUNCTION_ARGS)
3272 Oid oid = PG_GETARG_OID(0);
3274 PG_RETURN_BOOL(TSConfigIsVisible(oid));
3278 pg_my_temp_schema(PG_FUNCTION_ARGS)
3280 PG_RETURN_OID(myTempNamespace);
3284 pg_is_other_temp_schema(PG_FUNCTION_ARGS)
3286 Oid oid = PG_GETARG_OID(0);
3288 PG_RETURN_BOOL(isOtherTempNamespace(oid));