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-2024, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
16 * src/backend/catalog/namespace.c
18 *-------------------------------------------------------------------------
22 #include "access/htup_details.h"
23 #include "access/parallel.h"
24 #include "access/xact.h"
25 #include "access/xlog.h"
26 #include "catalog/dependency.h"
27 #include "catalog/namespace.h"
28 #include "catalog/objectaccess.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_collation.h"
31 #include "catalog/pg_conversion.h"
32 #include "catalog/pg_database.h"
33 #include "catalog/pg_namespace.h"
34 #include "catalog/pg_opclass.h"
35 #include "catalog/pg_operator.h"
36 #include "catalog/pg_opfamily.h"
37 #include "catalog/pg_proc.h"
38 #include "catalog/pg_statistic_ext.h"
39 #include "catalog/pg_ts_config.h"
40 #include "catalog/pg_ts_dict.h"
41 #include "catalog/pg_ts_parser.h"
42 #include "catalog/pg_ts_template.h"
43 #include "catalog/pg_type.h"
44 #include "commands/dbcommands.h"
45 #include "common/hashfn_unstable.h"
47 #include "mb/pg_wchar.h"
48 #include "miscadmin.h"
49 #include "nodes/makefuncs.h"
50 #include "storage/ipc.h"
51 #include "storage/lmgr.h"
52 #include "storage/procarray.h"
53 #include "utils/acl.h"
54 #include "utils/builtins.h"
55 #include "utils/catcache.h"
56 #include "utils/guc_hooks.h"
57 #include "utils/inval.h"
58 #include "utils/lsyscache.h"
59 #include "utils/memutils.h"
60 #include "utils/snapmgr.h"
61 #include "utils/syscache.h"
62 #include "utils/varlena.h"
66 * The namespace search path is a possibly-empty list of namespace OIDs.
67 * In addition to the explicit list, implicitly-searched namespaces
70 * 1. If a TEMP table namespace has been initialized in this session, it
71 * is implicitly searched first.
73 * 2. The system catalog namespace is always searched. If the system
74 * namespace is present in the explicit path then it will be searched in
75 * the specified order; otherwise it will be searched after TEMP tables and
76 * *before* the explicit list. (It might seem that the system namespace
77 * should be implicitly last, but this behavior appears to be required by
78 * SQL99. Also, this provides a way to search the system namespace first
79 * without thereby making it the default creation target namespace.)
81 * For security reasons, searches using the search path will ignore the temp
82 * namespace when searching for any object type other than relations and
83 * types. (We must allow types since temp tables have rowtypes.)
85 * The default creation target namespace is always the first element of the
86 * explicit list. If the explicit list is empty, there is no default target.
88 * The textual specification of search_path can include "$user" to refer to
89 * the namespace named the same as the current user, if any. (This is just
90 * ignored if there is no such namespace.) Also, it can include "pg_temp"
91 * to refer to the current backend's temp namespace. This is usually also
92 * ignorable if the temp namespace hasn't been set up, but there's a special
93 * case: if "pg_temp" appears first then it should be the default creation
94 * target. We kluge this case a little bit so that the temp namespace isn't
95 * set up until the first attempt to create something in it. (The reason for
96 * klugery is that we can't create the temp namespace outside a transaction,
97 * but initial GUC processing of search_path happens outside a transaction.)
98 * activeTempCreationPending is true if "pg_temp" appears first in the string
99 * but is not reflected in activeCreationNamespace because the namespace isn't
102 * In bootstrap mode, the search path is set equal to "pg_catalog", so that
103 * the system namespace is the only one searched or inserted into.
104 * initdb is also careful to set search_path to "pg_catalog" for its
105 * post-bootstrap standalone backend runs. Otherwise the default search
106 * path is determined by GUC. The factory default path contains the PUBLIC
107 * namespace (if it exists), preceded by the user's personal namespace
110 * activeSearchPath is always the actually active path; it points to
111 * baseSearchPath which is the list derived from namespace_search_path.
113 * If baseSearchPathValid is false, then baseSearchPath (and other derived
114 * variables) need to be recomputed from namespace_search_path, or retrieved
115 * from the search path cache if there haven't been any syscache
116 * invalidations. We mark it invalid upon an assignment to
117 * namespace_search_path or receipt of a syscache invalidation event for
118 * pg_namespace or pg_authid. The recomputation is done during the next
121 * Any namespaces mentioned in namespace_search_path that are not readable
122 * by the current user ID are simply left out of baseSearchPath; so
123 * we have to be willing to recompute the path when current userid changes.
124 * namespaceUser is the userid the path has been computed for.
126 * Note: all data pointed to by these List variables is in TopMemoryContext.
128 * activePathGeneration is incremented whenever the effective values of
129 * activeSearchPath/activeCreationNamespace/activeTempCreationPending change.
130 * This can be used to quickly detect whether any change has happened since
131 * a previous examination of the search path state.
134 /* These variables define the actually active state: */
136 static List
*activeSearchPath
= NIL
;
138 /* default place to create stuff; if InvalidOid, no default */
139 static Oid activeCreationNamespace
= InvalidOid
;
141 /* if true, activeCreationNamespace is wrong, it should be temp namespace */
142 static bool activeTempCreationPending
= false;
144 /* current generation counter; make sure this is never zero */
145 static uint64 activePathGeneration
= 1;
147 /* These variables are the values last derived from namespace_search_path: */
149 static List
*baseSearchPath
= NIL
;
151 static Oid baseCreationNamespace
= InvalidOid
;
153 static bool baseTempCreationPending
= false;
155 static Oid namespaceUser
= InvalidOid
;
157 /* The above four values are valid only if baseSearchPathValid */
158 static bool baseSearchPathValid
= true;
161 * Storage for search path cache. Clear searchPathCacheValid as a simple
162 * way to invalidate *all* the cache entries, not just the active one.
164 static bool searchPathCacheValid
= false;
165 static MemoryContext SearchPathCacheContext
= NULL
;
167 typedef struct SearchPathCacheKey
169 const char *searchPath
;
171 } SearchPathCacheKey
;
173 typedef struct SearchPathCacheEntry
175 SearchPathCacheKey key
;
176 List
*oidlist
; /* namespace OIDs that pass ACL checks */
177 List
*finalPath
; /* cached final computed search path */
178 Oid firstNS
; /* first explicitly-listed namespace */
180 bool forceRecompute
; /* force recompute of finalPath */
182 /* needed for simplehash */
184 } SearchPathCacheEntry
;
187 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
188 * in a particular backend session (this happens when a CREATE TEMP TABLE
189 * command is first executed). Thereafter it's the OID of the temp namespace.
191 * myTempToastNamespace is the OID of the namespace for my temp tables' toast
192 * tables. It is set when myTempNamespace is, and is InvalidOid before that.
194 * myTempNamespaceSubID shows whether we've created the TEMP namespace in the
195 * current subtransaction. The flag propagates up the subtransaction tree,
196 * so the main transaction will correctly recognize the flag if all
197 * intermediate subtransactions commit. When it is InvalidSubTransactionId,
198 * we either haven't made the TEMP namespace yet, or have successfully
199 * committed its creation, depending on whether myTempNamespace is valid.
201 static Oid myTempNamespace
= InvalidOid
;
203 static Oid myTempToastNamespace
= InvalidOid
;
205 static SubTransactionId myTempNamespaceSubID
= InvalidSubTransactionId
;
208 * This is the user's textual search path specification --- it's the value
209 * of the GUC variable 'search_path'.
211 char *namespace_search_path
= NULL
;
214 /* Local functions */
215 static bool RelationIsVisibleExt(Oid relid
, bool *is_missing
);
216 static bool TypeIsVisibleExt(Oid typid
, bool *is_missing
);
217 static bool FunctionIsVisibleExt(Oid funcid
, bool *is_missing
);
218 static bool OperatorIsVisibleExt(Oid oprid
, bool *is_missing
);
219 static bool OpclassIsVisibleExt(Oid opcid
, bool *is_missing
);
220 static bool OpfamilyIsVisibleExt(Oid opfid
, bool *is_missing
);
221 static bool CollationIsVisibleExt(Oid collid
, bool *is_missing
);
222 static bool ConversionIsVisibleExt(Oid conid
, bool *is_missing
);
223 static bool StatisticsObjIsVisibleExt(Oid stxid
, bool *is_missing
);
224 static bool TSParserIsVisibleExt(Oid prsId
, bool *is_missing
);
225 static bool TSDictionaryIsVisibleExt(Oid dictId
, bool *is_missing
);
226 static bool TSTemplateIsVisibleExt(Oid tmplId
, bool *is_missing
);
227 static bool TSConfigIsVisibleExt(Oid cfgid
, bool *is_missing
);
228 static void recomputeNamespacePath(void);
229 static void AccessTempTableNamespace(bool force
);
230 static void InitTempTableNamespace(void);
231 static void RemoveTempRelations(Oid tempNamespaceId
);
232 static void RemoveTempRelationsCallback(int code
, Datum arg
);
233 static void InvalidationCallback(Datum arg
, int cacheid
, uint32 hashvalue
);
234 static bool MatchNamedCall(HeapTuple proctup
, int nargs
, List
*argnames
,
235 bool include_out_arguments
, int pronargs
,
239 * Recomputing the namespace path can be costly when done frequently, such as
240 * when a function has search_path set in proconfig. Add a search path cache
241 * that can be used by recomputeNamespacePath().
243 * The cache is also used to remember already-validated strings in
244 * check_search_path() to avoid the need to call SplitIdentifierString()
247 * The search path cache is based on a wrapper around a simplehash hash table
248 * (nsphash, defined below). The spcache wrapper deals with OOM while trying
249 * to initialize a key, optimizes repeated lookups of the same key, and also
250 * offers a more convenient API.
254 spcachekey_hash(SearchPathCacheKey key
)
259 fasthash_init(&hs
, 0);
261 hs
.accum
= key
.roleid
;
262 fasthash_combine(&hs
);
265 * Combine search path into the hash and save the length for tweaking the
268 sp_len
= fasthash_accum_cstring(&hs
, key
.searchPath
);
270 return fasthash_final32(&hs
, sp_len
);
274 spcachekey_equal(SearchPathCacheKey a
, SearchPathCacheKey b
)
276 return a
.roleid
== b
.roleid
&&
277 strcmp(a
.searchPath
, b
.searchPath
) == 0;
280 #define SH_PREFIX nsphash
281 #define SH_ELEMENT_TYPE SearchPathCacheEntry
282 #define SH_KEY_TYPE SearchPathCacheKey
284 #define SH_HASH_KEY(tb, key) spcachekey_hash(key)
285 #define SH_EQUAL(tb, a, b) spcachekey_equal(a, b)
286 #define SH_SCOPE static inline
289 #include "lib/simplehash.h"
292 * We only expect a small number of unique search_path strings to be used. If
293 * this cache grows to an unreasonable size, reset it to avoid steady-state
294 * memory growth. Most likely, only a few of those entries will benefit from
295 * the cache, and the cache will be quickly repopulated with such entries.
297 #define SPCACHE_RESET_THRESHOLD 256
299 static nsphash_hash
*SearchPathCache
= NULL
;
300 static SearchPathCacheEntry
*LastSearchPathCacheEntry
= NULL
;
303 * Create or reset search_path cache as necessary.
308 if (SearchPathCache
&& searchPathCacheValid
&&
309 SearchPathCache
->members
< SPCACHE_RESET_THRESHOLD
)
312 searchPathCacheValid
= false;
313 baseSearchPathValid
= false;
316 * Make sure we don't leave dangling pointers if a failure happens during
319 SearchPathCache
= NULL
;
320 LastSearchPathCacheEntry
= NULL
;
322 if (SearchPathCacheContext
== NULL
)
324 /* Make the context we'll keep search path cache hashtable in */
325 SearchPathCacheContext
= AllocSetContextCreate(TopMemoryContext
,
326 "search_path processing cache",
327 ALLOCSET_DEFAULT_SIZES
);
331 MemoryContextReset(SearchPathCacheContext
);
334 /* arbitrary initial starting size of 16 elements */
335 SearchPathCache
= nsphash_create(SearchPathCacheContext
, 16, NULL
);
336 searchPathCacheValid
= true;
340 * Look up entry in search path cache without inserting. Returns NULL if not
343 static SearchPathCacheEntry
*
344 spcache_lookup(const char *searchPath
, Oid roleid
)
346 if (LastSearchPathCacheEntry
&&
347 LastSearchPathCacheEntry
->key
.roleid
== roleid
&&
348 strcmp(LastSearchPathCacheEntry
->key
.searchPath
, searchPath
) == 0)
350 return LastSearchPathCacheEntry
;
354 SearchPathCacheEntry
*entry
;
355 SearchPathCacheKey cachekey
= {
356 .searchPath
= searchPath
,
360 entry
= nsphash_lookup(SearchPathCache
, cachekey
);
362 LastSearchPathCacheEntry
= entry
;
368 * Look up or insert entry in search path cache.
370 * Initialize key safely, so that OOM does not leave an entry without a valid
371 * key. Caller must ensure that non-key contents are properly initialized.
373 static SearchPathCacheEntry
*
374 spcache_insert(const char *searchPath
, Oid roleid
)
376 if (LastSearchPathCacheEntry
&&
377 LastSearchPathCacheEntry
->key
.roleid
== roleid
&&
378 strcmp(LastSearchPathCacheEntry
->key
.searchPath
, searchPath
) == 0)
380 return LastSearchPathCacheEntry
;
384 SearchPathCacheEntry
*entry
;
385 SearchPathCacheKey cachekey
= {
386 .searchPath
= searchPath
,
391 * searchPath is not saved in SearchPathCacheContext. First perform a
392 * lookup, and copy searchPath only if we need to create a new entry.
394 entry
= nsphash_lookup(SearchPathCache
, cachekey
);
400 cachekey
.searchPath
= MemoryContextStrdup(SearchPathCacheContext
, searchPath
);
401 entry
= nsphash_insert(SearchPathCache
, cachekey
, &found
);
404 entry
->oidlist
= NIL
;
405 entry
->finalPath
= NIL
;
406 entry
->firstNS
= InvalidOid
;
407 entry
->temp_missing
= false;
408 entry
->forceRecompute
= false;
409 /* do not touch entry->status, used by simplehash */
412 LastSearchPathCacheEntry
= entry
;
418 * RangeVarGetRelidExtended
419 * Given a RangeVar describing an existing relation,
420 * select the proper namespace and look up the relation OID.
422 * If the schema or relation is not found, return InvalidOid if flags contains
423 * RVR_MISSING_OK, otherwise raise an error.
425 * If flags contains RVR_NOWAIT, throw an error if we'd have to wait for a
428 * If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait
431 * flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED.
433 * Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a
434 * return value of InvalidOid could either mean the relation is missing or it
435 * could not be locked.
437 * Callback allows caller to check permissions or acquire additional locks
438 * prior to grabbing the relation lock.
441 RangeVarGetRelidExtended(const RangeVar
*relation
, LOCKMODE lockmode
,
443 RangeVarGetRelidCallback callback
, void *callback_arg
)
447 Oid oldRelId
= InvalidOid
;
449 bool missing_ok
= (flags
& RVR_MISSING_OK
) != 0;
451 /* verify that flags do no conflict */
452 Assert(!((flags
& RVR_NOWAIT
) && (flags
& RVR_SKIP_LOCKED
)));
455 * We check the catalog name and then ignore it.
457 if (relation
->catalogname
)
459 if (strcmp(relation
->catalogname
, get_database_name(MyDatabaseId
)) != 0)
461 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
462 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
463 relation
->catalogname
, relation
->schemaname
,
464 relation
->relname
)));
468 * DDL operations can change the results of a name lookup. Since all such
469 * operations will generate invalidation messages, we keep track of
470 * whether any such messages show up while we're performing the operation,
471 * and retry until either (1) no more invalidation messages show up or (2)
472 * the answer doesn't change.
474 * But if lockmode = NoLock, then we assume that either the caller is OK
475 * with the answer changing under them, or that they already hold some
476 * appropriate lock, and therefore return the first answer we get without
477 * checking for invalidation messages. Also, if the requested lock is
478 * already held, LockRelationOid will not AcceptInvalidationMessages, so
479 * we may fail to notice a change. We could protect against that case by
480 * calling AcceptInvalidationMessages() before beginning this loop, but
481 * that would add a significant amount overhead, so for now we don't.
486 * Remember this value, so that, after looking up the relation name
487 * and locking its OID, we can check whether any invalidation messages
488 * have been processed that might require a do-over.
490 inval_count
= SharedInvalidMessageCounter
;
493 * Some non-default relpersistence value may have been specified. The
494 * parser never generates such a RangeVar in simple DML, but it can
495 * happen in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY
496 * KEY)". Such a command will generate an added CREATE INDEX
497 * operation, which must be careful to find the temp table, even when
498 * pg_temp is not first in the search path.
500 if (relation
->relpersistence
== RELPERSISTENCE_TEMP
)
502 if (!OidIsValid(myTempNamespace
))
503 relId
= InvalidOid
; /* this probably can't happen? */
506 if (relation
->schemaname
)
510 namespaceId
= LookupExplicitNamespace(relation
->schemaname
, missing_ok
);
513 * For missing_ok, allow a non-existent schema name to
516 if (namespaceId
!= myTempNamespace
)
518 (errcode(ERRCODE_INVALID_TABLE_DEFINITION
),
519 errmsg("temporary tables cannot specify a schema name")));
522 relId
= get_relname_relid(relation
->relname
, myTempNamespace
);
525 else if (relation
->schemaname
)
529 /* use exact schema given */
530 namespaceId
= LookupExplicitNamespace(relation
->schemaname
, missing_ok
);
531 if (missing_ok
&& !OidIsValid(namespaceId
))
534 relId
= get_relname_relid(relation
->relname
, namespaceId
);
538 /* search the namespace path */
539 relId
= RelnameGetRelid(relation
->relname
);
543 * Invoke caller-supplied callback, if any.
545 * This callback is a good place to check permissions: we haven't
546 * taken the table lock yet (and it's really best to check permissions
547 * before locking anything!), but we've gotten far enough to know what
548 * OID we think we should lock. Of course, concurrent DDL might
549 * change things while we're waiting for the lock, but in that case
550 * the callback will be invoked again for the new OID.
553 callback(relation
, relId
, oldRelId
, callback_arg
);
556 * If no lock requested, we assume the caller knows what they're
557 * doing. They should have already acquired a heavyweight lock on
558 * this relation earlier in the processing of this same statement, so
559 * it wouldn't be appropriate to AcceptInvalidationMessages() here, as
560 * that might pull the rug out from under them.
562 if (lockmode
== NoLock
)
566 * If, upon retry, we get back the same OID we did last time, then the
567 * invalidation messages we processed did not change the final answer.
570 * If we got a different OID, we've locked the relation that used to
571 * have this name rather than the one that does now. So release the
576 if (relId
== oldRelId
)
578 if (OidIsValid(oldRelId
))
579 UnlockRelationOid(oldRelId
, lockmode
);
583 * Lock relation. This will also accept any pending invalidation
584 * messages. If we got back InvalidOid, indicating not found, then
585 * there's nothing to lock, but we accept invalidation messages
586 * anyway, to flush any negative catcache entries that may be
589 if (!OidIsValid(relId
))
590 AcceptInvalidationMessages();
591 else if (!(flags
& (RVR_NOWAIT
| RVR_SKIP_LOCKED
)))
592 LockRelationOid(relId
, lockmode
);
593 else if (!ConditionalLockRelationOid(relId
, lockmode
))
595 int elevel
= (flags
& RVR_SKIP_LOCKED
) ? DEBUG1
: ERROR
;
597 if (relation
->schemaname
)
599 (errcode(ERRCODE_LOCK_NOT_AVAILABLE
),
600 errmsg("could not obtain lock on relation \"%s.%s\"",
601 relation
->schemaname
, relation
->relname
)));
604 (errcode(ERRCODE_LOCK_NOT_AVAILABLE
),
605 errmsg("could not obtain lock on relation \"%s\"",
606 relation
->relname
)));
612 * If no invalidation message were processed, we're done!
614 if (inval_count
== SharedInvalidMessageCounter
)
618 * Something may have changed. Let's repeat the name lookup, to make
619 * sure this name still references the same relation it did
626 if (!OidIsValid(relId
))
628 int elevel
= missing_ok
? DEBUG1
: ERROR
;
630 if (relation
->schemaname
)
632 (errcode(ERRCODE_UNDEFINED_TABLE
),
633 errmsg("relation \"%s.%s\" does not exist",
634 relation
->schemaname
, relation
->relname
)));
637 (errcode(ERRCODE_UNDEFINED_TABLE
),
638 errmsg("relation \"%s\" does not exist",
639 relation
->relname
)));
645 * RangeVarGetCreationNamespace
646 * Given a RangeVar describing a to-be-created relation,
647 * choose which namespace to create it in.
649 * Note: calling this may result in a CommandCounterIncrement operation.
650 * That will happen on the first request for a temp table in any particular
651 * backend run; we will need to either create or clean out the temp schema.
654 RangeVarGetCreationNamespace(const RangeVar
*newRelation
)
659 * We check the catalog name and then ignore it.
661 if (newRelation
->catalogname
)
663 if (strcmp(newRelation
->catalogname
, get_database_name(MyDatabaseId
)) != 0)
665 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
666 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
667 newRelation
->catalogname
, newRelation
->schemaname
,
668 newRelation
->relname
)));
671 if (newRelation
->schemaname
)
673 /* check for pg_temp alias */
674 if (strcmp(newRelation
->schemaname
, "pg_temp") == 0)
676 /* Initialize temp namespace */
677 AccessTempTableNamespace(false);
678 return myTempNamespace
;
680 /* use exact schema given */
681 namespaceId
= get_namespace_oid(newRelation
->schemaname
, false);
682 /* we do not check for USAGE rights here! */
684 else if (newRelation
->relpersistence
== RELPERSISTENCE_TEMP
)
686 /* Initialize temp namespace */
687 AccessTempTableNamespace(false);
688 return myTempNamespace
;
692 /* use the default creation namespace */
693 recomputeNamespacePath();
694 if (activeTempCreationPending
)
696 /* Need to initialize temp namespace */
697 AccessTempTableNamespace(true);
698 return myTempNamespace
;
700 namespaceId
= activeCreationNamespace
;
701 if (!OidIsValid(namespaceId
))
703 (errcode(ERRCODE_UNDEFINED_SCHEMA
),
704 errmsg("no schema has been selected to create in")));
707 /* Note: callers will check for CREATE rights when appropriate */
713 * RangeVarGetAndCheckCreationNamespace
715 * This function returns the OID of the namespace in which a new relation
716 * with a given name should be created. If the user does not have CREATE
717 * permission on the target namespace, this function will instead signal
720 * If non-NULL, *existing_relation_id is set to the OID of any existing relation
721 * with the same name which already exists in that namespace, or to InvalidOid
722 * if no such relation exists.
724 * If lockmode != NoLock, the specified lock mode is acquired on the existing
725 * relation, if any, provided that the current user owns the target relation.
726 * However, if lockmode != NoLock and the user does not own the target
727 * relation, we throw an ERROR, as we must not try to lock relations the
728 * user does not have permissions on.
730 * As a side effect, this function acquires AccessShareLock on the target
731 * namespace. Without this, the namespace could be dropped before our
732 * transaction commits, leaving behind relations with relnamespace pointing
733 * to a no-longer-existent namespace.
735 * As a further side-effect, if the selected namespace is a temporary namespace,
736 * we mark the RangeVar as RELPERSISTENCE_TEMP.
739 RangeVarGetAndCheckCreationNamespace(RangeVar
*relation
,
741 Oid
*existing_relation_id
)
745 Oid oldrelid
= InvalidOid
;
747 Oid oldnspid
= InvalidOid
;
751 * We check the catalog name and then ignore it.
753 if (relation
->catalogname
)
755 if (strcmp(relation
->catalogname
, get_database_name(MyDatabaseId
)) != 0)
757 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
758 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
759 relation
->catalogname
, relation
->schemaname
,
760 relation
->relname
)));
764 * As in RangeVarGetRelidExtended(), we guard against concurrent DDL
765 * operations by tracking whether any invalidation messages are processed
766 * while we're doing the name lookups and acquiring locks. See comments
767 * in that function for a more detailed explanation of this logic.
773 inval_count
= SharedInvalidMessageCounter
;
775 /* Look up creation namespace and check for existing relation. */
776 nspid
= RangeVarGetCreationNamespace(relation
);
777 Assert(OidIsValid(nspid
));
778 if (existing_relation_id
!= NULL
)
779 relid
= get_relname_relid(relation
->relname
, nspid
);
784 * In bootstrap processing mode, we don't bother with permissions or
785 * locking. Permissions might not be working yet, and locking is
788 if (IsBootstrapProcessingMode())
791 /* Check namespace permissions. */
792 aclresult
= object_aclcheck(NamespaceRelationId
, nspid
, GetUserId(), ACL_CREATE
);
793 if (aclresult
!= ACLCHECK_OK
)
794 aclcheck_error(aclresult
, OBJECT_SCHEMA
,
795 get_namespace_name(nspid
));
799 /* If nothing changed, we're done. */
800 if (relid
== oldrelid
&& nspid
== oldnspid
)
802 /* If creation namespace has changed, give up old lock. */
803 if (nspid
!= oldnspid
)
804 UnlockDatabaseObject(NamespaceRelationId
, oldnspid
, 0,
806 /* If name points to something different, give up old lock. */
807 if (relid
!= oldrelid
&& OidIsValid(oldrelid
) && lockmode
!= NoLock
)
808 UnlockRelationOid(oldrelid
, lockmode
);
811 /* Lock namespace. */
812 if (nspid
!= oldnspid
)
813 LockDatabaseObject(NamespaceRelationId
, nspid
, 0, AccessShareLock
);
815 /* Lock relation, if required if and we have permission. */
816 if (lockmode
!= NoLock
&& OidIsValid(relid
))
818 if (!object_ownercheck(RelationRelationId
, relid
, GetUserId()))
819 aclcheck_error(ACLCHECK_NOT_OWNER
, get_relkind_objtype(get_rel_relkind(relid
)),
821 if (relid
!= oldrelid
)
822 LockRelationOid(relid
, lockmode
);
825 /* If no invalidation message were processed, we're done! */
826 if (inval_count
== SharedInvalidMessageCounter
)
829 /* Something may have changed, so recheck our work. */
835 RangeVarAdjustRelationPersistence(relation
, nspid
);
836 if (existing_relation_id
!= NULL
)
837 *existing_relation_id
= relid
;
842 * Adjust the relpersistence for an about-to-be-created relation based on the
843 * creation namespace, and throw an error for invalid combinations.
846 RangeVarAdjustRelationPersistence(RangeVar
*newRelation
, Oid nspid
)
848 switch (newRelation
->relpersistence
)
850 case RELPERSISTENCE_TEMP
:
851 if (!isTempOrTempToastNamespace(nspid
))
853 if (isAnyTempNamespace(nspid
))
855 (errcode(ERRCODE_INVALID_TABLE_DEFINITION
),
856 errmsg("cannot create relations in temporary schemas of other sessions")));
859 (errcode(ERRCODE_INVALID_TABLE_DEFINITION
),
860 errmsg("cannot create temporary relation in non-temporary schema")));
863 case RELPERSISTENCE_PERMANENT
:
864 if (isTempOrTempToastNamespace(nspid
))
865 newRelation
->relpersistence
= RELPERSISTENCE_TEMP
;
866 else if (isAnyTempNamespace(nspid
))
868 (errcode(ERRCODE_INVALID_TABLE_DEFINITION
),
869 errmsg("cannot create relations in temporary schemas of other sessions")));
872 if (isAnyTempNamespace(nspid
))
874 (errcode(ERRCODE_INVALID_TABLE_DEFINITION
),
875 errmsg("only temporary relations may be created in temporary schemas")));
881 * Try to resolve an unqualified relation name.
882 * Returns OID if relation found in search path, else InvalidOid.
885 RelnameGetRelid(const char *relname
)
890 recomputeNamespacePath();
892 foreach(l
, activeSearchPath
)
894 Oid namespaceId
= lfirst_oid(l
);
896 relid
= get_relname_relid(relname
, namespaceId
);
897 if (OidIsValid(relid
))
901 /* Not found in path */
908 * Determine whether a relation (identified by OID) is visible in the
909 * current search path. Visible means "would be found by searching
910 * for the unqualified relation name".
913 RelationIsVisible(Oid relid
)
915 return RelationIsVisibleExt(relid
, NULL
);
919 * RelationIsVisibleExt
920 * As above, but if the relation isn't found and is_missing is not NULL,
921 * then set *is_missing = true and return false instead of throwing
922 * an error. (Caller must initialize *is_missing = false.)
925 RelationIsVisibleExt(Oid relid
, bool *is_missing
)
928 Form_pg_class relform
;
932 reltup
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
933 if (!HeapTupleIsValid(reltup
))
935 if (is_missing
!= NULL
)
940 elog(ERROR
, "cache lookup failed for relation %u", relid
);
942 relform
= (Form_pg_class
) GETSTRUCT(reltup
);
944 recomputeNamespacePath();
947 * Quick check: if it ain't in the path at all, it ain't visible. Items in
948 * the system namespace are surely in the path and so we needn't even do
949 * list_member_oid() for them.
951 relnamespace
= relform
->relnamespace
;
952 if (relnamespace
!= PG_CATALOG_NAMESPACE
&&
953 !list_member_oid(activeSearchPath
, relnamespace
))
958 * If it is in the path, it might still not be visible; it could be
959 * hidden by another relation of the same name earlier in the path. So
960 * we must do a slow check for conflicting relations.
962 char *relname
= NameStr(relform
->relname
);
966 foreach(l
, activeSearchPath
)
968 Oid namespaceId
= lfirst_oid(l
);
970 if (namespaceId
== relnamespace
)
972 /* Found it first in path */
976 if (OidIsValid(get_relname_relid(relname
, namespaceId
)))
978 /* Found something else first in path */
984 ReleaseSysCache(reltup
);
992 * Wrapper for binary compatibility.
995 TypenameGetTypid(const char *typname
)
997 return TypenameGetTypidExtended(typname
, true);
1001 * TypenameGetTypidExtended
1002 * Try to resolve an unqualified datatype name.
1003 * Returns OID if type found in search path, else InvalidOid.
1005 * This is essentially the same as RelnameGetRelid.
1008 TypenameGetTypidExtended(const char *typname
, bool temp_ok
)
1013 recomputeNamespacePath();
1015 foreach(l
, activeSearchPath
)
1017 Oid namespaceId
= lfirst_oid(l
);
1019 if (!temp_ok
&& namespaceId
== myTempNamespace
)
1020 continue; /* do not look in temp namespace */
1022 typid
= GetSysCacheOid2(TYPENAMENSP
, Anum_pg_type_oid
,
1023 PointerGetDatum(typname
),
1024 ObjectIdGetDatum(namespaceId
));
1025 if (OidIsValid(typid
))
1029 /* Not found in path */
1035 * Determine whether a type (identified by OID) is visible in the
1036 * current search path. Visible means "would be found by searching
1037 * for the unqualified type name".
1040 TypeIsVisible(Oid typid
)
1042 return TypeIsVisibleExt(typid
, NULL
);
1047 * As above, but if the type isn't found and is_missing is not NULL,
1048 * then set *is_missing = true and return false instead of throwing
1049 * an error. (Caller must initialize *is_missing = false.)
1052 TypeIsVisibleExt(Oid typid
, bool *is_missing
)
1055 Form_pg_type typform
;
1059 typtup
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
1060 if (!HeapTupleIsValid(typtup
))
1062 if (is_missing
!= NULL
)
1067 elog(ERROR
, "cache lookup failed for type %u", typid
);
1069 typform
= (Form_pg_type
) GETSTRUCT(typtup
);
1071 recomputeNamespacePath();
1074 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1075 * the system namespace are surely in the path and so we needn't even do
1076 * list_member_oid() for them.
1078 typnamespace
= typform
->typnamespace
;
1079 if (typnamespace
!= PG_CATALOG_NAMESPACE
&&
1080 !list_member_oid(activeSearchPath
, typnamespace
))
1085 * If it is in the path, it might still not be visible; it could be
1086 * hidden by another type of the same name earlier in the path. So we
1087 * must do a slow check for conflicting types.
1089 char *typname
= NameStr(typform
->typname
);
1093 foreach(l
, activeSearchPath
)
1095 Oid namespaceId
= lfirst_oid(l
);
1097 if (namespaceId
== typnamespace
)
1099 /* Found it first in path */
1103 if (SearchSysCacheExists2(TYPENAMENSP
,
1104 PointerGetDatum(typname
),
1105 ObjectIdGetDatum(namespaceId
)))
1107 /* Found something else first in path */
1113 ReleaseSysCache(typtup
);
1120 * FuncnameGetCandidates
1121 * Given a possibly-qualified function name and argument count,
1122 * retrieve a list of the possible matches.
1124 * If nargs is -1, we return all functions matching the given name,
1125 * regardless of argument count. (argnames must be NIL, and expand_variadic
1126 * and expand_defaults must be false, in this case.)
1128 * If argnames isn't NIL, we are considering a named- or mixed-notation call,
1129 * and only functions having all the listed argument names will be returned.
1130 * (We assume that length(argnames) <= nargs and all the passed-in names are
1131 * distinct.) The returned structs will include an argnumbers array showing
1132 * the actual argument index for each logical argument position.
1134 * If expand_variadic is true, then variadic functions having the same number
1135 * or fewer arguments will be retrieved, with the variadic argument and any
1136 * additional argument positions filled with the variadic element type.
1137 * nvargs in the returned struct is set to the number of such arguments.
1138 * If expand_variadic is false, variadic arguments are not treated specially,
1139 * and the returned nvargs will always be zero.
1141 * If expand_defaults is true, functions that could match after insertion of
1142 * default argument values will also be retrieved. In this case the returned
1143 * structs could have nargs > passed-in nargs, and ndargs is set to the number
1144 * of additional args (which can be retrieved from the function's
1145 * proargdefaults entry).
1147 * If include_out_arguments is true, then OUT-mode arguments are considered to
1148 * be included in the argument list. Their types are included in the returned
1149 * arrays, and argnumbers are indexes in proallargtypes not proargtypes.
1150 * We also set nominalnargs to be the length of proallargtypes not proargtypes.
1151 * Otherwise OUT-mode arguments are ignored.
1153 * It is not possible for nvargs and ndargs to both be nonzero in the same
1154 * list entry, since default insertion allows matches to functions with more
1155 * than nargs arguments while the variadic transformation requires the same
1158 * When argnames isn't NIL, the returned args[] type arrays are not ordered
1159 * according to the functions' declarations, but rather according to the call:
1160 * first any positional arguments, then the named arguments, then defaulted
1161 * arguments (if needed and allowed by expand_defaults). The argnumbers[]
1162 * array can be used to map this back to the catalog information.
1163 * argnumbers[k] is set to the proargtypes or proallargtypes index of the
1164 * k'th call argument.
1166 * We search a single namespace if the function name is qualified, else
1167 * all namespaces in the search path. In the multiple-namespace case,
1168 * we arrange for entries in earlier namespaces to mask identical entries in
1171 * When expanding variadics, we arrange for non-variadic functions to mask
1172 * variadic ones if the expanded argument list is the same. It is still
1173 * possible for there to be conflicts between different variadic functions,
1176 * It is guaranteed that the return list will never contain multiple entries
1177 * with identical argument lists. When expand_defaults is true, the entries
1178 * could have more than nargs positions, but we still guarantee that they are
1179 * distinct in the first nargs positions. However, if argnames isn't NIL or
1180 * either expand_variadic or expand_defaults is true, there might be multiple
1181 * candidate functions that expand to identical argument lists. Rather than
1182 * throw error here, we report such situations by returning a single entry
1183 * with oid = 0 that represents a set of such conflicting candidates.
1184 * The caller might end up discarding such an entry anyway, but if it selects
1185 * such an entry it should react as though the call were ambiguous.
1187 * If missing_ok is true, an empty list (NULL) is returned if the name was
1188 * schema-qualified with a schema that does not exist. Likewise if no
1189 * candidate is found for other reasons.
1192 FuncnameGetCandidates(List
*names
, int nargs
, List
*argnames
,
1193 bool expand_variadic
, bool expand_defaults
,
1194 bool include_out_arguments
, bool missing_ok
)
1196 FuncCandidateList resultList
= NULL
;
1197 bool any_special
= false;
1204 /* check for caller error */
1205 Assert(nargs
>= 0 || !(expand_variadic
| expand_defaults
));
1207 /* deconstruct the name list */
1208 DeconstructQualifiedName(names
, &schemaname
, &funcname
);
1212 /* use exact schema given */
1213 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
1214 if (!OidIsValid(namespaceId
))
1219 /* flag to indicate we need namespace search */
1220 namespaceId
= InvalidOid
;
1221 recomputeNamespacePath();
1224 /* Search syscache by name only */
1225 catlist
= SearchSysCacheList1(PROCNAMEARGSNSP
, CStringGetDatum(funcname
));
1227 for (i
= 0; i
< catlist
->n_members
; i
++)
1229 HeapTuple proctup
= &catlist
->members
[i
]->tuple
;
1230 Form_pg_proc procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
1231 Oid
*proargtypes
= procform
->proargtypes
.values
;
1232 int pronargs
= procform
->pronargs
;
1233 int effective_nargs
;
1238 int *argnumbers
= NULL
;
1239 FuncCandidateList newResult
;
1241 if (OidIsValid(namespaceId
))
1243 /* Consider only procs in specified namespace */
1244 if (procform
->pronamespace
!= namespaceId
)
1250 * Consider only procs that are in the search path and are not in
1251 * the temp namespace.
1255 foreach(nsp
, activeSearchPath
)
1257 if (procform
->pronamespace
== lfirst_oid(nsp
) &&
1258 procform
->pronamespace
!= myTempNamespace
)
1263 continue; /* proc is not in search path */
1267 * If we are asked to match to OUT arguments, then use the
1268 * proallargtypes array (which includes those); otherwise use
1269 * proargtypes (which doesn't). Of course, if proallargtypes is null,
1270 * we always use proargtypes.
1272 if (include_out_arguments
)
1274 Datum proallargtypes
;
1277 proallargtypes
= SysCacheGetAttr(PROCNAMEARGSNSP
, proctup
,
1278 Anum_pg_proc_proallargtypes
,
1282 ArrayType
*arr
= DatumGetArrayTypeP(proallargtypes
);
1284 pronargs
= ARR_DIMS(arr
)[0];
1285 if (ARR_NDIM(arr
) != 1 ||
1288 ARR_ELEMTYPE(arr
) != OIDOID
)
1289 elog(ERROR
, "proallargtypes is not a 1-D Oid array or it contains nulls");
1290 Assert(pronargs
>= procform
->pronargs
);
1291 proargtypes
= (Oid
*) ARR_DATA_PTR(arr
);
1295 if (argnames
!= NIL
)
1298 * Call uses named or mixed notation
1300 * Named or mixed notation can match a variadic function only if
1301 * expand_variadic is off; otherwise there is no way to match the
1302 * presumed-nameless parameters expanded from the variadic array.
1304 if (OidIsValid(procform
->provariadic
) && expand_variadic
)
1306 va_elem_type
= InvalidOid
;
1310 * Check argument count.
1312 Assert(nargs
>= 0); /* -1 not supported with argnames */
1314 if (pronargs
> nargs
&& expand_defaults
)
1316 /* Ignore if not enough default expressions */
1317 if (nargs
+ procform
->pronargdefaults
< pronargs
)
1319 use_defaults
= true;
1322 use_defaults
= false;
1324 /* Ignore if it doesn't match requested argument count */
1325 if (pronargs
!= nargs
&& !use_defaults
)
1328 /* Check for argument name match, generate positional mapping */
1329 if (!MatchNamedCall(proctup
, nargs
, argnames
,
1330 include_out_arguments
, pronargs
,
1334 /* Named argument matching is always "special" */
1340 * Call uses positional notation
1342 * Check if function is variadic, and get variadic element type if
1343 * so. If expand_variadic is false, we should just ignore
1346 if (pronargs
<= nargs
&& expand_variadic
)
1348 va_elem_type
= procform
->provariadic
;
1349 variadic
= OidIsValid(va_elem_type
);
1350 any_special
|= variadic
;
1354 va_elem_type
= InvalidOid
;
1359 * Check if function can match by using parameter defaults.
1361 if (pronargs
> nargs
&& expand_defaults
)
1363 /* Ignore if not enough default expressions */
1364 if (nargs
+ procform
->pronargdefaults
< pronargs
)
1366 use_defaults
= true;
1370 use_defaults
= false;
1372 /* Ignore if it doesn't match requested argument count */
1373 if (nargs
>= 0 && pronargs
!= nargs
&& !variadic
&& !use_defaults
)
1378 * We must compute the effective argument list so that we can easily
1379 * compare it to earlier results. We waste a palloc cycle if it gets
1380 * masked by an earlier result, but really that's a pretty infrequent
1381 * case so it's not worth worrying about.
1383 effective_nargs
= Max(pronargs
, nargs
);
1384 newResult
= (FuncCandidateList
)
1385 palloc(offsetof(struct _FuncCandidateList
, args
) +
1386 effective_nargs
* sizeof(Oid
));
1387 newResult
->pathpos
= pathpos
;
1388 newResult
->oid
= procform
->oid
;
1389 newResult
->nominalnargs
= pronargs
;
1390 newResult
->nargs
= effective_nargs
;
1391 newResult
->argnumbers
= argnumbers
;
1394 /* Re-order the argument types into call's logical order */
1395 for (int j
= 0; j
< pronargs
; j
++)
1396 newResult
->args
[j
] = proargtypes
[argnumbers
[j
]];
1400 /* Simple positional case, just copy proargtypes as-is */
1401 memcpy(newResult
->args
, proargtypes
, pronargs
* sizeof(Oid
));
1405 newResult
->nvargs
= effective_nargs
- pronargs
+ 1;
1406 /* Expand variadic argument into N copies of element type */
1407 for (int j
= pronargs
- 1; j
< effective_nargs
; j
++)
1408 newResult
->args
[j
] = va_elem_type
;
1411 newResult
->nvargs
= 0;
1412 newResult
->ndargs
= use_defaults
? pronargs
- nargs
: 0;
1415 * Does it have the same arguments as something we already accepted?
1416 * If so, decide what to do to avoid returning duplicate argument
1417 * lists. We can skip this check for the single-namespace case if no
1418 * special (named, variadic or defaults) match has been made, since
1419 * then the unique index on pg_proc guarantees all the matches have
1420 * different argument lists.
1422 if (resultList
!= NULL
&&
1423 (any_special
|| !OidIsValid(namespaceId
)))
1426 * If we have an ordered list from SearchSysCacheList (the normal
1427 * case), then any conflicting proc must immediately adjoin this
1428 * one in the list, so we only need to look at the newest result
1429 * item. If we have an unordered list, we have to scan the whole
1430 * result list. Also, if either the current candidate or any
1431 * previous candidate is a special match, we can't assume that
1432 * conflicts are adjacent.
1434 * We ignore defaulted arguments in deciding what is a match.
1436 FuncCandidateList prevResult
;
1438 if (catlist
->ordered
&& !any_special
)
1440 /* ndargs must be 0 if !any_special */
1441 if (effective_nargs
== resultList
->nargs
&&
1442 memcmp(newResult
->args
,
1444 effective_nargs
* sizeof(Oid
)) == 0)
1445 prevResult
= resultList
;
1451 int cmp_nargs
= newResult
->nargs
- newResult
->ndargs
;
1453 for (prevResult
= resultList
;
1455 prevResult
= prevResult
->next
)
1457 if (cmp_nargs
== prevResult
->nargs
- prevResult
->ndargs
&&
1458 memcmp(newResult
->args
,
1460 cmp_nargs
* sizeof(Oid
)) == 0)
1468 * We have a match with a previous result. Decide which one
1469 * to keep, or mark it ambiguous if we can't decide. The
1470 * logic here is preference > 0 means prefer the old result,
1471 * preference < 0 means prefer the new, preference = 0 means
1476 if (pathpos
!= prevResult
->pathpos
)
1479 * Prefer the one that's earlier in the search path.
1481 preference
= pathpos
- prevResult
->pathpos
;
1483 else if (variadic
&& prevResult
->nvargs
== 0)
1486 * With variadic functions we could have, for example,
1487 * both foo(numeric) and foo(variadic numeric[]) in the
1488 * same namespace; if so we prefer the non-variadic match
1489 * on efficiency grounds.
1493 else if (!variadic
&& prevResult
->nvargs
> 0)
1500 * We can't decide. This can happen with, for example,
1501 * both foo(numeric, variadic numeric[]) and
1502 * foo(variadic numeric[]) in the same namespace, or
1503 * both foo(int) and foo (int, int default something)
1504 * in the same namespace, or both foo(a int, b text)
1505 * and foo(b text, a int) in the same namespace.
1513 /* keep previous result */
1517 else if (preference
< 0)
1519 /* remove previous result from the list */
1520 if (prevResult
== resultList
)
1521 resultList
= prevResult
->next
;
1524 FuncCandidateList prevPrevResult
;
1526 for (prevPrevResult
= resultList
;
1528 prevPrevResult
= prevPrevResult
->next
)
1530 if (prevResult
== prevPrevResult
->next
)
1532 prevPrevResult
->next
= prevResult
->next
;
1536 Assert(prevPrevResult
); /* assert we found it */
1539 /* fall through to add newResult to list */
1543 /* mark old result as ambiguous, discard new */
1544 prevResult
->oid
= InvalidOid
;
1552 * Okay to add it to result list
1554 newResult
->next
= resultList
;
1555 resultList
= newResult
;
1558 ReleaseSysCacheList(catlist
);
1565 * Given a pg_proc heap tuple and a call's list of argument names,
1566 * check whether the function could match the call.
1568 * The call could match if all supplied argument names are accepted by
1569 * the function, in positions after the last positional argument, and there
1570 * are defaults for all unsupplied arguments.
1572 * If include_out_arguments is true, we are treating OUT arguments as
1573 * included in the argument list. pronargs is the number of arguments
1574 * we're considering (the length of either proargtypes or proallargtypes).
1576 * The number of positional arguments is nargs - list_length(argnames).
1577 * Note caller has already done basic checks on argument count.
1579 * On match, return true and fill *argnumbers with a palloc'd array showing
1580 * the mapping from call argument positions to actual function argument
1581 * numbers. Defaulted arguments are included in this map, at positions
1582 * after the last supplied argument.
1585 MatchNamedCall(HeapTuple proctup
, int nargs
, List
*argnames
,
1586 bool include_out_arguments
, int pronargs
,
1589 Form_pg_proc procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
1590 int numposargs
= nargs
- list_length(argnames
);
1595 bool arggiven
[FUNC_MAX_ARGS
];
1597 int ap
; /* call args position */
1598 int pp
; /* proargs position */
1601 Assert(argnames
!= NIL
);
1602 Assert(numposargs
>= 0);
1603 Assert(nargs
<= pronargs
);
1605 /* Ignore this function if its proargnames is null */
1606 (void) SysCacheGetAttr(PROCOID
, proctup
, Anum_pg_proc_proargnames
,
1611 /* OK, let's extract the argument names and types */
1612 pronallargs
= get_func_arg_info(proctup
,
1613 &p_argtypes
, &p_argnames
, &p_argmodes
);
1614 Assert(p_argnames
!= NULL
);
1616 Assert(include_out_arguments
? (pronargs
== pronallargs
) : (pronargs
<= pronallargs
));
1618 /* initialize state for matching */
1619 *argnumbers
= (int *) palloc(pronargs
* sizeof(int));
1620 memset(arggiven
, false, pronargs
* sizeof(bool));
1622 /* there are numposargs positional args before the named args */
1623 for (ap
= 0; ap
< numposargs
; ap
++)
1625 (*argnumbers
)[ap
] = ap
;
1626 arggiven
[ap
] = true;
1629 /* now examine the named args */
1630 foreach(lc
, argnames
)
1632 char *argname
= (char *) lfirst(lc
);
1638 for (i
= 0; i
< pronallargs
; i
++)
1640 /* consider only input params, except with include_out_arguments */
1641 if (!include_out_arguments
&&
1643 (p_argmodes
[i
] != FUNC_PARAM_IN
&&
1644 p_argmodes
[i
] != FUNC_PARAM_INOUT
&&
1645 p_argmodes
[i
] != FUNC_PARAM_VARIADIC
))
1647 if (p_argnames
[i
] && strcmp(p_argnames
[i
], argname
) == 0)
1649 /* fail if argname matches a positional argument */
1652 arggiven
[pp
] = true;
1653 (*argnumbers
)[ap
] = pp
;
1657 /* increase pp only for considered parameters */
1660 /* if name isn't in proargnames, fail */
1666 Assert(ap
== nargs
); /* processed all actual parameters */
1668 /* Check for default arguments */
1669 if (nargs
< pronargs
)
1671 int first_arg_with_default
= pronargs
- procform
->pronargdefaults
;
1673 for (pp
= numposargs
; pp
< pronargs
; pp
++)
1677 /* fail if arg not given and no default available */
1678 if (pp
< first_arg_with_default
)
1680 (*argnumbers
)[ap
++] = pp
;
1684 Assert(ap
== pronargs
); /* processed all function parameters */
1691 * Determine whether a function (identified by OID) is visible in the
1692 * current search path. Visible means "would be found by searching
1693 * for the unqualified function name with exact argument matches".
1696 FunctionIsVisible(Oid funcid
)
1698 return FunctionIsVisibleExt(funcid
, NULL
);
1702 * FunctionIsVisibleExt
1703 * As above, but if the function isn't found and is_missing is not NULL,
1704 * then set *is_missing = true and return false instead of throwing
1705 * an error. (Caller must initialize *is_missing = false.)
1708 FunctionIsVisibleExt(Oid funcid
, bool *is_missing
)
1711 Form_pg_proc procform
;
1715 proctup
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1716 if (!HeapTupleIsValid(proctup
))
1718 if (is_missing
!= NULL
)
1723 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1725 procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
1727 recomputeNamespacePath();
1730 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1731 * the system namespace are surely in the path and so we needn't even do
1732 * list_member_oid() for them.
1734 pronamespace
= procform
->pronamespace
;
1735 if (pronamespace
!= PG_CATALOG_NAMESPACE
&&
1736 !list_member_oid(activeSearchPath
, pronamespace
))
1741 * If it is in the path, it might still not be visible; it could be
1742 * hidden by another proc of the same name and arguments earlier in
1743 * the path. So we must do a slow check to see if this is the same
1744 * proc that would be found by FuncnameGetCandidates.
1746 char *proname
= NameStr(procform
->proname
);
1747 int nargs
= procform
->pronargs
;
1748 FuncCandidateList clist
;
1752 clist
= FuncnameGetCandidates(list_make1(makeString(proname
)),
1753 nargs
, NIL
, false, false, false, false);
1755 for (; clist
; clist
= clist
->next
)
1757 if (memcmp(clist
->args
, procform
->proargtypes
.values
,
1758 nargs
* sizeof(Oid
)) == 0)
1760 /* Found the expected entry; is it the right proc? */
1761 visible
= (clist
->oid
== funcid
);
1767 ReleaseSysCache(proctup
);
1775 * Given a possibly-qualified operator name and exact input datatypes,
1776 * look up the operator. Returns InvalidOid if not found.
1778 * Pass oprleft = InvalidOid for a prefix op.
1780 * If the operator name is not schema-qualified, it is sought in the current
1781 * namespace search path. If the name is schema-qualified and the given
1782 * schema does not exist, InvalidOid is returned.
1785 OpernameGetOprid(List
*names
, Oid oprleft
, Oid oprright
)
1792 /* deconstruct the name list */
1793 DeconstructQualifiedName(names
, &schemaname
, &opername
);
1797 /* search only in exact schema given */
1800 namespaceId
= LookupExplicitNamespace(schemaname
, true);
1801 if (OidIsValid(namespaceId
))
1805 opertup
= SearchSysCache4(OPERNAMENSP
,
1806 CStringGetDatum(opername
),
1807 ObjectIdGetDatum(oprleft
),
1808 ObjectIdGetDatum(oprright
),
1809 ObjectIdGetDatum(namespaceId
));
1810 if (HeapTupleIsValid(opertup
))
1812 Form_pg_operator operclass
= (Form_pg_operator
) GETSTRUCT(opertup
);
1813 Oid result
= operclass
->oid
;
1815 ReleaseSysCache(opertup
);
1823 /* Search syscache by name and argument types */
1824 catlist
= SearchSysCacheList3(OPERNAMENSP
,
1825 CStringGetDatum(opername
),
1826 ObjectIdGetDatum(oprleft
),
1827 ObjectIdGetDatum(oprright
));
1829 if (catlist
->n_members
== 0)
1831 /* no hope, fall out early */
1832 ReleaseSysCacheList(catlist
);
1837 * We have to find the list member that is first in the search path, if
1838 * there's more than one. This doubly-nested loop looks ugly, but in
1839 * practice there should usually be few catlist members.
1841 recomputeNamespacePath();
1843 foreach(l
, activeSearchPath
)
1845 Oid namespaceId
= lfirst_oid(l
);
1848 if (namespaceId
== myTempNamespace
)
1849 continue; /* do not look in temp namespace */
1851 for (i
= 0; i
< catlist
->n_members
; i
++)
1853 HeapTuple opertup
= &catlist
->members
[i
]->tuple
;
1854 Form_pg_operator operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
1856 if (operform
->oprnamespace
== namespaceId
)
1858 Oid result
= operform
->oid
;
1860 ReleaseSysCacheList(catlist
);
1866 ReleaseSysCacheList(catlist
);
1871 * OpernameGetCandidates
1872 * Given a possibly-qualified operator name and operator kind,
1873 * retrieve a list of the possible matches.
1875 * If oprkind is '\0', we return all operators matching the given name,
1876 * regardless of arguments.
1878 * We search a single namespace if the operator name is qualified, else
1879 * all namespaces in the search path. The return list will never contain
1880 * multiple entries with identical argument lists --- in the multiple-
1881 * namespace case, we arrange for entries in earlier namespaces to mask
1882 * identical entries in later namespaces.
1884 * The returned items always have two args[] entries --- the first will be
1885 * InvalidOid for a prefix oprkind. nargs is always 2, too.
1888 OpernameGetCandidates(List
*names
, char oprkind
, bool missing_schema_ok
)
1890 FuncCandidateList resultList
= NULL
;
1891 char *resultSpace
= NULL
;
1899 /* deconstruct the name list */
1900 DeconstructQualifiedName(names
, &schemaname
, &opername
);
1904 /* use exact schema given */
1905 namespaceId
= LookupExplicitNamespace(schemaname
, missing_schema_ok
);
1906 if (missing_schema_ok
&& !OidIsValid(namespaceId
))
1911 /* flag to indicate we need namespace search */
1912 namespaceId
= InvalidOid
;
1913 recomputeNamespacePath();
1916 /* Search syscache by name only */
1917 catlist
= SearchSysCacheList1(OPERNAMENSP
, CStringGetDatum(opername
));
1920 * In typical scenarios, most if not all of the operators found by the
1921 * catcache search will end up getting returned; and there can be quite a
1922 * few, for common operator names such as '=' or '+'. To reduce the time
1923 * spent in palloc, we allocate the result space as an array large enough
1924 * to hold all the operators. The original coding of this routine did a
1925 * separate palloc for each operator, but profiling revealed that the
1926 * pallocs used an unreasonably large fraction of parsing time.
1928 #define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
1931 if (catlist
->n_members
> 0)
1932 resultSpace
= palloc(catlist
->n_members
* SPACE_PER_OP
);
1934 for (i
= 0; i
< catlist
->n_members
; i
++)
1936 HeapTuple opertup
= &catlist
->members
[i
]->tuple
;
1937 Form_pg_operator operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
1939 FuncCandidateList newResult
;
1941 /* Ignore operators of wrong kind, if specific kind requested */
1942 if (oprkind
&& operform
->oprkind
!= oprkind
)
1945 if (OidIsValid(namespaceId
))
1947 /* Consider only opers in specified namespace */
1948 if (operform
->oprnamespace
!= namespaceId
)
1950 /* No need to check args, they must all be different */
1955 * Consider only opers that are in the search path and are not in
1956 * the temp namespace.
1960 foreach(nsp
, activeSearchPath
)
1962 if (operform
->oprnamespace
== lfirst_oid(nsp
) &&
1963 operform
->oprnamespace
!= myTempNamespace
)
1968 continue; /* oper is not in search path */
1971 * Okay, it's in the search path, but does it have the same
1972 * arguments as something we already accepted? If so, keep only
1973 * the one that appears earlier in the search path.
1975 * If we have an ordered list from SearchSysCacheList (the normal
1976 * case), then any conflicting oper must immediately adjoin this
1977 * one in the list, so we only need to look at the newest result
1978 * item. If we have an unordered list, we have to scan the whole
1983 FuncCandidateList prevResult
;
1985 if (catlist
->ordered
)
1987 if (operform
->oprleft
== resultList
->args
[0] &&
1988 operform
->oprright
== resultList
->args
[1])
1989 prevResult
= resultList
;
1995 for (prevResult
= resultList
;
1997 prevResult
= prevResult
->next
)
1999 if (operform
->oprleft
== prevResult
->args
[0] &&
2000 operform
->oprright
== prevResult
->args
[1])
2006 /* We have a match with a previous result */
2007 Assert(pathpos
!= prevResult
->pathpos
);
2008 if (pathpos
> prevResult
->pathpos
)
2009 continue; /* keep previous result */
2010 /* replace previous result */
2011 prevResult
->pathpos
= pathpos
;
2012 prevResult
->oid
= operform
->oid
;
2013 continue; /* args are same, of course */
2019 * Okay to add it to result list
2021 newResult
= (FuncCandidateList
) (resultSpace
+ nextResult
);
2022 nextResult
+= SPACE_PER_OP
;
2024 newResult
->pathpos
= pathpos
;
2025 newResult
->oid
= operform
->oid
;
2026 newResult
->nominalnargs
= 2;
2027 newResult
->nargs
= 2;
2028 newResult
->nvargs
= 0;
2029 newResult
->ndargs
= 0;
2030 newResult
->argnumbers
= NULL
;
2031 newResult
->args
[0] = operform
->oprleft
;
2032 newResult
->args
[1] = operform
->oprright
;
2033 newResult
->next
= resultList
;
2034 resultList
= newResult
;
2037 ReleaseSysCacheList(catlist
);
2044 * Determine whether an operator (identified by OID) is visible in the
2045 * current search path. Visible means "would be found by searching
2046 * for the unqualified operator name with exact argument matches".
2049 OperatorIsVisible(Oid oprid
)
2051 return OperatorIsVisibleExt(oprid
, NULL
);
2055 * OperatorIsVisibleExt
2056 * As above, but if the operator isn't found and is_missing is not NULL,
2057 * then set *is_missing = true and return false instead of throwing
2058 * an error. (Caller must initialize *is_missing = false.)
2061 OperatorIsVisibleExt(Oid oprid
, bool *is_missing
)
2064 Form_pg_operator oprform
;
2068 oprtup
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(oprid
));
2069 if (!HeapTupleIsValid(oprtup
))
2071 if (is_missing
!= NULL
)
2076 elog(ERROR
, "cache lookup failed for operator %u", oprid
);
2078 oprform
= (Form_pg_operator
) GETSTRUCT(oprtup
);
2080 recomputeNamespacePath();
2083 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2084 * the system namespace are surely in the path and so we needn't even do
2085 * list_member_oid() for them.
2087 oprnamespace
= oprform
->oprnamespace
;
2088 if (oprnamespace
!= PG_CATALOG_NAMESPACE
&&
2089 !list_member_oid(activeSearchPath
, oprnamespace
))
2094 * If it is in the path, it might still not be visible; it could be
2095 * hidden by another operator of the same name and arguments earlier
2096 * in the path. So we must do a slow check to see if this is the same
2097 * operator that would be found by OpernameGetOprid.
2099 char *oprname
= NameStr(oprform
->oprname
);
2101 visible
= (OpernameGetOprid(list_make1(makeString(oprname
)),
2102 oprform
->oprleft
, oprform
->oprright
)
2106 ReleaseSysCache(oprtup
);
2113 * OpclassnameGetOpcid
2114 * Try to resolve an unqualified index opclass name.
2115 * Returns OID if opclass found in search path, else InvalidOid.
2117 * This is essentially the same as TypenameGetTypid, but we have to have
2118 * an extra argument for the index AM OID.
2121 OpclassnameGetOpcid(Oid amid
, const char *opcname
)
2126 recomputeNamespacePath();
2128 foreach(l
, activeSearchPath
)
2130 Oid namespaceId
= lfirst_oid(l
);
2132 if (namespaceId
== myTempNamespace
)
2133 continue; /* do not look in temp namespace */
2135 opcid
= GetSysCacheOid3(CLAAMNAMENSP
, Anum_pg_opclass_oid
,
2136 ObjectIdGetDatum(amid
),
2137 PointerGetDatum(opcname
),
2138 ObjectIdGetDatum(namespaceId
));
2139 if (OidIsValid(opcid
))
2143 /* Not found in path */
2149 * Determine whether an opclass (identified by OID) is visible in the
2150 * current search path. Visible means "would be found by searching
2151 * for the unqualified opclass name".
2154 OpclassIsVisible(Oid opcid
)
2156 return OpclassIsVisibleExt(opcid
, NULL
);
2160 * OpclassIsVisibleExt
2161 * As above, but if the opclass isn't found and is_missing is not NULL,
2162 * then set *is_missing = true and return false instead of throwing
2163 * an error. (Caller must initialize *is_missing = false.)
2166 OpclassIsVisibleExt(Oid opcid
, bool *is_missing
)
2169 Form_pg_opclass opcform
;
2173 opctup
= SearchSysCache1(CLAOID
, ObjectIdGetDatum(opcid
));
2174 if (!HeapTupleIsValid(opctup
))
2176 if (is_missing
!= NULL
)
2181 elog(ERROR
, "cache lookup failed for opclass %u", opcid
);
2183 opcform
= (Form_pg_opclass
) GETSTRUCT(opctup
);
2185 recomputeNamespacePath();
2188 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2189 * the system namespace are surely in the path and so we needn't even do
2190 * list_member_oid() for them.
2192 opcnamespace
= opcform
->opcnamespace
;
2193 if (opcnamespace
!= PG_CATALOG_NAMESPACE
&&
2194 !list_member_oid(activeSearchPath
, opcnamespace
))
2199 * If it is in the path, it might still not be visible; it could be
2200 * hidden by another opclass of the same name earlier in the path. So
2201 * we must do a slow check to see if this opclass would be found by
2202 * OpclassnameGetOpcid.
2204 char *opcname
= NameStr(opcform
->opcname
);
2206 visible
= (OpclassnameGetOpcid(opcform
->opcmethod
, opcname
) == opcid
);
2209 ReleaseSysCache(opctup
);
2215 * OpfamilynameGetOpfid
2216 * Try to resolve an unqualified index opfamily name.
2217 * Returns OID if opfamily found in search path, else InvalidOid.
2219 * This is essentially the same as TypenameGetTypid, but we have to have
2220 * an extra argument for the index AM OID.
2223 OpfamilynameGetOpfid(Oid amid
, const char *opfname
)
2228 recomputeNamespacePath();
2230 foreach(l
, activeSearchPath
)
2232 Oid namespaceId
= lfirst_oid(l
);
2234 if (namespaceId
== myTempNamespace
)
2235 continue; /* do not look in temp namespace */
2237 opfid
= GetSysCacheOid3(OPFAMILYAMNAMENSP
, Anum_pg_opfamily_oid
,
2238 ObjectIdGetDatum(amid
),
2239 PointerGetDatum(opfname
),
2240 ObjectIdGetDatum(namespaceId
));
2241 if (OidIsValid(opfid
))
2245 /* Not found in path */
2251 * Determine whether an opfamily (identified by OID) is visible in the
2252 * current search path. Visible means "would be found by searching
2253 * for the unqualified opfamily name".
2256 OpfamilyIsVisible(Oid opfid
)
2258 return OpfamilyIsVisibleExt(opfid
, NULL
);
2262 * OpfamilyIsVisibleExt
2263 * As above, but if the opfamily isn't found and is_missing is not NULL,
2264 * then set *is_missing = true and return false instead of throwing
2265 * an error. (Caller must initialize *is_missing = false.)
2268 OpfamilyIsVisibleExt(Oid opfid
, bool *is_missing
)
2271 Form_pg_opfamily opfform
;
2275 opftup
= SearchSysCache1(OPFAMILYOID
, ObjectIdGetDatum(opfid
));
2276 if (!HeapTupleIsValid(opftup
))
2278 if (is_missing
!= NULL
)
2283 elog(ERROR
, "cache lookup failed for opfamily %u", opfid
);
2285 opfform
= (Form_pg_opfamily
) GETSTRUCT(opftup
);
2287 recomputeNamespacePath();
2290 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2291 * the system namespace are surely in the path and so we needn't even do
2292 * list_member_oid() for them.
2294 opfnamespace
= opfform
->opfnamespace
;
2295 if (opfnamespace
!= PG_CATALOG_NAMESPACE
&&
2296 !list_member_oid(activeSearchPath
, opfnamespace
))
2301 * If it is in the path, it might still not be visible; it could be
2302 * hidden by another opfamily of the same name earlier in the path. So
2303 * we must do a slow check to see if this opfamily would be found by
2304 * OpfamilynameGetOpfid.
2306 char *opfname
= NameStr(opfform
->opfname
);
2308 visible
= (OpfamilynameGetOpfid(opfform
->opfmethod
, opfname
) == opfid
);
2311 ReleaseSysCache(opftup
);
2318 * If there's a collation of the given name/namespace, and it works
2319 * with the given encoding, return its OID. Else return InvalidOid.
2322 lookup_collation(const char *collname
, Oid collnamespace
, int32 encoding
)
2326 Form_pg_collation collform
;
2328 /* Check for encoding-specific entry (exact match) */
2329 collid
= GetSysCacheOid3(COLLNAMEENCNSP
, Anum_pg_collation_oid
,
2330 PointerGetDatum(collname
),
2331 Int32GetDatum(encoding
),
2332 ObjectIdGetDatum(collnamespace
));
2333 if (OidIsValid(collid
))
2337 * Check for any-encoding entry. This takes a bit more work: while libc
2338 * collations with collencoding = -1 do work with all encodings, ICU
2339 * collations only work with certain encodings, so we have to check that
2340 * aspect before deciding it's a match.
2342 colltup
= SearchSysCache3(COLLNAMEENCNSP
,
2343 PointerGetDatum(collname
),
2345 ObjectIdGetDatum(collnamespace
));
2346 if (!HeapTupleIsValid(colltup
))
2348 collform
= (Form_pg_collation
) GETSTRUCT(colltup
);
2349 if (collform
->collprovider
== COLLPROVIDER_ICU
)
2351 if (is_encoding_supported_by_icu(encoding
))
2352 collid
= collform
->oid
;
2354 collid
= InvalidOid
;
2358 collid
= collform
->oid
;
2360 ReleaseSysCache(colltup
);
2365 * CollationGetCollid
2366 * Try to resolve an unqualified collation name.
2367 * Returns OID if collation found in search path, else InvalidOid.
2369 * Note that this will only find collations that work with the current
2370 * database's encoding.
2373 CollationGetCollid(const char *collname
)
2375 int32 dbencoding
= GetDatabaseEncoding();
2378 recomputeNamespacePath();
2380 foreach(l
, activeSearchPath
)
2382 Oid namespaceId
= lfirst_oid(l
);
2385 if (namespaceId
== myTempNamespace
)
2386 continue; /* do not look in temp namespace */
2388 collid
= lookup_collation(collname
, namespaceId
, dbencoding
);
2389 if (OidIsValid(collid
))
2393 /* Not found in path */
2398 * CollationIsVisible
2399 * Determine whether a collation (identified by OID) is visible in the
2400 * current search path. Visible means "would be found by searching
2401 * for the unqualified collation name".
2403 * Note that only collations that work with the current database's encoding
2404 * will be considered visible.
2407 CollationIsVisible(Oid collid
)
2409 return CollationIsVisibleExt(collid
, NULL
);
2413 * CollationIsVisibleExt
2414 * As above, but if the collation isn't found and is_missing is not NULL,
2415 * then set *is_missing = true and return false instead of throwing
2416 * an error. (Caller must initialize *is_missing = false.)
2419 CollationIsVisibleExt(Oid collid
, bool *is_missing
)
2422 Form_pg_collation collform
;
2426 colltup
= SearchSysCache1(COLLOID
, ObjectIdGetDatum(collid
));
2427 if (!HeapTupleIsValid(colltup
))
2429 if (is_missing
!= NULL
)
2434 elog(ERROR
, "cache lookup failed for collation %u", collid
);
2436 collform
= (Form_pg_collation
) GETSTRUCT(colltup
);
2438 recomputeNamespacePath();
2441 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2442 * the system namespace are surely in the path and so we needn't even do
2443 * list_member_oid() for them.
2445 collnamespace
= collform
->collnamespace
;
2446 if (collnamespace
!= PG_CATALOG_NAMESPACE
&&
2447 !list_member_oid(activeSearchPath
, collnamespace
))
2452 * If it is in the path, it might still not be visible; it could be
2453 * hidden by another collation of the same name earlier in the path,
2454 * or it might not work with the current DB encoding. So we must do a
2455 * slow check to see if this collation would be found by
2456 * CollationGetCollid.
2458 char *collname
= NameStr(collform
->collname
);
2460 visible
= (CollationGetCollid(collname
) == collid
);
2463 ReleaseSysCache(colltup
);
2470 * ConversionGetConid
2471 * Try to resolve an unqualified conversion name.
2472 * Returns OID if conversion found in search path, else InvalidOid.
2474 * This is essentially the same as RelnameGetRelid.
2477 ConversionGetConid(const char *conname
)
2482 recomputeNamespacePath();
2484 foreach(l
, activeSearchPath
)
2486 Oid namespaceId
= lfirst_oid(l
);
2488 if (namespaceId
== myTempNamespace
)
2489 continue; /* do not look in temp namespace */
2491 conid
= GetSysCacheOid2(CONNAMENSP
, Anum_pg_conversion_oid
,
2492 PointerGetDatum(conname
),
2493 ObjectIdGetDatum(namespaceId
));
2494 if (OidIsValid(conid
))
2498 /* Not found in path */
2503 * ConversionIsVisible
2504 * Determine whether a conversion (identified by OID) is visible in the
2505 * current search path. Visible means "would be found by searching
2506 * for the unqualified conversion name".
2509 ConversionIsVisible(Oid conid
)
2511 return ConversionIsVisibleExt(conid
, NULL
);
2515 * ConversionIsVisibleExt
2516 * As above, but if the conversion isn't found and is_missing is not NULL,
2517 * then set *is_missing = true and return false instead of throwing
2518 * an error. (Caller must initialize *is_missing = false.)
2521 ConversionIsVisibleExt(Oid conid
, bool *is_missing
)
2524 Form_pg_conversion conform
;
2528 contup
= SearchSysCache1(CONVOID
, ObjectIdGetDatum(conid
));
2529 if (!HeapTupleIsValid(contup
))
2531 if (is_missing
!= NULL
)
2536 elog(ERROR
, "cache lookup failed for conversion %u", conid
);
2538 conform
= (Form_pg_conversion
) GETSTRUCT(contup
);
2540 recomputeNamespacePath();
2543 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2544 * the system namespace are surely in the path and so we needn't even do
2545 * list_member_oid() for them.
2547 connamespace
= conform
->connamespace
;
2548 if (connamespace
!= PG_CATALOG_NAMESPACE
&&
2549 !list_member_oid(activeSearchPath
, connamespace
))
2554 * If it is in the path, it might still not be visible; it could be
2555 * hidden by another conversion of the same name earlier in the path.
2556 * So we must do a slow check to see if this conversion would be found
2557 * by ConversionGetConid.
2559 char *conname
= NameStr(conform
->conname
);
2561 visible
= (ConversionGetConid(conname
) == conid
);
2564 ReleaseSysCache(contup
);
2570 * get_statistics_object_oid - find a statistics object by possibly qualified name
2572 * If not found, returns InvalidOid if missing_ok, else throws error
2575 get_statistics_object_oid(List
*names
, bool missing_ok
)
2580 Oid stats_oid
= InvalidOid
;
2583 /* deconstruct the name list */
2584 DeconstructQualifiedName(names
, &schemaname
, &stats_name
);
2588 /* use exact schema given */
2589 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
2590 if (missing_ok
&& !OidIsValid(namespaceId
))
2591 stats_oid
= InvalidOid
;
2593 stats_oid
= GetSysCacheOid2(STATEXTNAMENSP
, Anum_pg_statistic_ext_oid
,
2594 PointerGetDatum(stats_name
),
2595 ObjectIdGetDatum(namespaceId
));
2599 /* search for it in search path */
2600 recomputeNamespacePath();
2602 foreach(l
, activeSearchPath
)
2604 namespaceId
= lfirst_oid(l
);
2606 if (namespaceId
== myTempNamespace
)
2607 continue; /* do not look in temp namespace */
2608 stats_oid
= GetSysCacheOid2(STATEXTNAMENSP
, Anum_pg_statistic_ext_oid
,
2609 PointerGetDatum(stats_name
),
2610 ObjectIdGetDatum(namespaceId
));
2611 if (OidIsValid(stats_oid
))
2616 if (!OidIsValid(stats_oid
) && !missing_ok
)
2618 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2619 errmsg("statistics object \"%s\" does not exist",
2620 NameListToString(names
))));
2626 * StatisticsObjIsVisible
2627 * Determine whether a statistics object (identified by OID) is visible in
2628 * the current search path. Visible means "would be found by searching
2629 * for the unqualified statistics object name".
2632 StatisticsObjIsVisible(Oid stxid
)
2634 return StatisticsObjIsVisibleExt(stxid
, NULL
);
2638 * StatisticsObjIsVisibleExt
2639 * As above, but if the statistics object isn't found and is_missing is
2640 * not NULL, then set *is_missing = true and return false instead of
2641 * throwing an error. (Caller must initialize *is_missing = false.)
2644 StatisticsObjIsVisibleExt(Oid stxid
, bool *is_missing
)
2647 Form_pg_statistic_ext stxform
;
2651 stxtup
= SearchSysCache1(STATEXTOID
, ObjectIdGetDatum(stxid
));
2652 if (!HeapTupleIsValid(stxtup
))
2654 if (is_missing
!= NULL
)
2659 elog(ERROR
, "cache lookup failed for statistics object %u", stxid
);
2661 stxform
= (Form_pg_statistic_ext
) GETSTRUCT(stxtup
);
2663 recomputeNamespacePath();
2666 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2667 * the system namespace are surely in the path and so we needn't even do
2668 * list_member_oid() for them.
2670 stxnamespace
= stxform
->stxnamespace
;
2671 if (stxnamespace
!= PG_CATALOG_NAMESPACE
&&
2672 !list_member_oid(activeSearchPath
, stxnamespace
))
2677 * If it is in the path, it might still not be visible; it could be
2678 * hidden by another statistics object of the same name earlier in the
2679 * path. So we must do a slow check for conflicting objects.
2681 char *stxname
= NameStr(stxform
->stxname
);
2685 foreach(l
, activeSearchPath
)
2687 Oid namespaceId
= lfirst_oid(l
);
2689 if (namespaceId
== stxnamespace
)
2691 /* Found it first in path */
2695 if (SearchSysCacheExists2(STATEXTNAMENSP
,
2696 PointerGetDatum(stxname
),
2697 ObjectIdGetDatum(namespaceId
)))
2699 /* Found something else first in path */
2705 ReleaseSysCache(stxtup
);
2711 * get_ts_parser_oid - find a TS parser by possibly qualified name
2713 * If not found, returns InvalidOid if missing_ok, else throws error
2716 get_ts_parser_oid(List
*names
, bool missing_ok
)
2721 Oid prsoid
= InvalidOid
;
2724 /* deconstruct the name list */
2725 DeconstructQualifiedName(names
, &schemaname
, &parser_name
);
2729 /* use exact schema given */
2730 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
2731 if (missing_ok
&& !OidIsValid(namespaceId
))
2732 prsoid
= InvalidOid
;
2734 prsoid
= GetSysCacheOid2(TSPARSERNAMENSP
, Anum_pg_ts_parser_oid
,
2735 PointerGetDatum(parser_name
),
2736 ObjectIdGetDatum(namespaceId
));
2740 /* search for it in search path */
2741 recomputeNamespacePath();
2743 foreach(l
, activeSearchPath
)
2745 namespaceId
= lfirst_oid(l
);
2747 if (namespaceId
== myTempNamespace
)
2748 continue; /* do not look in temp namespace */
2750 prsoid
= GetSysCacheOid2(TSPARSERNAMENSP
, Anum_pg_ts_parser_oid
,
2751 PointerGetDatum(parser_name
),
2752 ObjectIdGetDatum(namespaceId
));
2753 if (OidIsValid(prsoid
))
2758 if (!OidIsValid(prsoid
) && !missing_ok
)
2760 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2761 errmsg("text search parser \"%s\" does not exist",
2762 NameListToString(names
))));
2769 * Determine whether a parser (identified by OID) is visible in the
2770 * current search path. Visible means "would be found by searching
2771 * for the unqualified parser name".
2774 TSParserIsVisible(Oid prsId
)
2776 return TSParserIsVisibleExt(prsId
, NULL
);
2780 * TSParserIsVisibleExt
2781 * As above, but if the parser isn't found and is_missing is not NULL,
2782 * then set *is_missing = true and return false instead of throwing
2783 * an error. (Caller must initialize *is_missing = false.)
2786 TSParserIsVisibleExt(Oid prsId
, bool *is_missing
)
2789 Form_pg_ts_parser form
;
2793 tup
= SearchSysCache1(TSPARSEROID
, ObjectIdGetDatum(prsId
));
2794 if (!HeapTupleIsValid(tup
))
2796 if (is_missing
!= NULL
)
2801 elog(ERROR
, "cache lookup failed for text search parser %u", prsId
);
2803 form
= (Form_pg_ts_parser
) GETSTRUCT(tup
);
2805 recomputeNamespacePath();
2808 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2809 * the system namespace are surely in the path and so we needn't even do
2810 * list_member_oid() for them.
2812 namespace = form
->prsnamespace
;
2813 if (namespace != PG_CATALOG_NAMESPACE
&&
2814 !list_member_oid(activeSearchPath
, namespace))
2819 * If it is in the path, it might still not be visible; it could be
2820 * hidden by another parser of the same name earlier in the path. So
2821 * we must do a slow check for conflicting parsers.
2823 char *name
= NameStr(form
->prsname
);
2827 foreach(l
, activeSearchPath
)
2829 Oid namespaceId
= lfirst_oid(l
);
2831 if (namespaceId
== myTempNamespace
)
2832 continue; /* do not look in temp namespace */
2834 if (namespaceId
== namespace)
2836 /* Found it first in path */
2840 if (SearchSysCacheExists2(TSPARSERNAMENSP
,
2841 PointerGetDatum(name
),
2842 ObjectIdGetDatum(namespaceId
)))
2844 /* Found something else first in path */
2850 ReleaseSysCache(tup
);
2856 * get_ts_dict_oid - find a TS dictionary by possibly qualified name
2858 * If not found, returns InvalidOid if missing_ok, else throws error
2861 get_ts_dict_oid(List
*names
, bool missing_ok
)
2866 Oid dictoid
= InvalidOid
;
2869 /* deconstruct the name list */
2870 DeconstructQualifiedName(names
, &schemaname
, &dict_name
);
2874 /* use exact schema given */
2875 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
2876 if (missing_ok
&& !OidIsValid(namespaceId
))
2877 dictoid
= InvalidOid
;
2879 dictoid
= GetSysCacheOid2(TSDICTNAMENSP
, Anum_pg_ts_dict_oid
,
2880 PointerGetDatum(dict_name
),
2881 ObjectIdGetDatum(namespaceId
));
2885 /* search for it in search path */
2886 recomputeNamespacePath();
2888 foreach(l
, activeSearchPath
)
2890 namespaceId
= lfirst_oid(l
);
2892 if (namespaceId
== myTempNamespace
)
2893 continue; /* do not look in temp namespace */
2895 dictoid
= GetSysCacheOid2(TSDICTNAMENSP
, Anum_pg_ts_dict_oid
,
2896 PointerGetDatum(dict_name
),
2897 ObjectIdGetDatum(namespaceId
));
2898 if (OidIsValid(dictoid
))
2903 if (!OidIsValid(dictoid
) && !missing_ok
)
2905 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2906 errmsg("text search dictionary \"%s\" does not exist",
2907 NameListToString(names
))));
2913 * TSDictionaryIsVisible
2914 * Determine whether a dictionary (identified by OID) is visible in the
2915 * current search path. Visible means "would be found by searching
2916 * for the unqualified dictionary name".
2919 TSDictionaryIsVisible(Oid dictId
)
2921 return TSDictionaryIsVisibleExt(dictId
, NULL
);
2925 * TSDictionaryIsVisibleExt
2926 * As above, but if the dictionary isn't found and is_missing is not NULL,
2927 * then set *is_missing = true and return false instead of throwing
2928 * an error. (Caller must initialize *is_missing = false.)
2931 TSDictionaryIsVisibleExt(Oid dictId
, bool *is_missing
)
2934 Form_pg_ts_dict form
;
2938 tup
= SearchSysCache1(TSDICTOID
, ObjectIdGetDatum(dictId
));
2939 if (!HeapTupleIsValid(tup
))
2941 if (is_missing
!= NULL
)
2946 elog(ERROR
, "cache lookup failed for text search dictionary %u",
2949 form
= (Form_pg_ts_dict
) GETSTRUCT(tup
);
2951 recomputeNamespacePath();
2954 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2955 * the system namespace are surely in the path and so we needn't even do
2956 * list_member_oid() for them.
2958 namespace = form
->dictnamespace
;
2959 if (namespace != PG_CATALOG_NAMESPACE
&&
2960 !list_member_oid(activeSearchPath
, namespace))
2965 * If it is in the path, it might still not be visible; it could be
2966 * hidden by another dictionary of the same name earlier in the path.
2967 * So we must do a slow check for conflicting dictionaries.
2969 char *name
= NameStr(form
->dictname
);
2973 foreach(l
, activeSearchPath
)
2975 Oid namespaceId
= lfirst_oid(l
);
2977 if (namespaceId
== myTempNamespace
)
2978 continue; /* do not look in temp namespace */
2980 if (namespaceId
== namespace)
2982 /* Found it first in path */
2986 if (SearchSysCacheExists2(TSDICTNAMENSP
,
2987 PointerGetDatum(name
),
2988 ObjectIdGetDatum(namespaceId
)))
2990 /* Found something else first in path */
2996 ReleaseSysCache(tup
);
3002 * get_ts_template_oid - find a TS template by possibly qualified name
3004 * If not found, returns InvalidOid if missing_ok, else throws error
3007 get_ts_template_oid(List
*names
, bool missing_ok
)
3010 char *template_name
;
3012 Oid tmploid
= InvalidOid
;
3015 /* deconstruct the name list */
3016 DeconstructQualifiedName(names
, &schemaname
, &template_name
);
3020 /* use exact schema given */
3021 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
3022 if (missing_ok
&& !OidIsValid(namespaceId
))
3023 tmploid
= InvalidOid
;
3025 tmploid
= GetSysCacheOid2(TSTEMPLATENAMENSP
, Anum_pg_ts_template_oid
,
3026 PointerGetDatum(template_name
),
3027 ObjectIdGetDatum(namespaceId
));
3031 /* search for it in search path */
3032 recomputeNamespacePath();
3034 foreach(l
, activeSearchPath
)
3036 namespaceId
= lfirst_oid(l
);
3038 if (namespaceId
== myTempNamespace
)
3039 continue; /* do not look in temp namespace */
3041 tmploid
= GetSysCacheOid2(TSTEMPLATENAMENSP
, Anum_pg_ts_template_oid
,
3042 PointerGetDatum(template_name
),
3043 ObjectIdGetDatum(namespaceId
));
3044 if (OidIsValid(tmploid
))
3049 if (!OidIsValid(tmploid
) && !missing_ok
)
3051 (errcode(ERRCODE_UNDEFINED_OBJECT
),
3052 errmsg("text search template \"%s\" does not exist",
3053 NameListToString(names
))));
3059 * TSTemplateIsVisible
3060 * Determine whether a template (identified by OID) is visible in the
3061 * current search path. Visible means "would be found by searching
3062 * for the unqualified template name".
3065 TSTemplateIsVisible(Oid tmplId
)
3067 return TSTemplateIsVisibleExt(tmplId
, NULL
);
3071 * TSTemplateIsVisibleExt
3072 * As above, but if the template isn't found and is_missing is not NULL,
3073 * then set *is_missing = true and return false instead of throwing
3074 * an error. (Caller must initialize *is_missing = false.)
3077 TSTemplateIsVisibleExt(Oid tmplId
, bool *is_missing
)
3080 Form_pg_ts_template form
;
3084 tup
= SearchSysCache1(TSTEMPLATEOID
, ObjectIdGetDatum(tmplId
));
3085 if (!HeapTupleIsValid(tup
))
3087 if (is_missing
!= NULL
)
3092 elog(ERROR
, "cache lookup failed for text search template %u", tmplId
);
3094 form
= (Form_pg_ts_template
) GETSTRUCT(tup
);
3096 recomputeNamespacePath();
3099 * Quick check: if it ain't in the path at all, it ain't visible. Items in
3100 * the system namespace are surely in the path and so we needn't even do
3101 * list_member_oid() for them.
3103 namespace = form
->tmplnamespace
;
3104 if (namespace != PG_CATALOG_NAMESPACE
&&
3105 !list_member_oid(activeSearchPath
, namespace))
3110 * If it is in the path, it might still not be visible; it could be
3111 * hidden by another template of the same name earlier in the path. So
3112 * we must do a slow check for conflicting templates.
3114 char *name
= NameStr(form
->tmplname
);
3118 foreach(l
, activeSearchPath
)
3120 Oid namespaceId
= lfirst_oid(l
);
3122 if (namespaceId
== myTempNamespace
)
3123 continue; /* do not look in temp namespace */
3125 if (namespaceId
== namespace)
3127 /* Found it first in path */
3131 if (SearchSysCacheExists2(TSTEMPLATENAMENSP
,
3132 PointerGetDatum(name
),
3133 ObjectIdGetDatum(namespaceId
)))
3135 /* Found something else first in path */
3141 ReleaseSysCache(tup
);
3147 * get_ts_config_oid - find a TS config by possibly qualified name
3149 * If not found, returns InvalidOid if missing_ok, else throws error
3152 get_ts_config_oid(List
*names
, bool missing_ok
)
3157 Oid cfgoid
= InvalidOid
;
3160 /* deconstruct the name list */
3161 DeconstructQualifiedName(names
, &schemaname
, &config_name
);
3165 /* use exact schema given */
3166 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
3167 if (missing_ok
&& !OidIsValid(namespaceId
))
3168 cfgoid
= InvalidOid
;
3170 cfgoid
= GetSysCacheOid2(TSCONFIGNAMENSP
, Anum_pg_ts_config_oid
,
3171 PointerGetDatum(config_name
),
3172 ObjectIdGetDatum(namespaceId
));
3176 /* search for it in search path */
3177 recomputeNamespacePath();
3179 foreach(l
, activeSearchPath
)
3181 namespaceId
= lfirst_oid(l
);
3183 if (namespaceId
== myTempNamespace
)
3184 continue; /* do not look in temp namespace */
3186 cfgoid
= GetSysCacheOid2(TSCONFIGNAMENSP
, Anum_pg_ts_config_oid
,
3187 PointerGetDatum(config_name
),
3188 ObjectIdGetDatum(namespaceId
));
3189 if (OidIsValid(cfgoid
))
3194 if (!OidIsValid(cfgoid
) && !missing_ok
)
3196 (errcode(ERRCODE_UNDEFINED_OBJECT
),
3197 errmsg("text search configuration \"%s\" does not exist",
3198 NameListToString(names
))));
3205 * Determine whether a text search configuration (identified by OID)
3206 * is visible in the current search path. Visible means "would be found
3207 * by searching for the unqualified text search configuration name".
3210 TSConfigIsVisible(Oid cfgid
)
3212 return TSConfigIsVisibleExt(cfgid
, NULL
);
3216 * TSConfigIsVisibleExt
3217 * As above, but if the configuration isn't found and is_missing is not
3218 * NULL, then set *is_missing = true and return false instead of throwing
3219 * an error. (Caller must initialize *is_missing = false.)
3222 TSConfigIsVisibleExt(Oid cfgid
, bool *is_missing
)
3225 Form_pg_ts_config form
;
3229 tup
= SearchSysCache1(TSCONFIGOID
, ObjectIdGetDatum(cfgid
));
3230 if (!HeapTupleIsValid(tup
))
3232 if (is_missing
!= NULL
)
3237 elog(ERROR
, "cache lookup failed for text search configuration %u",
3240 form
= (Form_pg_ts_config
) GETSTRUCT(tup
);
3242 recomputeNamespacePath();
3245 * Quick check: if it ain't in the path at all, it ain't visible. Items in
3246 * the system namespace are surely in the path and so we needn't even do
3247 * list_member_oid() for them.
3249 namespace = form
->cfgnamespace
;
3250 if (namespace != PG_CATALOG_NAMESPACE
&&
3251 !list_member_oid(activeSearchPath
, namespace))
3256 * If it is in the path, it might still not be visible; it could be
3257 * hidden by another configuration of the same name earlier in the
3258 * path. So we must do a slow check for conflicting configurations.
3260 char *name
= NameStr(form
->cfgname
);
3264 foreach(l
, activeSearchPath
)
3266 Oid namespaceId
= lfirst_oid(l
);
3268 if (namespaceId
== myTempNamespace
)
3269 continue; /* do not look in temp namespace */
3271 if (namespaceId
== namespace)
3273 /* Found it first in path */
3277 if (SearchSysCacheExists2(TSCONFIGNAMENSP
,
3278 PointerGetDatum(name
),
3279 ObjectIdGetDatum(namespaceId
)))
3281 /* Found something else first in path */
3287 ReleaseSysCache(tup
);
3294 * DeconstructQualifiedName
3295 * Given a possibly-qualified name expressed as a list of String nodes,
3296 * extract the schema name and object name.
3298 * *nspname_p is set to NULL if there is no explicit schema name.
3301 DeconstructQualifiedName(const List
*names
,
3306 char *schemaname
= NULL
;
3307 char *objname
= NULL
;
3309 switch (list_length(names
))
3312 objname
= strVal(linitial(names
));
3315 schemaname
= strVal(linitial(names
));
3316 objname
= strVal(lsecond(names
));
3319 catalogname
= strVal(linitial(names
));
3320 schemaname
= strVal(lsecond(names
));
3321 objname
= strVal(lthird(names
));
3324 * We check the catalog name and then ignore it.
3326 if (strcmp(catalogname
, get_database_name(MyDatabaseId
)) != 0)
3328 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
3329 errmsg("cross-database references are not implemented: %s",
3330 NameListToString(names
))));
3334 (errcode(ERRCODE_SYNTAX_ERROR
),
3335 errmsg("improper qualified name (too many dotted names): %s",
3336 NameListToString(names
))));
3340 *nspname_p
= schemaname
;
3341 *objname_p
= objname
;
3345 * LookupNamespaceNoError
3346 * Look up a schema name.
3348 * Returns the namespace OID, or InvalidOid if not found.
3350 * Note this does NOT perform any permissions check --- callers are
3351 * responsible for being sure that an appropriate check is made.
3352 * In the majority of cases LookupExplicitNamespace is preferable.
3355 LookupNamespaceNoError(const char *nspname
)
3357 /* check for pg_temp alias */
3358 if (strcmp(nspname
, "pg_temp") == 0)
3360 if (OidIsValid(myTempNamespace
))
3362 InvokeNamespaceSearchHook(myTempNamespace
, true);
3363 return myTempNamespace
;
3367 * Since this is used only for looking up existing objects, there is
3368 * no point in trying to initialize the temp namespace here; and doing
3369 * so might create problems for some callers. Just report "not found".
3374 return get_namespace_oid(nspname
, true);
3378 * LookupExplicitNamespace
3379 * Process an explicitly-specified schema name: look up the schema
3380 * and verify we have USAGE (lookup) rights in it.
3382 * Returns the namespace OID
3385 LookupExplicitNamespace(const char *nspname
, bool missing_ok
)
3388 AclResult aclresult
;
3390 /* check for pg_temp alias */
3391 if (strcmp(nspname
, "pg_temp") == 0)
3393 if (OidIsValid(myTempNamespace
))
3394 return myTempNamespace
;
3397 * Since this is used only for looking up existing objects, there is
3398 * no point in trying to initialize the temp namespace here; and doing
3399 * so might create problems for some callers --- just fall through.
3403 namespaceId
= get_namespace_oid(nspname
, missing_ok
);
3404 if (missing_ok
&& !OidIsValid(namespaceId
))
3407 aclresult
= object_aclcheck(NamespaceRelationId
, namespaceId
, GetUserId(), ACL_USAGE
);
3408 if (aclresult
!= ACLCHECK_OK
)
3409 aclcheck_error(aclresult
, OBJECT_SCHEMA
,
3411 /* Schema search hook for this lookup */
3412 InvokeNamespaceSearchHook(namespaceId
, true);
3418 * LookupCreationNamespace
3419 * Look up the schema and verify we have CREATE rights on it.
3421 * This is just like LookupExplicitNamespace except for the different
3422 * permission check, and that we are willing to create pg_temp if needed.
3424 * Note: calling this may result in a CommandCounterIncrement operation,
3425 * if we have to create or clean out the temp namespace.
3428 LookupCreationNamespace(const char *nspname
)
3431 AclResult aclresult
;
3433 /* check for pg_temp alias */
3434 if (strcmp(nspname
, "pg_temp") == 0)
3436 /* Initialize temp namespace */
3437 AccessTempTableNamespace(false);
3438 return myTempNamespace
;
3441 namespaceId
= get_namespace_oid(nspname
, false);
3443 aclresult
= object_aclcheck(NamespaceRelationId
, namespaceId
, GetUserId(), ACL_CREATE
);
3444 if (aclresult
!= ACLCHECK_OK
)
3445 aclcheck_error(aclresult
, OBJECT_SCHEMA
,
3452 * Common checks on switching namespaces.
3454 * We complain if either the old or new namespaces is a temporary schema
3455 * (or temporary toast schema), or if either the old or new namespaces is the
3459 CheckSetNamespace(Oid oldNspOid
, Oid nspOid
)
3461 /* disallow renaming into or out of temp schemas */
3462 if (isAnyTempNamespace(nspOid
) || isAnyTempNamespace(oldNspOid
))
3464 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
3465 errmsg("cannot move objects into or out of temporary schemas")));
3467 /* same for TOAST schema */
3468 if (nspOid
== PG_TOAST_NAMESPACE
|| oldNspOid
== PG_TOAST_NAMESPACE
)
3470 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
3471 errmsg("cannot move objects into or out of TOAST schema")));
3475 * QualifiedNameGetCreationNamespace
3476 * Given a possibly-qualified name for an object (in List-of-Strings
3477 * format), determine what namespace the object should be created in.
3478 * Also extract and return the object name (last component of list).
3480 * Note: this does not apply any permissions check. Callers must check
3481 * for CREATE rights on the selected namespace when appropriate.
3483 * Note: calling this may result in a CommandCounterIncrement operation,
3484 * if we have to create or clean out the temp namespace.
3487 QualifiedNameGetCreationNamespace(const List
*names
, char **objname_p
)
3492 /* deconstruct the name list */
3493 DeconstructQualifiedName(names
, &schemaname
, objname_p
);
3497 /* check for pg_temp alias */
3498 if (strcmp(schemaname
, "pg_temp") == 0)
3500 /* Initialize temp namespace */
3501 AccessTempTableNamespace(false);
3502 return myTempNamespace
;
3504 /* use exact schema given */
3505 namespaceId
= get_namespace_oid(schemaname
, false);
3506 /* we do not check for USAGE rights here! */
3510 /* use the default creation namespace */
3511 recomputeNamespacePath();
3512 if (activeTempCreationPending
)
3514 /* Need to initialize temp namespace */
3515 AccessTempTableNamespace(true);
3516 return myTempNamespace
;
3518 namespaceId
= activeCreationNamespace
;
3519 if (!OidIsValid(namespaceId
))
3521 (errcode(ERRCODE_UNDEFINED_SCHEMA
),
3522 errmsg("no schema has been selected to create in")));
3529 * get_namespace_oid - given a namespace name, look up the OID
3531 * If missing_ok is false, throw an error if namespace name not found. If
3532 * true, just return InvalidOid.
3535 get_namespace_oid(const char *nspname
, bool missing_ok
)
3539 oid
= GetSysCacheOid1(NAMESPACENAME
, Anum_pg_namespace_oid
,
3540 CStringGetDatum(nspname
));
3541 if (!OidIsValid(oid
) && !missing_ok
)
3543 (errcode(ERRCODE_UNDEFINED_SCHEMA
),
3544 errmsg("schema \"%s\" does not exist", nspname
)));
3550 * makeRangeVarFromNameList
3551 * Utility routine to convert a qualified-name list into RangeVar form.
3554 makeRangeVarFromNameList(const List
*names
)
3556 RangeVar
*rel
= makeRangeVar(NULL
, NULL
, -1);
3558 switch (list_length(names
))
3561 rel
->relname
= strVal(linitial(names
));
3564 rel
->schemaname
= strVal(linitial(names
));
3565 rel
->relname
= strVal(lsecond(names
));
3568 rel
->catalogname
= strVal(linitial(names
));
3569 rel
->schemaname
= strVal(lsecond(names
));
3570 rel
->relname
= strVal(lthird(names
));
3574 (errcode(ERRCODE_SYNTAX_ERROR
),
3575 errmsg("improper relation name (too many dotted names): %s",
3576 NameListToString(names
))));
3585 * Utility routine to convert a qualified-name list into a string.
3587 * This is used primarily to form error messages, and so we do not quote
3588 * the list elements, for the sake of legibility.
3590 * In most scenarios the list elements should always be String values,
3591 * but we also allow A_Star for the convenience of ColumnRef processing.
3594 NameListToString(const List
*names
)
3596 StringInfoData string
;
3599 initStringInfo(&string
);
3603 Node
*name
= (Node
*) lfirst(l
);
3605 if (l
!= list_head(names
))
3606 appendStringInfoChar(&string
, '.');
3608 if (IsA(name
, String
))
3609 appendStringInfoString(&string
, strVal(name
));
3610 else if (IsA(name
, A_Star
))
3611 appendStringInfoChar(&string
, '*');
3613 elog(ERROR
, "unexpected node type in name list: %d",
3614 (int) nodeTag(name
));
3621 * NameListToQuotedString
3622 * Utility routine to convert a qualified-name list into a string.
3624 * Same as above except that names will be double-quoted where necessary,
3625 * so the string could be re-parsed (eg, by textToQualifiedNameList).
3628 NameListToQuotedString(const List
*names
)
3630 StringInfoData string
;
3633 initStringInfo(&string
);
3637 if (l
!= list_head(names
))
3638 appendStringInfoChar(&string
, '.');
3639 appendStringInfoString(&string
, quote_identifier(strVal(lfirst(l
))));
3646 * isTempNamespace - is the given namespace my temporary-table namespace?
3649 isTempNamespace(Oid namespaceId
)
3651 if (OidIsValid(myTempNamespace
) && myTempNamespace
== namespaceId
)
3657 * isTempToastNamespace - is the given namespace my temporary-toast-table
3661 isTempToastNamespace(Oid namespaceId
)
3663 if (OidIsValid(myTempToastNamespace
) && myTempToastNamespace
== namespaceId
)
3669 * isTempOrTempToastNamespace - is the given namespace my temporary-table
3670 * namespace or my temporary-toast-table namespace?
3673 isTempOrTempToastNamespace(Oid namespaceId
)
3675 if (OidIsValid(myTempNamespace
) &&
3676 (myTempNamespace
== namespaceId
|| myTempToastNamespace
== namespaceId
))
3682 * isAnyTempNamespace - is the given namespace a temporary-table namespace
3683 * (either my own, or another backend's)? Temporary-toast-table namespaces
3684 * are included, too.
3687 isAnyTempNamespace(Oid namespaceId
)
3692 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3693 nspname
= get_namespace_name(namespaceId
);
3695 return false; /* no such namespace? */
3696 result
= (strncmp(nspname
, "pg_temp_", 8) == 0) ||
3697 (strncmp(nspname
, "pg_toast_temp_", 14) == 0);
3703 * isOtherTempNamespace - is the given namespace some other backend's
3704 * temporary-table namespace (including temporary-toast-table namespaces)?
3706 * Note: for most purposes in the C code, this function is obsolete. Use
3707 * RELATION_IS_OTHER_TEMP() instead to detect non-local temp relations.
3710 isOtherTempNamespace(Oid namespaceId
)
3712 /* If it's my own temp namespace, say "false" */
3713 if (isTempOrTempToastNamespace(namespaceId
))
3715 /* Else, if it's any temp namespace, say "true" */
3716 return isAnyTempNamespace(namespaceId
);
3720 * checkTempNamespaceStatus - is the given namespace owned and actively used
3723 * Note: this can be used while scanning relations in pg_class to detect
3724 * orphaned temporary tables or namespaces with a backend connected to a
3725 * given database. The result may be out of date quickly, so the caller
3726 * must be careful how to handle this information.
3729 checkTempNamespaceStatus(Oid namespaceId
)
3732 ProcNumber procNumber
;
3734 Assert(OidIsValid(MyDatabaseId
));
3736 procNumber
= GetTempNamespaceProcNumber(namespaceId
);
3738 /* No such namespace, or its name shows it's not temp? */
3739 if (procNumber
== INVALID_PROC_NUMBER
)
3740 return TEMP_NAMESPACE_NOT_TEMP
;
3742 /* Is the backend alive? */
3743 proc
= ProcNumberGetProc(procNumber
);
3745 return TEMP_NAMESPACE_IDLE
;
3747 /* Is the backend connected to the same database we are looking at? */
3748 if (proc
->databaseId
!= MyDatabaseId
)
3749 return TEMP_NAMESPACE_IDLE
;
3751 /* Does the backend own the temporary namespace? */
3752 if (proc
->tempNamespaceId
!= namespaceId
)
3753 return TEMP_NAMESPACE_IDLE
;
3755 /* Yup, so namespace is busy */
3756 return TEMP_NAMESPACE_IN_USE
;
3760 * GetTempNamespaceProcNumber - if the given namespace is a temporary-table
3761 * namespace (either my own, or another backend's), return the proc number
3762 * that owns it. Temporary-toast-table namespaces are included, too.
3763 * If it isn't a temp namespace, return INVALID_PROC_NUMBER.
3766 GetTempNamespaceProcNumber(Oid namespaceId
)
3771 /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3772 nspname
= get_namespace_name(namespaceId
);
3774 return INVALID_PROC_NUMBER
; /* no such namespace? */
3775 if (strncmp(nspname
, "pg_temp_", 8) == 0)
3776 result
= atoi(nspname
+ 8);
3777 else if (strncmp(nspname
, "pg_toast_temp_", 14) == 0)
3778 result
= atoi(nspname
+ 14);
3780 result
= INVALID_PROC_NUMBER
;
3786 * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
3787 * which must already be assigned. (This is only used when creating a toast
3788 * table for a temp table, so we must have already done InitTempTableNamespace)
3791 GetTempToastNamespace(void)
3793 Assert(OidIsValid(myTempToastNamespace
));
3794 return myTempToastNamespace
;
3799 * GetTempNamespaceState - fetch status of session's temporary namespace
3801 * This is used for conveying state to a parallel worker, and is not meant
3802 * for general-purpose access.
3805 GetTempNamespaceState(Oid
*tempNamespaceId
, Oid
*tempToastNamespaceId
)
3807 /* Return namespace OIDs, or 0 if session has not created temp namespace */
3808 *tempNamespaceId
= myTempNamespace
;
3809 *tempToastNamespaceId
= myTempToastNamespace
;
3813 * SetTempNamespaceState - set status of session's temporary namespace
3815 * This is used for conveying state to a parallel worker, and is not meant for
3816 * general-purpose access. By transferring these namespace OIDs to workers,
3817 * we ensure they will have the same notion of the search path as their leader
3821 SetTempNamespaceState(Oid tempNamespaceId
, Oid tempToastNamespaceId
)
3823 /* Worker should not have created its own namespaces ... */
3824 Assert(myTempNamespace
== InvalidOid
);
3825 Assert(myTempToastNamespace
== InvalidOid
);
3826 Assert(myTempNamespaceSubID
== InvalidSubTransactionId
);
3828 /* Assign same namespace OIDs that leader has */
3829 myTempNamespace
= tempNamespaceId
;
3830 myTempToastNamespace
= tempToastNamespaceId
;
3833 * It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
3834 * Even if the namespace is new so far as the leader is concerned, it's
3835 * not new to the worker, and we certainly wouldn't want the worker trying
3839 baseSearchPathValid
= false; /* may need to rebuild list */
3840 searchPathCacheValid
= false;
3845 * GetSearchPathMatcher - fetch current search path definition.
3847 * The result structure is allocated in the specified memory context
3848 * (which might or might not be equal to CurrentMemoryContext); but any
3849 * junk created by revalidation calculations will be in CurrentMemoryContext.
3852 GetSearchPathMatcher(MemoryContext context
)
3854 SearchPathMatcher
*result
;
3856 MemoryContext oldcxt
;
3858 recomputeNamespacePath();
3860 oldcxt
= MemoryContextSwitchTo(context
);
3862 result
= (SearchPathMatcher
*) palloc0(sizeof(SearchPathMatcher
));
3863 schemas
= list_copy(activeSearchPath
);
3864 while (schemas
&& linitial_oid(schemas
) != activeCreationNamespace
)
3866 if (linitial_oid(schemas
) == myTempNamespace
)
3867 result
->addTemp
= true;
3870 Assert(linitial_oid(schemas
) == PG_CATALOG_NAMESPACE
);
3871 result
->addCatalog
= true;
3873 schemas
= list_delete_first(schemas
);
3875 result
->schemas
= schemas
;
3876 result
->generation
= activePathGeneration
;
3878 MemoryContextSwitchTo(oldcxt
);
3884 * CopySearchPathMatcher - copy the specified SearchPathMatcher.
3886 * The result structure is allocated in CurrentMemoryContext.
3889 CopySearchPathMatcher(SearchPathMatcher
*path
)
3891 SearchPathMatcher
*result
;
3893 result
= (SearchPathMatcher
*) palloc(sizeof(SearchPathMatcher
));
3894 result
->schemas
= list_copy(path
->schemas
);
3895 result
->addCatalog
= path
->addCatalog
;
3896 result
->addTemp
= path
->addTemp
;
3897 result
->generation
= path
->generation
;
3903 * SearchPathMatchesCurrentEnvironment - does path match current environment?
3905 * This is tested over and over in some common code paths, and in the typical
3906 * scenario where the active search path seldom changes, it'll always succeed.
3907 * We make that case fast by keeping a generation counter that is advanced
3908 * whenever the active search path changes.
3911 SearchPathMatchesCurrentEnvironment(SearchPathMatcher
*path
)
3916 recomputeNamespacePath();
3918 /* Quick out if already known equal to active path. */
3919 if (path
->generation
== activePathGeneration
)
3922 /* We scan down the activeSearchPath to see if it matches the input. */
3923 lc
= list_head(activeSearchPath
);
3925 /* If path->addTemp, first item should be my temp namespace. */
3928 if (lc
&& lfirst_oid(lc
) == myTempNamespace
)
3929 lc
= lnext(activeSearchPath
, lc
);
3933 /* If path->addCatalog, next item should be pg_catalog. */
3934 if (path
->addCatalog
)
3936 if (lc
&& lfirst_oid(lc
) == PG_CATALOG_NAMESPACE
)
3937 lc
= lnext(activeSearchPath
, lc
);
3941 /* We should now be looking at the activeCreationNamespace. */
3942 if (activeCreationNamespace
!= (lc
? lfirst_oid(lc
) : InvalidOid
))
3944 /* The remainder of activeSearchPath should match path->schemas. */
3945 foreach(lcp
, path
->schemas
)
3947 if (lc
&& lfirst_oid(lc
) == lfirst_oid(lcp
))
3948 lc
= lnext(activeSearchPath
, lc
);
3956 * Update path->generation so that future tests will return quickly, so
3957 * long as the active search path doesn't change.
3959 path
->generation
= activePathGeneration
;
3965 * get_collation_oid - find a collation by possibly qualified name
3967 * Note that this will only find collations that work with the current
3968 * database's encoding.
3971 get_collation_oid(List
*collname
, bool missing_ok
)
3974 char *collation_name
;
3975 int32 dbencoding
= GetDatabaseEncoding();
3980 /* deconstruct the name list */
3981 DeconstructQualifiedName(collname
, &schemaname
, &collation_name
);
3985 /* use exact schema given */
3986 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
3987 if (missing_ok
&& !OidIsValid(namespaceId
))
3990 colloid
= lookup_collation(collation_name
, namespaceId
, dbencoding
);
3991 if (OidIsValid(colloid
))
3996 /* search for it in search path */
3997 recomputeNamespacePath();
3999 foreach(l
, activeSearchPath
)
4001 namespaceId
= lfirst_oid(l
);
4003 if (namespaceId
== myTempNamespace
)
4004 continue; /* do not look in temp namespace */
4006 colloid
= lookup_collation(collation_name
, namespaceId
, dbencoding
);
4007 if (OidIsValid(colloid
))
4012 /* Not found in path */
4015 (errcode(ERRCODE_UNDEFINED_OBJECT
),
4016 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
4017 NameListToString(collname
), GetDatabaseEncodingName())));
4022 * get_conversion_oid - find a conversion by possibly qualified name
4025 get_conversion_oid(List
*conname
, bool missing_ok
)
4028 char *conversion_name
;
4030 Oid conoid
= InvalidOid
;
4033 /* deconstruct the name list */
4034 DeconstructQualifiedName(conname
, &schemaname
, &conversion_name
);
4038 /* use exact schema given */
4039 namespaceId
= LookupExplicitNamespace(schemaname
, missing_ok
);
4040 if (missing_ok
&& !OidIsValid(namespaceId
))
4041 conoid
= InvalidOid
;
4043 conoid
= GetSysCacheOid2(CONNAMENSP
, Anum_pg_conversion_oid
,
4044 PointerGetDatum(conversion_name
),
4045 ObjectIdGetDatum(namespaceId
));
4049 /* search for it in search path */
4050 recomputeNamespacePath();
4052 foreach(l
, activeSearchPath
)
4054 namespaceId
= lfirst_oid(l
);
4056 if (namespaceId
== myTempNamespace
)
4057 continue; /* do not look in temp namespace */
4059 conoid
= GetSysCacheOid2(CONNAMENSP
, Anum_pg_conversion_oid
,
4060 PointerGetDatum(conversion_name
),
4061 ObjectIdGetDatum(namespaceId
));
4062 if (OidIsValid(conoid
))
4067 /* Not found in path */
4068 if (!OidIsValid(conoid
) && !missing_ok
)
4070 (errcode(ERRCODE_UNDEFINED_OBJECT
),
4071 errmsg("conversion \"%s\" does not exist",
4072 NameListToString(conname
))));
4077 * FindDefaultConversionProc - find default encoding conversion proc
4080 FindDefaultConversionProc(int32 for_encoding
, int32 to_encoding
)
4085 recomputeNamespacePath();
4087 foreach(l
, activeSearchPath
)
4089 Oid namespaceId
= lfirst_oid(l
);
4091 if (namespaceId
== myTempNamespace
)
4092 continue; /* do not look in temp namespace */
4094 proc
= FindDefaultConversion(namespaceId
, for_encoding
, to_encoding
);
4095 if (OidIsValid(proc
))
4099 /* Not found in path */
4104 * Look up namespace IDs and perform ACL checks. Return newly-allocated list.
4107 preprocessNamespacePath(const char *searchPath
, Oid roleid
,
4115 /* Need a modifiable copy */
4116 rawname
= pstrdup(searchPath
);
4118 /* Parse string into list of identifiers */
4119 if (!SplitIdentifierString(rawname
, ',', &namelist
))
4121 /* syntax error in name list */
4122 /* this should not happen if GUC checked check_search_path */
4123 elog(ERROR
, "invalid list syntax");
4127 * Convert the list of names to a list of OIDs. If any names are not
4128 * recognizable or we don't have read access, just leave them out of the
4129 * list. (We can't raise an error, since the search_path setting has
4130 * already been accepted.) Don't make duplicate entries, either.
4133 *temp_missing
= false;
4134 foreach(l
, namelist
)
4136 char *curname
= (char *) lfirst(l
);
4139 if (strcmp(curname
, "$user") == 0)
4141 /* $user --- substitute namespace matching user name, if any */
4144 tuple
= SearchSysCache1(AUTHOID
, ObjectIdGetDatum(roleid
));
4145 if (HeapTupleIsValid(tuple
))
4149 rname
= NameStr(((Form_pg_authid
) GETSTRUCT(tuple
))->rolname
);
4150 namespaceId
= get_namespace_oid(rname
, true);
4151 ReleaseSysCache(tuple
);
4152 if (OidIsValid(namespaceId
) &&
4153 object_aclcheck(NamespaceRelationId
, namespaceId
, roleid
,
4154 ACL_USAGE
) == ACLCHECK_OK
)
4155 oidlist
= lappend_oid(oidlist
, namespaceId
);
4158 else if (strcmp(curname
, "pg_temp") == 0)
4160 /* pg_temp --- substitute temp namespace, if any */
4161 if (OidIsValid(myTempNamespace
))
4162 oidlist
= lappend_oid(oidlist
, myTempNamespace
);
4165 /* If it ought to be the creation namespace, set flag */
4167 *temp_missing
= true;
4172 /* normal namespace reference */
4173 namespaceId
= get_namespace_oid(curname
, true);
4174 if (OidIsValid(namespaceId
) &&
4175 object_aclcheck(NamespaceRelationId
, namespaceId
, roleid
,
4176 ACL_USAGE
) == ACLCHECK_OK
)
4177 oidlist
= lappend_oid(oidlist
, namespaceId
);
4182 list_free(namelist
);
4188 * Remove duplicates, run namespace search hooks, and prepend
4189 * implicitly-searched namespaces. Return newly-allocated list.
4191 * If an object_access_hook is present, this must always be recalculated. It
4192 * may seem that duplicate elimination is not dependent on the result of the
4193 * hook, but if a hook returns different results on different calls for the
4194 * same namespace ID, then it could affect the order in which that namespace
4195 * appears in the final list.
4198 finalNamespacePath(List
*oidlist
, Oid
*firstNS
)
4200 List
*finalPath
= NIL
;
4203 foreach(lc
, oidlist
)
4205 Oid namespaceId
= lfirst_oid(lc
);
4207 if (!list_member_oid(finalPath
, namespaceId
))
4209 if (InvokeNamespaceSearchHook(namespaceId
, false))
4210 finalPath
= lappend_oid(finalPath
, namespaceId
);
4215 * Remember the first member of the explicit list. (Note: this is
4216 * nominally wrong if temp_missing, but we need it anyway to distinguish
4217 * explicit from implicit mention of pg_catalog.)
4219 if (finalPath
== NIL
)
4220 *firstNS
= InvalidOid
;
4222 *firstNS
= linitial_oid(finalPath
);
4225 * Add any implicitly-searched namespaces to the list. Note these go on
4226 * the front, not the back; also notice that we do not check USAGE
4227 * permissions for these.
4229 if (!list_member_oid(finalPath
, PG_CATALOG_NAMESPACE
))
4230 finalPath
= lcons_oid(PG_CATALOG_NAMESPACE
, finalPath
);
4232 if (OidIsValid(myTempNamespace
) &&
4233 !list_member_oid(finalPath
, myTempNamespace
))
4234 finalPath
= lcons_oid(myTempNamespace
, finalPath
);
4240 * Retrieve search path information from the cache; or if not there, fill
4241 * it. The returned entry is valid only until the next call to this function.
4243 static const SearchPathCacheEntry
*
4244 cachedNamespacePath(const char *searchPath
, Oid roleid
)
4246 MemoryContext oldcxt
;
4247 SearchPathCacheEntry
*entry
;
4251 entry
= spcache_insert(searchPath
, roleid
);
4254 * An OOM may have resulted in a cache entry with missing 'oidlist' or
4255 * 'finalPath', so just compute whatever is missing.
4258 if (entry
->oidlist
== NIL
)
4260 oldcxt
= MemoryContextSwitchTo(SearchPathCacheContext
);
4261 entry
->oidlist
= preprocessNamespacePath(searchPath
, roleid
,
4262 &entry
->temp_missing
);
4263 MemoryContextSwitchTo(oldcxt
);
4267 * If a hook is set, we must recompute finalPath from the oidlist each
4268 * time, because the hook may affect the result. This is still much faster
4269 * than recomputing from the string (and doing catalog lookups and ACL
4272 if (entry
->finalPath
== NIL
|| object_access_hook
||
4273 entry
->forceRecompute
)
4275 list_free(entry
->finalPath
);
4276 entry
->finalPath
= NIL
;
4278 oldcxt
= MemoryContextSwitchTo(SearchPathCacheContext
);
4279 entry
->finalPath
= finalNamespacePath(entry
->oidlist
,
4281 MemoryContextSwitchTo(oldcxt
);
4284 * If an object_access_hook is set when finalPath is calculated, the
4285 * result may be affected by the hook. Force recomputation of
4286 * finalPath the next time this cache entry is used, even if the
4287 * object_access_hook is not set at that time.
4289 entry
->forceRecompute
= object_access_hook
? true : false;
4296 * recomputeNamespacePath - recompute path derived variables if needed.
4299 recomputeNamespacePath(void)
4301 Oid roleid
= GetUserId();
4303 const SearchPathCacheEntry
*entry
;
4305 /* Do nothing if path is already valid. */
4306 if (baseSearchPathValid
&& namespaceUser
== roleid
)
4309 entry
= cachedNamespacePath(namespace_search_path
, roleid
);
4311 if (baseCreationNamespace
== entry
->firstNS
&&
4312 baseTempCreationPending
== entry
->temp_missing
&&
4313 equal(entry
->finalPath
, baseSearchPath
))
4315 pathChanged
= false;
4319 MemoryContext oldcxt
;
4324 /* Must save OID list in permanent storage. */
4325 oldcxt
= MemoryContextSwitchTo(TopMemoryContext
);
4326 newpath
= list_copy(entry
->finalPath
);
4327 MemoryContextSwitchTo(oldcxt
);
4329 /* Now safe to assign to state variables. */
4330 list_free(baseSearchPath
);
4331 baseSearchPath
= newpath
;
4332 baseCreationNamespace
= entry
->firstNS
;
4333 baseTempCreationPending
= entry
->temp_missing
;
4336 /* Mark the path valid. */
4337 baseSearchPathValid
= true;
4338 namespaceUser
= roleid
;
4340 /* And make it active. */
4341 activeSearchPath
= baseSearchPath
;
4342 activeCreationNamespace
= baseCreationNamespace
;
4343 activeTempCreationPending
= baseTempCreationPending
;
4346 * Bump the generation only if something actually changed. (Notice that
4347 * what we compared to was the old state of the base path variables.)
4350 activePathGeneration
++;
4354 * AccessTempTableNamespace
4355 * Provide access to a temporary namespace, potentially creating it
4356 * if not present yet. This routine registers if the namespace gets
4357 * in use in this transaction. 'force' can be set to true to allow
4358 * the caller to enforce the creation of the temporary namespace for
4359 * use in this backend, which happens if its creation is pending.
4362 AccessTempTableNamespace(bool force
)
4365 * Make note that this temporary namespace has been accessed in this
4368 MyXactFlags
|= XACT_FLAGS_ACCESSEDTEMPNAMESPACE
;
4371 * If the caller attempting to access a temporary schema expects the
4372 * creation of the namespace to be pending and should be enforced, then go
4373 * through the creation.
4375 if (!force
&& OidIsValid(myTempNamespace
))
4379 * The temporary tablespace does not exist yet and is wanted, so
4382 InitTempTableNamespace();
4386 * InitTempTableNamespace
4387 * Initialize temp table namespace on first use in a particular backend
4390 InitTempTableNamespace(void)
4392 char namespaceName
[NAMEDATALEN
];
4396 Assert(!OidIsValid(myTempNamespace
));
4399 * First, do permission check to see if we are authorized to make temp
4400 * tables. We use a nonstandard error message here since "databasename:
4401 * permission denied" might be a tad cryptic.
4403 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
4404 * that's necessary since current user ID could change during the session.
4405 * But there's no need to make the namespace in the first place until a
4406 * temp table creation request is made by someone with appropriate rights.
4408 if (object_aclcheck(DatabaseRelationId
, MyDatabaseId
, GetUserId(),
4409 ACL_CREATE_TEMP
) != ACLCHECK_OK
)
4411 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
4412 errmsg("permission denied to create temporary tables in database \"%s\"",
4413 get_database_name(MyDatabaseId
))));
4416 * Do not allow a Hot Standby session to make temp tables. Aside from
4417 * problems with modifying the system catalogs, there is a naming
4418 * conflict: pg_temp_N belongs to the session with proc number N on the
4419 * primary, not to a hot standby session with the same proc number. We
4420 * should not be able to get here anyway due to XactReadOnly checks, but
4421 * let's just make real sure. Note that this also backstops various
4422 * operations that allow XactReadOnly transactions to modify temp tables;
4423 * they'd need RecoveryInProgress checks if not for this.
4425 if (RecoveryInProgress())
4427 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION
),
4428 errmsg("cannot create temporary tables during recovery")));
4430 /* Parallel workers can't create temporary tables, either. */
4431 if (IsParallelWorker())
4433 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION
),
4434 errmsg("cannot create temporary tables during a parallel operation")));
4436 snprintf(namespaceName
, sizeof(namespaceName
), "pg_temp_%d", MyProcNumber
);
4438 namespaceId
= get_namespace_oid(namespaceName
, true);
4439 if (!OidIsValid(namespaceId
))
4442 * First use of this temp namespace in this database; create it. The
4443 * temp namespaces are always owned by the superuser. We leave their
4444 * permissions at default --- i.e., no access except to superuser ---
4445 * to ensure that unprivileged users can't peek at other backends'
4446 * temp tables. This works because the places that access the temp
4447 * namespace for my own backend skip permissions checks on it.
4449 namespaceId
= NamespaceCreate(namespaceName
, BOOTSTRAP_SUPERUSERID
,
4451 /* Advance command counter to make namespace visible */
4452 CommandCounterIncrement();
4457 * If the namespace already exists, clean it out (in case the former
4458 * owner crashed without doing so).
4460 RemoveTempRelations(namespaceId
);
4464 * If the corresponding toast-table namespace doesn't exist yet, create
4465 * it. (We assume there is no need to clean it out if it does exist, since
4466 * dropping a parent table should make its toast table go away.)
4468 snprintf(namespaceName
, sizeof(namespaceName
), "pg_toast_temp_%d",
4471 toastspaceId
= get_namespace_oid(namespaceName
, true);
4472 if (!OidIsValid(toastspaceId
))
4474 toastspaceId
= NamespaceCreate(namespaceName
, BOOTSTRAP_SUPERUSERID
,
4476 /* Advance command counter to make namespace visible */
4477 CommandCounterIncrement();
4481 * Okay, we've prepared the temp namespace ... but it's not committed yet,
4482 * so all our work could be undone by transaction rollback. Set flag for
4483 * AtEOXact_Namespace to know what to do.
4485 myTempNamespace
= namespaceId
;
4486 myTempToastNamespace
= toastspaceId
;
4489 * Mark MyProc as owning this namespace which other processes can use to
4490 * decide if a temporary namespace is in use or not. We assume that
4491 * assignment of namespaceId is an atomic operation. Even if it is not,
4492 * the temporary relation which resulted in the creation of this temporary
4493 * namespace is still locked until the current transaction commits, and
4494 * its pg_namespace row is not visible yet. However it does not matter:
4495 * this flag makes the namespace as being in use, so no objects created on
4496 * it would be removed concurrently.
4498 MyProc
->tempNamespaceId
= namespaceId
;
4500 /* It should not be done already. */
4501 Assert(myTempNamespaceSubID
== InvalidSubTransactionId
);
4502 myTempNamespaceSubID
= GetCurrentSubTransactionId();
4504 baseSearchPathValid
= false; /* need to rebuild list */
4505 searchPathCacheValid
= false;
4509 * End-of-transaction cleanup for namespaces.
4512 AtEOXact_Namespace(bool isCommit
, bool parallel
)
4515 * If we abort the transaction in which a temp namespace was selected,
4516 * we'll have to do any creation or cleanout work over again. So, just
4517 * forget the namespace entirely until next time. On the other hand, if
4518 * we commit then register an exit callback to clean out the temp tables
4519 * at backend shutdown. (We only want to register the callback once per
4520 * session, so this is a good place to do it.)
4522 if (myTempNamespaceSubID
!= InvalidSubTransactionId
&& !parallel
)
4525 before_shmem_exit(RemoveTempRelationsCallback
, 0);
4528 myTempNamespace
= InvalidOid
;
4529 myTempToastNamespace
= InvalidOid
;
4530 baseSearchPathValid
= false; /* need to rebuild list */
4531 searchPathCacheValid
= false;
4534 * Reset the temporary namespace flag in MyProc. We assume that
4535 * this operation is atomic.
4537 * Because this transaction is aborting, the pg_namespace row is
4538 * not visible to anyone else anyway, but that doesn't matter:
4539 * it's not a problem if objects contained in this namespace are
4540 * removed concurrently.
4542 MyProc
->tempNamespaceId
= InvalidOid
;
4544 myTempNamespaceSubID
= InvalidSubTransactionId
;
4550 * AtEOSubXact_Namespace
4552 * At subtransaction commit, propagate the temp-namespace-creation
4553 * flag to the parent subtransaction.
4555 * At subtransaction abort, forget the flag if we set it up.
4558 AtEOSubXact_Namespace(bool isCommit
, SubTransactionId mySubid
,
4559 SubTransactionId parentSubid
)
4562 if (myTempNamespaceSubID
== mySubid
)
4565 myTempNamespaceSubID
= parentSubid
;
4568 myTempNamespaceSubID
= InvalidSubTransactionId
;
4569 /* TEMP namespace creation failed, so reset state */
4570 myTempNamespace
= InvalidOid
;
4571 myTempToastNamespace
= InvalidOid
;
4572 baseSearchPathValid
= false; /* need to rebuild list */
4573 searchPathCacheValid
= false;
4576 * Reset the temporary namespace flag in MyProc. We assume that
4577 * this operation is atomic.
4579 * Because this subtransaction is aborting, the pg_namespace row
4580 * is not visible to anyone else anyway, but that doesn't matter:
4581 * it's not a problem if objects contained in this namespace are
4582 * removed concurrently.
4584 MyProc
->tempNamespaceId
= InvalidOid
;
4590 * Remove all relations in the specified temp namespace.
4592 * This is called at backend shutdown (if we made any temp relations).
4593 * It is also called when we begin using a pre-existing temp namespace,
4594 * in order to clean out any relations that might have been created by
4595 * a crashed backend.
4598 RemoveTempRelations(Oid tempNamespaceId
)
4600 ObjectAddress object
;
4603 * We want to get rid of everything in the target namespace, but not the
4604 * namespace itself (deleting it only to recreate it later would be a
4605 * waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
4606 * deletion, and we want to not drop any extensions that might happen to
4609 object
.classId
= NamespaceRelationId
;
4610 object
.objectId
= tempNamespaceId
;
4611 object
.objectSubId
= 0;
4613 performDeletion(&object
, DROP_CASCADE
,
4614 PERFORM_DELETION_INTERNAL
|
4615 PERFORM_DELETION_QUIETLY
|
4616 PERFORM_DELETION_SKIP_ORIGINAL
|
4617 PERFORM_DELETION_SKIP_EXTENSIONS
);
4621 * Callback to remove temp relations at backend exit.
4624 RemoveTempRelationsCallback(int code
, Datum arg
)
4626 if (OidIsValid(myTempNamespace
)) /* should always be true */
4628 /* Need to ensure we have a usable transaction. */
4629 AbortOutOfAnyTransaction();
4630 StartTransactionCommand();
4631 PushActiveSnapshot(GetTransactionSnapshot());
4633 RemoveTempRelations(myTempNamespace
);
4635 PopActiveSnapshot();
4636 CommitTransactionCommand();
4641 * Remove all temp tables from the temporary namespace.
4644 ResetTempTableNamespace(void)
4646 if (OidIsValid(myTempNamespace
))
4647 RemoveTempRelations(myTempNamespace
);
4652 * Routines for handling the GUC variable 'search_path'.
4655 /* check_hook: validate new search_path value */
4657 check_search_path(char **newval
, void **extra
, GucSource source
)
4659 Oid roleid
= InvalidOid
;
4660 const char *searchPath
= *newval
;
4663 bool use_cache
= (SearchPathCacheContext
!= NULL
);
4666 * We used to try to check that the named schemas exist, but there are
4667 * many valid use-cases for having search_path settings that include
4668 * schemas that don't exist; and often, we are not inside a transaction
4669 * here and so can't consult the system catalogs anyway. So now, the only
4670 * requirement is syntactic validity of the identifier list.
4672 * Checking only the syntactic validity also allows us to use the search
4673 * path cache (if available) to avoid calling SplitIdentifierString() on
4674 * the same string repeatedly.
4680 roleid
= GetUserId();
4682 if (spcache_lookup(searchPath
, roleid
) != NULL
)
4687 * Ensure validity check succeeds before creating cache entry.
4690 rawname
= pstrdup(searchPath
); /* need a modifiable copy */
4692 /* Parse string into list of identifiers */
4693 if (!SplitIdentifierString(rawname
, ',', &namelist
))
4695 /* syntax error in name list */
4696 GUC_check_errdetail("List syntax is invalid.");
4698 list_free(namelist
);
4702 list_free(namelist
);
4704 /* OK to create empty cache entry */
4706 (void) spcache_insert(searchPath
, roleid
);
4711 /* assign_hook: do extra actions as needed */
4713 assign_search_path(const char *newval
, void *extra
)
4715 /* don't access search_path during bootstrap */
4716 Assert(!IsBootstrapProcessingMode());
4719 * We mark the path as needing recomputation, but don't do anything until
4720 * it's needed. This avoids trying to do database access during GUC
4721 * initialization, or outside a transaction.
4723 * This does not invalidate the search path cache, so if this value had
4724 * been previously set and no syscache invalidations happened,
4725 * recomputation may not be necessary.
4727 baseSearchPathValid
= false;
4731 * InitializeSearchPath: initialize module during InitPostgres.
4733 * This is called after we are up enough to be able to do catalog lookups.
4736 InitializeSearchPath(void)
4738 if (IsBootstrapProcessingMode())
4741 * In bootstrap mode, the search path must be 'pg_catalog' so that
4742 * tables are created in the proper namespace; ignore the GUC setting.
4744 MemoryContext oldcxt
;
4746 oldcxt
= MemoryContextSwitchTo(TopMemoryContext
);
4747 baseSearchPath
= list_make1_oid(PG_CATALOG_NAMESPACE
);
4748 MemoryContextSwitchTo(oldcxt
);
4749 baseCreationNamespace
= PG_CATALOG_NAMESPACE
;
4750 baseTempCreationPending
= false;
4751 baseSearchPathValid
= true;
4752 namespaceUser
= GetUserId();
4753 activeSearchPath
= baseSearchPath
;
4754 activeCreationNamespace
= baseCreationNamespace
;
4755 activeTempCreationPending
= baseTempCreationPending
;
4756 activePathGeneration
++; /* pro forma */
4761 * In normal mode, arrange for a callback on any syscache invalidation
4762 * that will affect the search_path cache.
4765 /* namespace name or ACLs may have changed */
4766 CacheRegisterSyscacheCallback(NAMESPACEOID
,
4767 InvalidationCallback
,
4770 /* role name may affect the meaning of "$user" */
4771 CacheRegisterSyscacheCallback(AUTHOID
,
4772 InvalidationCallback
,
4775 /* role membership may affect ACLs */
4776 CacheRegisterSyscacheCallback(AUTHMEMROLEMEM
,
4777 InvalidationCallback
,
4780 /* database owner may affect ACLs */
4781 CacheRegisterSyscacheCallback(DATABASEOID
,
4782 InvalidationCallback
,
4785 /* Force search path to be recomputed on next use */
4786 baseSearchPathValid
= false;
4787 searchPathCacheValid
= false;
4792 * InvalidationCallback
4793 * Syscache inval callback function
4796 InvalidationCallback(Datum arg
, int cacheid
, uint32 hashvalue
)
4799 * Force search path to be recomputed on next use, also invalidating the
4800 * search path cache (because namespace names, ACLs, or role names may
4803 baseSearchPathValid
= false;
4804 searchPathCacheValid
= false;
4808 * Fetch the active search path. The return value is a palloc'ed list
4809 * of OIDs; the caller is responsible for freeing this storage as
4812 * The returned list includes the implicitly-prepended namespaces only if
4813 * includeImplicit is true.
4815 * Note: calling this may result in a CommandCounterIncrement operation,
4816 * if we have to create or clean out the temp namespace.
4819 fetch_search_path(bool includeImplicit
)
4823 recomputeNamespacePath();
4826 * If the temp namespace should be first, force it to exist. This is so
4827 * that callers can trust the result to reflect the actual default
4828 * creation namespace. It's a bit bogus to do this here, since
4829 * current_schema() is supposedly a stable function without side-effects,
4830 * but the alternatives seem worse.
4832 if (activeTempCreationPending
)
4834 AccessTempTableNamespace(true);
4835 recomputeNamespacePath();
4838 result
= list_copy(activeSearchPath
);
4839 if (!includeImplicit
)
4841 while (result
&& linitial_oid(result
) != activeCreationNamespace
)
4842 result
= list_delete_first(result
);
4849 * Fetch the active search path into a caller-allocated array of OIDs.
4850 * Returns the number of path entries. (If this is more than sarray_len,
4851 * then the data didn't fit and is not all stored.)
4853 * The returned list always includes the implicitly-prepended namespaces,
4854 * but never includes the temp namespace. (This is suitable for existing
4855 * users, which would want to ignore the temp namespace anyway.) This
4856 * definition allows us to not worry about initializing the temp namespace.
4859 fetch_search_path_array(Oid
*sarray
, int sarray_len
)
4864 recomputeNamespacePath();
4866 foreach(l
, activeSearchPath
)
4868 Oid namespaceId
= lfirst_oid(l
);
4870 if (namespaceId
== myTempNamespace
)
4871 continue; /* do not include temp namespace */
4873 if (count
< sarray_len
)
4874 sarray
[count
] = namespaceId
;
4883 * Export the FooIsVisible functions as SQL-callable functions.
4885 * Note: as of Postgres 8.4, these will silently return NULL if called on
4886 * a nonexistent object OID, rather than failing. This is to avoid race
4887 * condition errors when a query that's scanning a catalog using an MVCC
4888 * snapshot uses one of these functions. The underlying IsVisible functions
4889 * always use an up-to-date snapshot and so might see the object as already
4890 * gone when it's still visible to the transaction snapshot.
4894 pg_table_is_visible(PG_FUNCTION_ARGS
)
4896 Oid oid
= PG_GETARG_OID(0);
4898 bool is_missing
= false;
4900 result
= RelationIsVisibleExt(oid
, &is_missing
);
4904 PG_RETURN_BOOL(result
);
4908 pg_type_is_visible(PG_FUNCTION_ARGS
)
4910 Oid oid
= PG_GETARG_OID(0);
4912 bool is_missing
= false;
4914 result
= TypeIsVisibleExt(oid
, &is_missing
);
4918 PG_RETURN_BOOL(result
);
4922 pg_function_is_visible(PG_FUNCTION_ARGS
)
4924 Oid oid
= PG_GETARG_OID(0);
4926 bool is_missing
= false;
4928 result
= FunctionIsVisibleExt(oid
, &is_missing
);
4932 PG_RETURN_BOOL(result
);
4936 pg_operator_is_visible(PG_FUNCTION_ARGS
)
4938 Oid oid
= PG_GETARG_OID(0);
4940 bool is_missing
= false;
4942 result
= OperatorIsVisibleExt(oid
, &is_missing
);
4946 PG_RETURN_BOOL(result
);
4950 pg_opclass_is_visible(PG_FUNCTION_ARGS
)
4952 Oid oid
= PG_GETARG_OID(0);
4954 bool is_missing
= false;
4956 result
= OpclassIsVisibleExt(oid
, &is_missing
);
4960 PG_RETURN_BOOL(result
);
4964 pg_opfamily_is_visible(PG_FUNCTION_ARGS
)
4966 Oid oid
= PG_GETARG_OID(0);
4968 bool is_missing
= false;
4970 result
= OpfamilyIsVisibleExt(oid
, &is_missing
);
4974 PG_RETURN_BOOL(result
);
4978 pg_collation_is_visible(PG_FUNCTION_ARGS
)
4980 Oid oid
= PG_GETARG_OID(0);
4982 bool is_missing
= false;
4984 result
= CollationIsVisibleExt(oid
, &is_missing
);
4988 PG_RETURN_BOOL(result
);
4992 pg_conversion_is_visible(PG_FUNCTION_ARGS
)
4994 Oid oid
= PG_GETARG_OID(0);
4996 bool is_missing
= false;
4998 result
= ConversionIsVisibleExt(oid
, &is_missing
);
5002 PG_RETURN_BOOL(result
);
5006 pg_statistics_obj_is_visible(PG_FUNCTION_ARGS
)
5008 Oid oid
= PG_GETARG_OID(0);
5010 bool is_missing
= false;
5012 result
= StatisticsObjIsVisibleExt(oid
, &is_missing
);
5016 PG_RETURN_BOOL(result
);
5020 pg_ts_parser_is_visible(PG_FUNCTION_ARGS
)
5022 Oid oid
= PG_GETARG_OID(0);
5024 bool is_missing
= false;
5026 result
= TSParserIsVisibleExt(oid
, &is_missing
);
5030 PG_RETURN_BOOL(result
);
5034 pg_ts_dict_is_visible(PG_FUNCTION_ARGS
)
5036 Oid oid
= PG_GETARG_OID(0);
5038 bool is_missing
= false;
5040 result
= TSDictionaryIsVisibleExt(oid
, &is_missing
);
5044 PG_RETURN_BOOL(result
);
5048 pg_ts_template_is_visible(PG_FUNCTION_ARGS
)
5050 Oid oid
= PG_GETARG_OID(0);
5052 bool is_missing
= false;
5054 result
= TSTemplateIsVisibleExt(oid
, &is_missing
);
5058 PG_RETURN_BOOL(result
);
5062 pg_ts_config_is_visible(PG_FUNCTION_ARGS
)
5064 Oid oid
= PG_GETARG_OID(0);
5066 bool is_missing
= false;
5068 result
= TSConfigIsVisibleExt(oid
, &is_missing
);
5072 PG_RETURN_BOOL(result
);
5076 pg_my_temp_schema(PG_FUNCTION_ARGS
)
5078 PG_RETURN_OID(myTempNamespace
);
5082 pg_is_other_temp_schema(PG_FUNCTION_ARGS
)
5084 Oid oid
= PG_GETARG_OID(0);
5086 PG_RETURN_BOOL(isOtherTempNamespace(oid
));