PostgreSQL Source Code git master
namespace.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/parallel.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "common/hashfn_unstable.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/procarray.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/guc_hooks.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
#include "lib/simplehash.h"
Include dependency graph for namespace.c:

Go to the source code of this file.

Data Structures

struct  SearchPathCacheKey
 
struct  SearchPathCacheEntry
 

Macros

#define SH_PREFIX   nsphash
 
#define SH_ELEMENT_TYPE   SearchPathCacheEntry
 
#define SH_KEY_TYPE   SearchPathCacheKey
 
#define SH_KEY   key
 
#define SH_HASH_KEY(tb, key)   spcachekey_hash(key)
 
#define SH_EQUAL(tb, a, b)   spcachekey_equal(a, b)
 
#define SH_SCOPE   static inline
 
#define SH_DECLARE
 
#define SH_DEFINE
 
#define SPCACHE_RESET_THRESHOLD   256
 
#define SPACE_PER_OP
 

Typedefs

typedef struct SearchPathCacheKey SearchPathCacheKey
 
typedef struct SearchPathCacheEntry SearchPathCacheEntry
 

Functions

static bool RelationIsVisibleExt (Oid relid, bool *is_missing)
 
static bool TypeIsVisibleExt (Oid typid, bool *is_missing)
 
static bool FunctionIsVisibleExt (Oid funcid, bool *is_missing)
 
static bool OperatorIsVisibleExt (Oid oprid, bool *is_missing)
 
static bool OpclassIsVisibleExt (Oid opcid, bool *is_missing)
 
static bool OpfamilyIsVisibleExt (Oid opfid, bool *is_missing)
 
static bool CollationIsVisibleExt (Oid collid, bool *is_missing)
 
static bool ConversionIsVisibleExt (Oid conid, bool *is_missing)
 
static bool StatisticsObjIsVisibleExt (Oid stxid, bool *is_missing)
 
static bool TSParserIsVisibleExt (Oid prsId, bool *is_missing)
 
static bool TSDictionaryIsVisibleExt (Oid dictId, bool *is_missing)
 
static bool TSTemplateIsVisibleExt (Oid tmplId, bool *is_missing)
 
static bool TSConfigIsVisibleExt (Oid cfgid, bool *is_missing)
 
static void recomputeNamespacePath (void)
 
static void AccessTempTableNamespace (bool force)
 
static void InitTempTableNamespace (void)
 
static void RemoveTempRelations (Oid tempNamespaceId)
 
static void RemoveTempRelationsCallback (int code, Datum arg)
 
static void InvalidationCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static bool MatchNamedCall (HeapTuple proctup, int nargs, List *argnames, bool include_out_arguments, int pronargs, int **argnumbers)
 
static uint32 spcachekey_hash (SearchPathCacheKey key)
 
static bool spcachekey_equal (SearchPathCacheKey a, SearchPathCacheKey b)
 
static void spcache_init (void)
 
static SearchPathCacheEntryspcache_lookup (const char *searchPath, Oid roleid)
 
static SearchPathCacheEntryspcache_insert (const char *searchPath, Oid roleid)
 
Oid RangeVarGetRelidExtended (const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
 
Oid RangeVarGetCreationNamespace (const RangeVar *newRelation)
 
Oid RangeVarGetAndCheckCreationNamespace (RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
 
void RangeVarAdjustRelationPersistence (RangeVar *newRelation, Oid nspid)
 
Oid RelnameGetRelid (const char *relname)
 
bool RelationIsVisible (Oid relid)
 
Oid TypenameGetTypid (const char *typname)
 
Oid TypenameGetTypidExtended (const char *typname, bool temp_ok)
 
bool TypeIsVisible (Oid typid)
 
FuncCandidateList FuncnameGetCandidates (List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool include_out_arguments, bool missing_ok)
 
bool FunctionIsVisible (Oid funcid)
 
Oid OpernameGetOprid (List *names, Oid oprleft, Oid oprright)
 
FuncCandidateList OpernameGetCandidates (List *names, char oprkind, bool missing_schema_ok)
 
bool OperatorIsVisible (Oid oprid)
 
Oid OpclassnameGetOpcid (Oid amid, const char *opcname)
 
bool OpclassIsVisible (Oid opcid)
 
Oid OpfamilynameGetOpfid (Oid amid, const char *opfname)
 
bool OpfamilyIsVisible (Oid opfid)
 
static Oid lookup_collation (const char *collname, Oid collnamespace, int32 encoding)
 
Oid CollationGetCollid (const char *collname)
 
bool CollationIsVisible (Oid collid)
 
Oid ConversionGetConid (const char *conname)
 
bool ConversionIsVisible (Oid conid)
 
Oid get_statistics_object_oid (List *names, bool missing_ok)
 
bool StatisticsObjIsVisible (Oid stxid)
 
Oid get_ts_parser_oid (List *names, bool missing_ok)
 
bool TSParserIsVisible (Oid prsId)
 
Oid get_ts_dict_oid (List *names, bool missing_ok)
 
bool TSDictionaryIsVisible (Oid dictId)
 
Oid get_ts_template_oid (List *names, bool missing_ok)
 
bool TSTemplateIsVisible (Oid tmplId)
 
Oid get_ts_config_oid (List *names, bool missing_ok)
 
bool TSConfigIsVisible (Oid cfgid)
 
void DeconstructQualifiedName (const List *names, char **nspname_p, char **objname_p)
 
Oid LookupNamespaceNoError (const char *nspname)
 
Oid LookupExplicitNamespace (const char *nspname, bool missing_ok)
 
Oid LookupCreationNamespace (const char *nspname)
 
void CheckSetNamespace (Oid oldNspOid, Oid nspOid)
 
Oid QualifiedNameGetCreationNamespace (const List *names, char **objname_p)
 
Oid get_namespace_oid (const char *nspname, bool missing_ok)
 
RangeVarmakeRangeVarFromNameList (const List *names)
 
char * NameListToString (const List *names)
 
char * NameListToQuotedString (const List *names)
 
bool isTempNamespace (Oid namespaceId)
 
bool isTempToastNamespace (Oid namespaceId)
 
bool isTempOrTempToastNamespace (Oid namespaceId)
 
bool isAnyTempNamespace (Oid namespaceId)
 
bool isOtherTempNamespace (Oid namespaceId)
 
TempNamespaceStatus checkTempNamespaceStatus (Oid namespaceId)
 
ProcNumber GetTempNamespaceProcNumber (Oid namespaceId)
 
Oid GetTempToastNamespace (void)
 
void GetTempNamespaceState (Oid *tempNamespaceId, Oid *tempToastNamespaceId)
 
void SetTempNamespaceState (Oid tempNamespaceId, Oid tempToastNamespaceId)
 
SearchPathMatcherGetSearchPathMatcher (MemoryContext context)
 
SearchPathMatcherCopySearchPathMatcher (SearchPathMatcher *path)
 
bool SearchPathMatchesCurrentEnvironment (SearchPathMatcher *path)
 
Oid get_collation_oid (List *collname, bool missing_ok)
 
Oid get_conversion_oid (List *conname, bool missing_ok)
 
Oid FindDefaultConversionProc (int32 for_encoding, int32 to_encoding)
 
static ListpreprocessNamespacePath (const char *searchPath, Oid roleid, bool *temp_missing)
 
static ListfinalNamespacePath (List *oidlist, Oid *firstNS)
 
static const SearchPathCacheEntrycachedNamespacePath (const char *searchPath, Oid roleid)
 
void AtEOXact_Namespace (bool isCommit, bool parallel)
 
void AtEOSubXact_Namespace (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
void ResetTempTableNamespace (void)
 
bool check_search_path (char **newval, void **extra, GucSource source)
 
void assign_search_path (const char *newval, void *extra)
 
void InitializeSearchPath (void)
 
Listfetch_search_path (bool includeImplicit)
 
int fetch_search_path_array (Oid *sarray, int sarray_len)
 
Datum pg_table_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_type_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_function_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_operator_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_opclass_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_opfamily_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_collation_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_conversion_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_statistics_obj_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_ts_parser_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_ts_dict_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_ts_template_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_ts_config_is_visible (PG_FUNCTION_ARGS)
 
Datum pg_my_temp_schema (PG_FUNCTION_ARGS)
 
Datum pg_is_other_temp_schema (PG_FUNCTION_ARGS)
 

Variables

static ListactiveSearchPath = NIL
 
static Oid activeCreationNamespace = InvalidOid
 
static bool activeTempCreationPending = false
 
static uint64 activePathGeneration = 1
 
static ListbaseSearchPath = NIL
 
static Oid baseCreationNamespace = InvalidOid
 
static bool baseTempCreationPending = false
 
static Oid namespaceUser = InvalidOid
 
static bool baseSearchPathValid = true
 
static bool searchPathCacheValid = false
 
static MemoryContext SearchPathCacheContext = NULL
 
static Oid myTempNamespace = InvalidOid
 
static Oid myTempToastNamespace = InvalidOid
 
static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId
 
char * namespace_search_path = NULL
 
static nsphash_hash * SearchPathCache = NULL
 
static SearchPathCacheEntryLastSearchPathCacheEntry = NULL
 

Macro Definition Documentation

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 287 of file namespace.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 288 of file namespace.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   SearchPathCacheEntry

Definition at line 281 of file namespace.c.

◆ SH_EQUAL

#define SH_EQUAL (   tb,
  a,
  b 
)    spcachekey_equal(a, b)

Definition at line 285 of file namespace.c.

◆ SH_HASH_KEY

#define SH_HASH_KEY (   tb,
  key 
)    spcachekey_hash(key)

Definition at line 284 of file namespace.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 283 of file namespace.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   SearchPathCacheKey

Definition at line 282 of file namespace.c.

◆ SH_PREFIX

#define SH_PREFIX   nsphash

Definition at line 280 of file namespace.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 286 of file namespace.c.

◆ SPACE_PER_OP

#define SPACE_PER_OP
Value:
MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
2 * sizeof(Oid))
#define MAXALIGN(LEN)
Definition: c.h:768
unsigned int Oid
Definition: postgres_ext.h:32

◆ SPCACHE_RESET_THRESHOLD

#define SPCACHE_RESET_THRESHOLD   256

Definition at line 297 of file namespace.c.

Typedef Documentation

◆ SearchPathCacheEntry

◆ SearchPathCacheKey

Function Documentation

◆ AccessTempTableNamespace()

static void AccessTempTableNamespace ( bool  force)
static

Definition at line 4362 of file namespace.c.

4363{
4364 /*
4365 * Make note that this temporary namespace has been accessed in this
4366 * transaction.
4367 */
4369
4370 /*
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.
4374 */
4375 if (!force && OidIsValid(myTempNamespace))
4376 return;
4377
4378 /*
4379 * The temporary tablespace does not exist yet and is wanted, so
4380 * initialize it.
4381 */
4383}
#define OidIsValid(objectId)
Definition: c.h:732
static Oid myTempNamespace
Definition: namespace.c:201
static void InitTempTableNamespace(void)
Definition: namespace.c:4390
int MyXactFlags
Definition: xact.c:135
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition: xact.h:102

References InitTempTableNamespace(), myTempNamespace, MyXactFlags, OidIsValid, and XACT_FLAGS_ACCESSEDTEMPNAMESPACE.

Referenced by fetch_search_path(), LookupCreationNamespace(), QualifiedNameGetCreationNamespace(), and RangeVarGetCreationNamespace().

◆ assign_search_path()

void assign_search_path ( const char *  newval,
void *  extra 
)

Definition at line 4713 of file namespace.c.

4714{
4715 /* don't access search_path during bootstrap */
4717
4718 /*
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.
4722 *
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.
4726 */
4727 baseSearchPathValid = false;
4728}
#define Assert(condition)
Definition: c.h:815
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
static bool baseSearchPathValid
Definition: namespace.c:158

References Assert, baseSearchPathValid, and IsBootstrapProcessingMode.

◆ AtEOSubXact_Namespace()

void AtEOSubXact_Namespace ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 4558 of file namespace.c.

4560{
4561
4562 if (myTempNamespaceSubID == mySubid)
4563 {
4564 if (isCommit)
4565 myTempNamespaceSubID = parentSubid;
4566 else
4567 {
4569 /* TEMP namespace creation failed, so reset state */
4572 baseSearchPathValid = false; /* need to rebuild list */
4573 searchPathCacheValid = false;
4574
4575 /*
4576 * Reset the temporary namespace flag in MyProc. We assume that
4577 * this operation is atomic.
4578 *
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.
4583 */
4585 }
4586 }
4587}
#define InvalidSubTransactionId
Definition: c.h:615
static bool searchPathCacheValid
Definition: namespace.c:164
static SubTransactionId myTempNamespaceSubID
Definition: namespace.c:205
static Oid myTempToastNamespace
Definition: namespace.c:203
#define InvalidOid
Definition: postgres_ext.h:37
PGPROC * MyProc
Definition: proc.c:66
Oid tempNamespaceId
Definition: proc.h:210

References baseSearchPathValid, InvalidOid, InvalidSubTransactionId, MyProc, myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, searchPathCacheValid, and PGPROC::tempNamespaceId.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_Namespace()

void AtEOXact_Namespace ( bool  isCommit,
bool  parallel 
)

Definition at line 4512 of file namespace.c.

4513{
4514 /*
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.)
4521 */
4523 {
4524 if (isCommit)
4526 else
4527 {
4530 baseSearchPathValid = false; /* need to rebuild list */
4531 searchPathCacheValid = false;
4532
4533 /*
4534 * Reset the temporary namespace flag in MyProc. We assume that
4535 * this operation is atomic.
4536 *
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.
4541 */
4543 }
4545 }
4546
4547}
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:337
static void RemoveTempRelationsCallback(int code, Datum arg)
Definition: namespace.c:4624

References baseSearchPathValid, before_shmem_exit(), InvalidOid, InvalidSubTransactionId, MyProc, myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, RemoveTempRelationsCallback(), searchPathCacheValid, and PGPROC::tempNamespaceId.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

◆ cachedNamespacePath()

static const SearchPathCacheEntry * cachedNamespacePath ( const char *  searchPath,
Oid  roleid 
)
static

Definition at line 4244 of file namespace.c.

4245{
4246 MemoryContext oldcxt;
4247 SearchPathCacheEntry *entry;
4248
4249 spcache_init();
4250
4251 entry = spcache_insert(searchPath, roleid);
4252
4253 /*
4254 * An OOM may have resulted in a cache entry with missing 'oidlist' or
4255 * 'finalPath', so just compute whatever is missing.
4256 */
4257
4258 if (entry->oidlist == NIL)
4259 {
4261 entry->oidlist = preprocessNamespacePath(searchPath, roleid,
4262 &entry->temp_missing);
4263 MemoryContextSwitchTo(oldcxt);
4264 }
4265
4266 /*
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
4270 * checks).
4271 */
4272 if (entry->finalPath == NIL || object_access_hook ||
4273 entry->forceRecompute)
4274 {
4275 list_free(entry->finalPath);
4276 entry->finalPath = NIL;
4277
4279 entry->finalPath = finalNamespacePath(entry->oidlist,
4280 &entry->firstNS);
4281 MemoryContextSwitchTo(oldcxt);
4282
4283 /*
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.
4288 */
4289 entry->forceRecompute = object_access_hook ? true : false;
4290 }
4291
4292 return entry;
4293}
return true
Definition: isn.c:125
void list_free(List *list)
Definition: list.c:1546
static MemoryContext SearchPathCacheContext
Definition: namespace.c:165
static SearchPathCacheEntry * spcache_insert(const char *searchPath, Oid roleid)
Definition: namespace.c:374
static List * preprocessNamespacePath(const char *searchPath, Oid roleid, bool *temp_missing)
Definition: namespace.c:4107
static void spcache_init(void)
Definition: namespace.c:306
static List * finalNamespacePath(List *oidlist, Oid *firstNS)
Definition: namespace.c:4198
object_access_hook_type object_access_hook
Definition: objectaccess.c:22
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define NIL
Definition: pg_list.h:68

References finalNamespacePath(), SearchPathCacheEntry::finalPath, SearchPathCacheEntry::firstNS, SearchPathCacheEntry::forceRecompute, list_free(), MemoryContextSwitchTo(), NIL, object_access_hook, SearchPathCacheEntry::oidlist, preprocessNamespacePath(), SearchPathCacheContext, spcache_init(), spcache_insert(), SearchPathCacheEntry::temp_missing, and true.

Referenced by recomputeNamespacePath().

◆ check_search_path()

bool check_search_path ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4657 of file namespace.c.

4658{
4659 Oid roleid = InvalidOid;
4660 const char *searchPath = *newval;
4661 char *rawname;
4662 List *namelist;
4663 bool use_cache = (SearchPathCacheContext != NULL);
4664
4665 /*
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.
4671 *
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.
4675 */
4676 if (use_cache)
4677 {
4678 spcache_init();
4679
4680 roleid = GetUserId();
4681
4682 if (spcache_lookup(searchPath, roleid) != NULL)
4683 return true;
4684 }
4685
4686 /*
4687 * Ensure validity check succeeds before creating cache entry.
4688 */
4689
4690 rawname = pstrdup(searchPath); /* need a modifiable copy */
4691
4692 /* Parse string into list of identifiers */
4693 if (!SplitIdentifierString(rawname, ',', &namelist))
4694 {
4695 /* syntax error in name list */
4696 GUC_check_errdetail("List syntax is invalid.");
4697 pfree(rawname);
4698 list_free(namelist);
4699 return false;
4700 }
4701 pfree(rawname);
4702 list_free(namelist);
4703
4704 /* OK to create empty cache entry */
4705 if (use_cache)
4706 (void) spcache_insert(searchPath, roleid);
4707
4708 return true;
4709}
#define newval
#define GUC_check_errdetail
Definition: guc.h:476
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
Oid GetUserId(void)
Definition: miscinit.c:517
static SearchPathCacheEntry * spcache_lookup(const char *searchPath, Oid roleid)
Definition: namespace.c:344
Definition: pg_list.h:54
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3432

References GetUserId(), GUC_check_errdetail, InvalidOid, list_free(), newval, pfree(), pstrdup(), SearchPathCacheContext, spcache_init(), spcache_insert(), spcache_lookup(), and SplitIdentifierString().

◆ CheckSetNamespace()

void CheckSetNamespace ( Oid  oldNspOid,
Oid  nspOid 
)

Definition at line 3459 of file namespace.c.

3460{
3461 /* disallow renaming into or out of temp schemas */
3462 if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
3463 ereport(ERROR,
3464 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3465 errmsg("cannot move objects into or out of temporary schemas")));
3466
3467 /* same for TOAST schema */
3468 if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
3469 ereport(ERROR,
3470 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3471 errmsg("cannot move objects into or out of TOAST schema")));
3472}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3687

References ereport, errcode(), errmsg(), ERROR, and isAnyTempNamespace().

Referenced by AlterObjectNamespace_internal(), AlterTableNamespace(), and AlterTypeNamespaceInternal().

◆ checkTempNamespaceStatus()

TempNamespaceStatus checkTempNamespaceStatus ( Oid  namespaceId)

Definition at line 3729 of file namespace.c.

3730{
3731 PGPROC *proc;
3732 ProcNumber procNumber;
3733
3735
3736 procNumber = GetTempNamespaceProcNumber(namespaceId);
3737
3738 /* No such namespace, or its name shows it's not temp? */
3739 if (procNumber == INVALID_PROC_NUMBER)
3741
3742 /* Is the backend alive? */
3743 proc = ProcNumberGetProc(procNumber);
3744 if (proc == NULL)
3745 return TEMP_NAMESPACE_IDLE;
3746
3747 /* Is the backend connected to the same database we are looking at? */
3748 if (proc->databaseId != MyDatabaseId)
3749 return TEMP_NAMESPACE_IDLE;
3750
3751 /* Does the backend own the temporary namespace? */
3752 if (proc->tempNamespaceId != namespaceId)
3753 return TEMP_NAMESPACE_IDLE;
3754
3755 /* Yup, so namespace is busy */
3756 return TEMP_NAMESPACE_IN_USE;
3757}
Oid MyDatabaseId
Definition: globals.c:93
ProcNumber GetTempNamespaceProcNumber(Oid namespaceId)
Definition: namespace.c:3766
@ TEMP_NAMESPACE_IN_USE
Definition: namespace.h:49
@ TEMP_NAMESPACE_NOT_TEMP
Definition: namespace.h:47
@ TEMP_NAMESPACE_IDLE
Definition: namespace.h:48
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
Definition: procarray.c:3138
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
int ProcNumber
Definition: procnumber.h:24
Definition: proc.h:162
Oid databaseId
Definition: proc.h:207

References Assert, PGPROC::databaseId, GetTempNamespaceProcNumber(), INVALID_PROC_NUMBER, MyDatabaseId, OidIsValid, ProcNumberGetProc(), TEMP_NAMESPACE_IDLE, TEMP_NAMESPACE_IN_USE, TEMP_NAMESPACE_NOT_TEMP, and PGPROC::tempNamespaceId.

Referenced by do_autovacuum().

◆ CollationGetCollid()

Oid CollationGetCollid ( const char *  collname)

Definition at line 2373 of file namespace.c.

2374{
2375 int32 dbencoding = GetDatabaseEncoding();
2376 ListCell *l;
2377
2379
2380 foreach(l, activeSearchPath)
2381 {
2382 Oid namespaceId = lfirst_oid(l);
2383 Oid collid;
2384
2385 if (namespaceId == myTempNamespace)
2386 continue; /* do not look in temp namespace */
2387
2388 collid = lookup_collation(collname, namespaceId, dbencoding);
2389 if (OidIsValid(collid))
2390 return collid;
2391 }
2392
2393 /* Not found in path */
2394 return InvalidOid;
2395}
int32_t int32
Definition: c.h:484
Oid collid
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
static Oid lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
Definition: namespace.c:2322
static List * activeSearchPath
Definition: namespace.c:136
static void recomputeNamespacePath(void)
Definition: namespace.c:4299
#define lfirst_oid(lc)
Definition: pg_list.h:174

References activeSearchPath, collid, GetDatabaseEncoding(), InvalidOid, lfirst_oid, lookup_collation(), myTempNamespace, OidIsValid, and recomputeNamespacePath().

Referenced by CollationIsVisibleExt().

◆ CollationIsVisible()

bool CollationIsVisible ( Oid  collid)

Definition at line 2407 of file namespace.c.

2408{
2409 return CollationIsVisibleExt(collid, NULL);
2410}
static bool CollationIsVisibleExt(Oid collid, bool *is_missing)
Definition: namespace.c:2419

References CollationIsVisibleExt(), and collid.

Referenced by generate_collation_name(), getObjectDescription(), and regcollationout().

◆ CollationIsVisibleExt()

static bool CollationIsVisibleExt ( Oid  collid,
bool *  is_missing 
)
static

Definition at line 2419 of file namespace.c.

2420{
2421 HeapTuple colltup;
2422 Form_pg_collation collform;
2423 Oid collnamespace;
2424 bool visible;
2425
2426 colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
2427 if (!HeapTupleIsValid(colltup))
2428 {
2429 if (is_missing != NULL)
2430 {
2431 *is_missing = true;
2432 return false;
2433 }
2434 elog(ERROR, "cache lookup failed for collation %u", collid);
2435 }
2436 collform = (Form_pg_collation) GETSTRUCT(colltup);
2437
2439
2440 /*
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.
2444 */
2445 collnamespace = collform->collnamespace;
2446 if (collnamespace != PG_CATALOG_NAMESPACE &&
2447 !list_member_oid(activeSearchPath, collnamespace))
2448 visible = false;
2449 else
2450 {
2451 /*
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.
2457 */
2458 char *collname = NameStr(collform->collname);
2459
2460 visible = (CollationGetCollid(collname) == collid);
2461 }
2462
2463 ReleaseSysCache(colltup);
2464
2465 return visible;
2466}
#define NameStr(name)
Definition: c.h:703
#define elog(elevel,...)
Definition: elog.h:225
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
Oid CollationGetCollid(const char *collname)
Definition: namespace.c:2373
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References activeSearchPath, CollationGetCollid(), collid, elog, ERROR, GETSTRUCT, HeapTupleIsValid, list_member_oid(), NameStr, ObjectIdGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), and SearchSysCache1().

Referenced by CollationIsVisible(), and pg_collation_is_visible().

◆ ConversionGetConid()

Oid ConversionGetConid ( const char *  conname)

Definition at line 2477 of file namespace.c.

2478{
2479 Oid conid;
2480 ListCell *l;
2481
2483
2484 foreach(l, activeSearchPath)
2485 {
2486 Oid namespaceId = lfirst_oid(l);
2487
2488 if (namespaceId == myTempNamespace)
2489 continue; /* do not look in temp namespace */
2490
2491 conid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
2492 PointerGetDatum(conname),
2493 ObjectIdGetDatum(namespaceId));
2494 if (OidIsValid(conid))
2495 return conid;
2496 }
2497
2498 /* Not found in path */
2499 return InvalidOid;
2500}
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:111

References activeSearchPath, GetSysCacheOid2, InvalidOid, lfirst_oid, myTempNamespace, ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by ConversionIsVisibleExt().

◆ ConversionIsVisible()

bool ConversionIsVisible ( Oid  conid)

Definition at line 2509 of file namespace.c.

2510{
2511 return ConversionIsVisibleExt(conid, NULL);
2512}
static bool ConversionIsVisibleExt(Oid conid, bool *is_missing)
Definition: namespace.c:2521

References ConversionIsVisibleExt().

Referenced by getObjectDescription().

◆ ConversionIsVisibleExt()

static bool ConversionIsVisibleExt ( Oid  conid,
bool *  is_missing 
)
static

Definition at line 2521 of file namespace.c.

2522{
2523 HeapTuple contup;
2524 Form_pg_conversion conform;
2525 Oid connamespace;
2526 bool visible;
2527
2528 contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
2529 if (!HeapTupleIsValid(contup))
2530 {
2531 if (is_missing != NULL)
2532 {
2533 *is_missing = true;
2534 return false;
2535 }
2536 elog(ERROR, "cache lookup failed for conversion %u", conid);
2537 }
2538 conform = (Form_pg_conversion) GETSTRUCT(contup);
2539
2541
2542 /*
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.
2546 */
2547 connamespace = conform->connamespace;
2548 if (connamespace != PG_CATALOG_NAMESPACE &&
2549 !list_member_oid(activeSearchPath, connamespace))
2550 visible = false;
2551 else
2552 {
2553 /*
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.
2558 */
2559 char *conname = NameStr(conform->conname);
2560
2561 visible = (ConversionGetConid(conname) == conid);
2562 }
2563
2564 ReleaseSysCache(contup);
2565
2566 return visible;
2567}
Oid ConversionGetConid(const char *conname)
Definition: namespace.c:2477
FormData_pg_conversion * Form_pg_conversion
Definition: pg_conversion.h:61

References activeSearchPath, ConversionGetConid(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, list_member_oid(), NameStr, ObjectIdGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), and SearchSysCache1().

Referenced by ConversionIsVisible(), and pg_conversion_is_visible().

◆ CopySearchPathMatcher()

SearchPathMatcher * CopySearchPathMatcher ( SearchPathMatcher path)

Definition at line 3889 of file namespace.c.

3890{
3891 SearchPathMatcher *result;
3892
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;
3898
3899 return result;
3900}
List * list_copy(const List *oldlist)
Definition: list.c:1573
void * palloc(Size size)
Definition: mcxt.c:1317
uint64 generation
Definition: namespace.h:64

References SearchPathMatcher::addCatalog, SearchPathMatcher::addTemp, SearchPathMatcher::generation, list_copy(), palloc(), and SearchPathMatcher::schemas.

Referenced by CopyCachedPlan().

◆ DeconstructQualifiedName()

void DeconstructQualifiedName ( const List names,
char **  nspname_p,
char **  objname_p 
)

Definition at line 3301 of file namespace.c.

3304{
3305 char *catalogname;
3306 char *schemaname = NULL;
3307 char *objname = NULL;
3308
3309 switch (list_length(names))
3310 {
3311 case 1:
3312 objname = strVal(linitial(names));
3313 break;
3314 case 2:
3315 schemaname = strVal(linitial(names));
3316 objname = strVal(lsecond(names));
3317 break;
3318 case 3:
3319 catalogname = strVal(linitial(names));
3320 schemaname = strVal(lsecond(names));
3321 objname = strVal(lthird(names));
3322
3323 /*
3324 * We check the catalog name and then ignore it.
3325 */
3326 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
3327 ereport(ERROR,
3328 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3329 errmsg("cross-database references are not implemented: %s",
3330 NameListToString(names))));
3331 break;
3332 default:
3333 ereport(ERROR,
3334 (errcode(ERRCODE_SYNTAX_ERROR),
3335 errmsg("improper qualified name (too many dotted names): %s",
3336 NameListToString(names))));
3337 break;
3338 }
3339
3340 *nspname_p = schemaname;
3341 *objname_p = objname;
3342}
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3187
char * NameListToString(const List *names)
Definition: namespace.c:3594
static int list_length(const List *l)
Definition: pg_list.h:152
#define lthird(l)
Definition: pg_list.h:188
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define strVal(v)
Definition: value.h:82

References ereport, errcode(), errmsg(), ERROR, get_database_name(), linitial, list_length(), lsecond, lthird, MyDatabaseId, NameListToString(), and strVal.

Referenced by AlterStatistics(), FuncnameGetCandidates(), get_collation_oid(), get_conversion_oid(), get_statistics_object_oid(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), LookupTypeNameExtended(), make_oper_cache_key(), OpClassCacheLookup(), OpernameGetCandidates(), OpernameGetOprid(), OpFamilyCacheLookup(), QualifiedNameGetCreationNamespace(), and ResolveOpClass().

◆ fetch_search_path()

List * fetch_search_path ( bool  includeImplicit)

Definition at line 4819 of file namespace.c.

4820{
4821 List *result;
4822
4824
4825 /*
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.
4831 */
4833 {
4836 }
4837
4838 result = list_copy(activeSearchPath);
4839 if (!includeImplicit)
4840 {
4841 while (result && linitial_oid(result) != activeCreationNamespace)
4842 result = list_delete_first(result);
4843 }
4844
4845 return result;
4846}
List * list_delete_first(List *list)
Definition: list.c:943
static Oid activeCreationNamespace
Definition: namespace.c:139
static bool activeTempCreationPending
Definition: namespace.c:142
static void AccessTempTableNamespace(bool force)
Definition: namespace.c:4362
#define linitial_oid(l)
Definition: pg_list.h:180

References AccessTempTableNamespace(), activeCreationNamespace, activeSearchPath, activeTempCreationPending, linitial_oid, list_copy(), list_delete_first(), and recomputeNamespacePath().

Referenced by AfterTriggerSetState(), CreateExtensionInternal(), current_schema(), current_schemas(), and ObjectsInPublicationToOids().

◆ fetch_search_path_array()

int fetch_search_path_array ( Oid sarray,
int  sarray_len 
)

Definition at line 4859 of file namespace.c.

4860{
4861 int count = 0;
4862 ListCell *l;
4863
4865
4866 foreach(l, activeSearchPath)
4867 {
4868 Oid namespaceId = lfirst_oid(l);
4869
4870 if (namespaceId == myTempNamespace)
4871 continue; /* do not include temp namespace */
4872
4873 if (count < sarray_len)
4874 sarray[count] = namespaceId;
4875 count++;
4876 }
4877
4878 return count;
4879}

References activeSearchPath, lfirst_oid, myTempNamespace, and recomputeNamespacePath().

Referenced by make_oper_cache_key().

◆ finalNamespacePath()

static List * finalNamespacePath ( List oidlist,
Oid firstNS 
)
static

Definition at line 4198 of file namespace.c.

4199{
4200 List *finalPath = NIL;
4201 ListCell *lc;
4202
4203 foreach(lc, oidlist)
4204 {
4205 Oid namespaceId = lfirst_oid(lc);
4206
4207 if (!list_member_oid(finalPath, namespaceId))
4208 {
4209 if (InvokeNamespaceSearchHook(namespaceId, false))
4210 finalPath = lappend_oid(finalPath, namespaceId);
4211 }
4212 }
4213
4214 /*
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.)
4218 */
4219 if (finalPath == NIL)
4220 *firstNS = InvalidOid;
4221 else
4222 *firstNS = linitial_oid(finalPath);
4223
4224 /*
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.
4228 */
4229 if (!list_member_oid(finalPath, PG_CATALOG_NAMESPACE))
4230 finalPath = lcons_oid(PG_CATALOG_NAMESPACE, finalPath);
4231
4233 !list_member_oid(finalPath, myTempNamespace))
4234 finalPath = lcons_oid(myTempNamespace, finalPath);
4235
4236 return finalPath;
4237}
List * lcons_oid(Oid datum, List *list)
Definition: list.c:531
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
#define InvokeNamespaceSearchHook(objectId, ereport_on_violation)
Definition: objectaccess.h:208

References InvalidOid, InvokeNamespaceSearchHook, lappend_oid(), lcons_oid(), lfirst_oid, linitial_oid, list_member_oid(), myTempNamespace, NIL, and OidIsValid.

Referenced by cachedNamespacePath().

◆ FindDefaultConversionProc()

Oid FindDefaultConversionProc ( int32  for_encoding,
int32  to_encoding 
)

Definition at line 4080 of file namespace.c.

4081{
4082 Oid proc;
4083 ListCell *l;
4084
4086
4087 foreach(l, activeSearchPath)
4088 {
4089 Oid namespaceId = lfirst_oid(l);
4090
4091 if (namespaceId == myTempNamespace)
4092 continue; /* do not look in temp namespace */
4093
4094 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
4095 if (OidIsValid(proc))
4096 return proc;
4097 }
4098
4099 /* Not found in path */
4100 return InvalidOid;
4101}
Oid FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)

References activeSearchPath, FindDefaultConversion(), InvalidOid, lfirst_oid, myTempNamespace, OidIsValid, and recomputeNamespacePath().

Referenced by BeginCopyFrom(), InitializeClientEncoding(), pg_do_encoding_conversion(), PrepareClientEncoding(), and test_enc_conversion().

◆ FuncnameGetCandidates()

FuncCandidateList FuncnameGetCandidates ( List names,
int  nargs,
List argnames,
bool  expand_variadic,
bool  expand_defaults,
bool  include_out_arguments,
bool  missing_ok 
)

Definition at line 1192 of file namespace.c.

1195{
1196 FuncCandidateList resultList = NULL;
1197 bool any_special = false;
1198 char *schemaname;
1199 char *funcname;
1200 Oid namespaceId;
1201 CatCList *catlist;
1202 int i;
1203
1204 /* check for caller error */
1205 Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
1206
1207 /* deconstruct the name list */
1208 DeconstructQualifiedName(names, &schemaname, &funcname);
1209
1210 if (schemaname)
1211 {
1212 /* use exact schema given */
1213 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
1214 if (!OidIsValid(namespaceId))
1215 return NULL;
1216 }
1217 else
1218 {
1219 /* flag to indicate we need namespace search */
1220 namespaceId = InvalidOid;
1222 }
1223
1224 /* Search syscache by name only */
1225 catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname));
1226
1227 for (i = 0; i < catlist->n_members; i++)
1228 {
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;
1234 int pathpos = 0;
1235 bool variadic;
1236 bool use_defaults;
1237 Oid va_elem_type;
1238 int *argnumbers = NULL;
1239 FuncCandidateList newResult;
1240
1241 if (OidIsValid(namespaceId))
1242 {
1243 /* Consider only procs in specified namespace */
1244 if (procform->pronamespace != namespaceId)
1245 continue;
1246 }
1247 else
1248 {
1249 /*
1250 * Consider only procs that are in the search path and are not in
1251 * the temp namespace.
1252 */
1253 ListCell *nsp;
1254
1255 foreach(nsp, activeSearchPath)
1256 {
1257 if (procform->pronamespace == lfirst_oid(nsp) &&
1258 procform->pronamespace != myTempNamespace)
1259 break;
1260 pathpos++;
1261 }
1262 if (nsp == NULL)
1263 continue; /* proc is not in search path */
1264 }
1265
1266 /*
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.
1271 */
1272 if (include_out_arguments)
1273 {
1274 Datum proallargtypes;
1275 bool isNull;
1276
1277 proallargtypes = SysCacheGetAttr(PROCNAMEARGSNSP, proctup,
1278 Anum_pg_proc_proallargtypes,
1279 &isNull);
1280 if (!isNull)
1281 {
1282 ArrayType *arr = DatumGetArrayTypeP(proallargtypes);
1283
1284 pronargs = ARR_DIMS(arr)[0];
1285 if (ARR_NDIM(arr) != 1 ||
1286 pronargs < 0 ||
1287 ARR_HASNULL(arr) ||
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);
1292 }
1293 }
1294
1295 if (argnames != NIL)
1296 {
1297 /*
1298 * Call uses named or mixed notation
1299 *
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.
1303 */
1304 if (OidIsValid(procform->provariadic) && expand_variadic)
1305 continue;
1306 va_elem_type = InvalidOid;
1307 variadic = false;
1308
1309 /*
1310 * Check argument count.
1311 */
1312 Assert(nargs >= 0); /* -1 not supported with argnames */
1313
1314 if (pronargs > nargs && expand_defaults)
1315 {
1316 /* Ignore if not enough default expressions */
1317 if (nargs + procform->pronargdefaults < pronargs)
1318 continue;
1319 use_defaults = true;
1320 }
1321 else
1322 use_defaults = false;
1323
1324 /* Ignore if it doesn't match requested argument count */
1325 if (pronargs != nargs && !use_defaults)
1326 continue;
1327
1328 /* Check for argument name match, generate positional mapping */
1329 if (!MatchNamedCall(proctup, nargs, argnames,
1330 include_out_arguments, pronargs,
1331 &argnumbers))
1332 continue;
1333
1334 /* Named argument matching is always "special" */
1335 any_special = true;
1336 }
1337 else
1338 {
1339 /*
1340 * Call uses positional notation
1341 *
1342 * Check if function is variadic, and get variadic element type if
1343 * so. If expand_variadic is false, we should just ignore
1344 * variadic-ness.
1345 */
1346 if (pronargs <= nargs && expand_variadic)
1347 {
1348 va_elem_type = procform->provariadic;
1349 variadic = OidIsValid(va_elem_type);
1350 any_special |= variadic;
1351 }
1352 else
1353 {
1354 va_elem_type = InvalidOid;
1355 variadic = false;
1356 }
1357
1358 /*
1359 * Check if function can match by using parameter defaults.
1360 */
1361 if (pronargs > nargs && expand_defaults)
1362 {
1363 /* Ignore if not enough default expressions */
1364 if (nargs + procform->pronargdefaults < pronargs)
1365 continue;
1366 use_defaults = true;
1367 any_special = true;
1368 }
1369 else
1370 use_defaults = false;
1371
1372 /* Ignore if it doesn't match requested argument count */
1373 if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
1374 continue;
1375 }
1376
1377 /*
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.
1382 */
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;
1392 if (argnumbers)
1393 {
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]];
1397 }
1398 else
1399 {
1400 /* Simple positional case, just copy proargtypes as-is */
1401 memcpy(newResult->args, proargtypes, pronargs * sizeof(Oid));
1402 }
1403 if (variadic)
1404 {
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;
1409 }
1410 else
1411 newResult->nvargs = 0;
1412 newResult->ndargs = use_defaults ? pronargs - nargs : 0;
1413
1414 /*
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.
1421 */
1422 if (resultList != NULL &&
1423 (any_special || !OidIsValid(namespaceId)))
1424 {
1425 /*
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.
1433 *
1434 * We ignore defaulted arguments in deciding what is a match.
1435 */
1436 FuncCandidateList prevResult;
1437
1438 if (catlist->ordered && !any_special)
1439 {
1440 /* ndargs must be 0 if !any_special */
1441 if (effective_nargs == resultList->nargs &&
1442 memcmp(newResult->args,
1443 resultList->args,
1444 effective_nargs * sizeof(Oid)) == 0)
1445 prevResult = resultList;
1446 else
1447 prevResult = NULL;
1448 }
1449 else
1450 {
1451 int cmp_nargs = newResult->nargs - newResult->ndargs;
1452
1453 for (prevResult = resultList;
1454 prevResult;
1455 prevResult = prevResult->next)
1456 {
1457 if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
1458 memcmp(newResult->args,
1459 prevResult->args,
1460 cmp_nargs * sizeof(Oid)) == 0)
1461 break;
1462 }
1463 }
1464
1465 if (prevResult)
1466 {
1467 /*
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
1472 * ambiguous.
1473 */
1474 int preference;
1475
1476 if (pathpos != prevResult->pathpos)
1477 {
1478 /*
1479 * Prefer the one that's earlier in the search path.
1480 */
1481 preference = pathpos - prevResult->pathpos;
1482 }
1483 else if (variadic && prevResult->nvargs == 0)
1484 {
1485 /*
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.
1490 */
1491 preference = 1;
1492 }
1493 else if (!variadic && prevResult->nvargs > 0)
1494 {
1495 preference = -1;
1496 }
1497 else
1498 {
1499 /*----------
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.
1506 *----------
1507 */
1508 preference = 0;
1509 }
1510
1511 if (preference > 0)
1512 {
1513 /* keep previous result */
1514 pfree(newResult);
1515 continue;
1516 }
1517 else if (preference < 0)
1518 {
1519 /* remove previous result from the list */
1520 if (prevResult == resultList)
1521 resultList = prevResult->next;
1522 else
1523 {
1524 FuncCandidateList prevPrevResult;
1525
1526 for (prevPrevResult = resultList;
1527 prevPrevResult;
1528 prevPrevResult = prevPrevResult->next)
1529 {
1530 if (prevResult == prevPrevResult->next)
1531 {
1532 prevPrevResult->next = prevResult->next;
1533 break;
1534 }
1535 }
1536 Assert(prevPrevResult); /* assert we found it */
1537 }
1538 pfree(prevResult);
1539 /* fall through to add newResult to list */
1540 }
1541 else
1542 {
1543 /* mark old result as ambiguous, discard new */
1544 prevResult->oid = InvalidOid;
1545 pfree(newResult);
1546 continue;
1547 }
1548 }
1549 }
1550
1551 /*
1552 * Okay to add it to result list
1553 */
1554 newResult->next = resultList;
1555 resultList = newResult;
1556 }
1557
1558 ReleaseSysCacheList(catlist);
1559
1560 return resultList;
1561}
#define ARR_NDIM(a)
Definition: array.h:290
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_HASNULL(a)
Definition: array.h:291
#define Max(x, y)
Definition: c.h:955
#define funcname
Definition: indent_codes.h:69
int j
Definition: isn.c:73
int i
Definition: isn.c:72
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:3385
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:3301
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, bool include_out_arguments, int pronargs, int **argnumbers)
Definition: namespace.c:1585
struct _FuncCandidateList * FuncCandidateList
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
int16 pronargs
Definition: pg_proc.h:81
uintptr_t Datum
Definition: postgres.h:69
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
struct _FuncCandidateList * next
Definition: namespace.h:31
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition: namespace.h:39
bool ordered
Definition: catcache.h:176
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:180
int n_members
Definition: catcache.h:178
HeapTupleData tuple
Definition: catcache.h:123
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
#define ReleaseSysCacheList(x)
Definition: syscache.h:134
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:127

References activeSearchPath, _FuncCandidateList::argnumbers, generate_unaccent_rules::args, _FuncCandidateList::args, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, Assert, CStringGetDatum(), DatumGetArrayTypeP, DeconstructQualifiedName(), elog, ERROR, funcname, GETSTRUCT, i, InvalidOid, j, lfirst_oid, LookupExplicitNamespace(), MatchNamedCall(), Max, catclist::members, myTempNamespace, catclist::n_members, _FuncCandidateList::nargs, _FuncCandidateList::ndargs, _FuncCandidateList::next, NIL, _FuncCandidateList::nominalnargs, _FuncCandidateList::nvargs, _FuncCandidateList::oid, OidIsValid, catclist::ordered, palloc(), _FuncCandidateList::pathpos, pfree(), pronargs, recomputeNamespacePath(), ReleaseSysCacheList, SearchSysCacheList1, SysCacheGetAttr(), and catctup::tuple.

Referenced by func_get_detail(), FunctionIsVisibleExt(), LookupFuncNameInternal(), regprocedurein(), regprocin(), and regprocout().

◆ FunctionIsVisible()

bool FunctionIsVisible ( Oid  funcid)

Definition at line 1696 of file namespace.c.

1697{
1698 return FunctionIsVisibleExt(funcid, NULL);
1699}
static bool FunctionIsVisibleExt(Oid funcid, bool *is_missing)
Definition: namespace.c:1708

References FunctionIsVisibleExt().

Referenced by format_procedure_extended().

◆ FunctionIsVisibleExt()

static bool FunctionIsVisibleExt ( Oid  funcid,
bool *  is_missing 
)
static

Definition at line 1708 of file namespace.c.

1709{
1710 HeapTuple proctup;
1711 Form_pg_proc procform;
1712 Oid pronamespace;
1713 bool visible;
1714
1715 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1716 if (!HeapTupleIsValid(proctup))
1717 {
1718 if (is_missing != NULL)
1719 {
1720 *is_missing = true;
1721 return false;
1722 }
1723 elog(ERROR, "cache lookup failed for function %u", funcid);
1724 }
1725 procform = (Form_pg_proc) GETSTRUCT(proctup);
1726
1728
1729 /*
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.
1733 */
1734 pronamespace = procform->pronamespace;
1735 if (pronamespace != PG_CATALOG_NAMESPACE &&
1736 !list_member_oid(activeSearchPath, pronamespace))
1737 visible = false;
1738 else
1739 {
1740 /*
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.
1745 */
1746 char *proname = NameStr(procform->proname);
1747 int nargs = procform->pronargs;
1748 FuncCandidateList clist;
1749
1750 visible = false;
1751
1753 nargs, NIL, false, false, false, false);
1754
1755 for (; clist; clist = clist->next)
1756 {
1757 if (memcmp(clist->args, procform->proargtypes.values,
1758 nargs * sizeof(Oid)) == 0)
1759 {
1760 /* Found the expected entry; is it the right proc? */
1761 visible = (clist->oid == funcid);
1762 break;
1763 }
1764 }
1765 }
1766
1767 ReleaseSysCache(proctup);
1768
1769 return visible;
1770}
FuncCandidateList FuncnameGetCandidates(List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool include_out_arguments, bool missing_ok)
Definition: namespace.c:1192
#define list_make1(x1)
Definition: pg_list.h:212
NameData proname
Definition: pg_proc.h:35
String * makeString(char *str)
Definition: value.c:63

References activeSearchPath, _FuncCandidateList::args, elog, ERROR, FuncnameGetCandidates(), GETSTRUCT, HeapTupleIsValid, list_make1, list_member_oid(), makeString(), NameStr, _FuncCandidateList::next, NIL, ObjectIdGetDatum(), _FuncCandidateList::oid, proname, recomputeNamespacePath(), ReleaseSysCache(), and SearchSysCache1().

Referenced by FunctionIsVisible(), and pg_function_is_visible().

◆ get_collation_oid()

Oid get_collation_oid ( List collname,
bool  missing_ok 
)

Definition at line 3971 of file namespace.c.

3972{
3973 char *schemaname;
3974 char *collation_name;
3975 int32 dbencoding = GetDatabaseEncoding();
3976 Oid namespaceId;
3977 Oid colloid;
3978 ListCell *l;
3979
3980 /* deconstruct the name list */
3981 DeconstructQualifiedName(collname, &schemaname, &collation_name);
3982
3983 if (schemaname)
3984 {
3985 /* use exact schema given */
3986 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3987 if (missing_ok && !OidIsValid(namespaceId))
3988 return InvalidOid;
3989
3990 colloid = lookup_collation(collation_name, namespaceId, dbencoding);
3991 if (OidIsValid(colloid))
3992 return colloid;
3993 }
3994 else
3995 {
3996 /* search for it in search path */
3998
3999 foreach(l, activeSearchPath)
4000 {
4001 namespaceId = lfirst_oid(l);
4002
4003 if (namespaceId == myTempNamespace)
4004 continue; /* do not look in temp namespace */
4005
4006 colloid = lookup_collation(collation_name, namespaceId, dbencoding);
4007 if (OidIsValid(colloid))
4008 return colloid;
4009 }
4010 }
4011
4012 /* Not found in path */
4013 if (!missing_ok)
4014 ereport(ERROR,
4015 (errcode(ERRCODE_UNDEFINED_OBJECT),
4016 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
4018 return InvalidOid;
4019}
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetDatabaseEncoding(), GetDatabaseEncodingName(), InvalidOid, lfirst_oid, lookup_collation(), LookupExplicitNamespace(), myTempNamespace, NameListToString(), OidIsValid, and recomputeNamespacePath().

Referenced by AlterCollation(), ComputeIndexAttrs(), ComputePartitionAttrs(), DefineCollation(), DefineDomain(), DefineRange(), get_object_address(), LookupCollation(), and regcollationin().

◆ get_conversion_oid()

Oid get_conversion_oid ( List conname,
bool  missing_ok 
)

Definition at line 4025 of file namespace.c.

4026{
4027 char *schemaname;
4028 char *conversion_name;
4029 Oid namespaceId;
4030 Oid conoid = InvalidOid;
4031 ListCell *l;
4032
4033 /* deconstruct the name list */
4034 DeconstructQualifiedName(conname, &schemaname, &conversion_name);
4035
4036 if (schemaname)
4037 {
4038 /* use exact schema given */
4039 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
4040 if (missing_ok && !OidIsValid(namespaceId))
4041 conoid = InvalidOid;
4042 else
4043 conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
4044 PointerGetDatum(conversion_name),
4045 ObjectIdGetDatum(namespaceId));
4046 }
4047 else
4048 {
4049 /* search for it in search path */
4051
4052 foreach(l, activeSearchPath)
4053 {
4054 namespaceId = lfirst_oid(l);
4055
4056 if (namespaceId == myTempNamespace)
4057 continue; /* do not look in temp namespace */
4058
4059 conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
4060 PointerGetDatum(conversion_name),
4061 ObjectIdGetDatum(namespaceId));
4062 if (OidIsValid(conoid))
4063 return conoid;
4064 }
4065 }
4066
4067 /* Not found in path */
4068 if (!OidIsValid(conoid) && !missing_ok)
4069 ereport(ERROR,
4070 (errcode(ERRCODE_UNDEFINED_OBJECT),
4071 errmsg("conversion \"%s\" does not exist",
4072 NameListToString(conname))));
4073 return conoid;
4074}

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, InvalidOid, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by get_object_address().

◆ get_namespace_oid()

Oid get_namespace_oid ( const char *  nspname,
bool  missing_ok 
)

◆ get_statistics_object_oid()

Oid get_statistics_object_oid ( List names,
bool  missing_ok 
)

Definition at line 2575 of file namespace.c.

2576{
2577 char *schemaname;
2578 char *stats_name;
2579 Oid namespaceId;
2580 Oid stats_oid = InvalidOid;
2581 ListCell *l;
2582
2583 /* deconstruct the name list */
2584 DeconstructQualifiedName(names, &schemaname, &stats_name);
2585
2586 if (schemaname)
2587 {
2588 /* use exact schema given */
2589 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2590 if (missing_ok && !OidIsValid(namespaceId))
2591 stats_oid = InvalidOid;
2592 else
2593 stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2594 PointerGetDatum(stats_name),
2595 ObjectIdGetDatum(namespaceId));
2596 }
2597 else
2598 {
2599 /* search for it in search path */
2601
2602 foreach(l, activeSearchPath)
2603 {
2604 namespaceId = lfirst_oid(l);
2605
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))
2612 break;
2613 }
2614 }
2615
2616 if (!OidIsValid(stats_oid) && !missing_ok)
2617 ereport(ERROR,
2618 (errcode(ERRCODE_UNDEFINED_OBJECT),
2619 errmsg("statistics object \"%s\" does not exist",
2620 NameListToString(names))));
2621
2622 return stats_oid;
2623}

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, InvalidOid, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by AlterStatistics(), and get_object_address().

◆ get_ts_config_oid()

Oid get_ts_config_oid ( List names,
bool  missing_ok 
)

Definition at line 3152 of file namespace.c.

3153{
3154 char *schemaname;
3155 char *config_name;
3156 Oid namespaceId;
3157 Oid cfgoid = InvalidOid;
3158 ListCell *l;
3159
3160 /* deconstruct the name list */
3161 DeconstructQualifiedName(names, &schemaname, &config_name);
3162
3163 if (schemaname)
3164 {
3165 /* use exact schema given */
3166 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3167 if (missing_ok && !OidIsValid(namespaceId))
3168 cfgoid = InvalidOid;
3169 else
3170 cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
3171 PointerGetDatum(config_name),
3172 ObjectIdGetDatum(namespaceId));
3173 }
3174 else
3175 {
3176 /* search for it in search path */
3178
3179 foreach(l, activeSearchPath)
3180 {
3181 namespaceId = lfirst_oid(l);
3182
3183 if (namespaceId == myTempNamespace)
3184 continue; /* do not look in temp namespace */
3185
3186 cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
3187 PointerGetDatum(config_name),
3188 ObjectIdGetDatum(namespaceId));
3189 if (OidIsValid(cfgoid))
3190 break;
3191 }
3192 }
3193
3194 if (!OidIsValid(cfgoid) && !missing_ok)
3195 ereport(ERROR,
3196 (errcode(ERRCODE_UNDEFINED_OBJECT),
3197 errmsg("text search configuration \"%s\" does not exist",
3198 NameListToString(names))));
3199
3200 return cfgoid;
3201}

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, InvalidOid, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by check_default_text_search_config(), DefineTSConfiguration(), get_object_address(), GetTSConfigTuple(), getTSCurrentConfig(), regconfigin(), and tsvector_update_trigger().

◆ get_ts_dict_oid()

Oid get_ts_dict_oid ( List names,
bool  missing_ok 
)

Definition at line 2861 of file namespace.c.

2862{
2863 char *schemaname;
2864 char *dict_name;
2865 Oid namespaceId;
2866 Oid dictoid = InvalidOid;
2867 ListCell *l;
2868
2869 /* deconstruct the name list */
2870 DeconstructQualifiedName(names, &schemaname, &dict_name);
2871
2872 if (schemaname)
2873 {
2874 /* use exact schema given */
2875 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2876 if (missing_ok && !OidIsValid(namespaceId))
2877 dictoid = InvalidOid;
2878 else
2879 dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2880 PointerGetDatum(dict_name),
2881 ObjectIdGetDatum(namespaceId));
2882 }
2883 else
2884 {
2885 /* search for it in search path */
2887
2888 foreach(l, activeSearchPath)
2889 {
2890 namespaceId = lfirst_oid(l);
2891
2892 if (namespaceId == myTempNamespace)
2893 continue; /* do not look in temp namespace */
2894
2895 dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2896 PointerGetDatum(dict_name),
2897 ObjectIdGetDatum(namespaceId));
2898 if (OidIsValid(dictoid))
2899 break;
2900 }
2901 }
2902
2903 if (!OidIsValid(dictoid) && !missing_ok)
2904 ereport(ERROR,
2905 (errcode(ERRCODE_UNDEFINED_OBJECT),
2906 errmsg("text search dictionary \"%s\" does not exist",
2907 NameListToString(names))));
2908
2909 return dictoid;
2910}

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, InvalidOid, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by AlterTSDictionary(), get_object_address(), MakeConfigurationMapping(), regdictionaryin(), and thesaurus_init().

◆ get_ts_parser_oid()

Oid get_ts_parser_oid ( List names,
bool  missing_ok 
)

Definition at line 2716 of file namespace.c.

2717{
2718 char *schemaname;
2719 char *parser_name;
2720 Oid namespaceId;
2721 Oid prsoid = InvalidOid;
2722 ListCell *l;
2723
2724 /* deconstruct the name list */
2725 DeconstructQualifiedName(names, &schemaname, &parser_name);
2726
2727 if (schemaname)
2728 {
2729 /* use exact schema given */
2730 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2731 if (missing_ok && !OidIsValid(namespaceId))
2732 prsoid = InvalidOid;
2733 else
2734 prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2735 PointerGetDatum(parser_name),
2736 ObjectIdGetDatum(namespaceId));
2737 }
2738 else
2739 {
2740 /* search for it in search path */
2742
2743 foreach(l, activeSearchPath)
2744 {
2745 namespaceId = lfirst_oid(l);
2746
2747 if (namespaceId == myTempNamespace)
2748 continue; /* do not look in temp namespace */
2749
2750 prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2751 PointerGetDatum(parser_name),
2752 ObjectIdGetDatum(namespaceId));
2753 if (OidIsValid(prsoid))
2754 break;
2755 }
2756 }
2757
2758 if (!OidIsValid(prsoid) && !missing_ok)
2759 ereport(ERROR,
2760 (errcode(ERRCODE_UNDEFINED_OBJECT),
2761 errmsg("text search parser \"%s\" does not exist",
2762 NameListToString(names))));
2763
2764 return prsoid;
2765}

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, InvalidOid, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by DefineTSConfiguration(), get_object_address(), ts_parse_byname(), and ts_token_type_byname().

◆ get_ts_template_oid()

Oid get_ts_template_oid ( List names,
bool  missing_ok 
)

Definition at line 3007 of file namespace.c.

3008{
3009 char *schemaname;
3010 char *template_name;
3011 Oid namespaceId;
3012 Oid tmploid = InvalidOid;
3013 ListCell *l;
3014
3015 /* deconstruct the name list */
3016 DeconstructQualifiedName(names, &schemaname, &template_name);
3017
3018 if (schemaname)
3019 {
3020 /* use exact schema given */
3021 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3022 if (missing_ok && !OidIsValid(namespaceId))
3023 tmploid = InvalidOid;
3024 else
3025 tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
3026 PointerGetDatum(template_name),
3027 ObjectIdGetDatum(namespaceId));
3028 }
3029 else
3030 {
3031 /* search for it in search path */
3033
3034 foreach(l, activeSearchPath)
3035 {
3036 namespaceId = lfirst_oid(l);
3037
3038 if (namespaceId == myTempNamespace)
3039 continue; /* do not look in temp namespace */
3040
3041 tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
3042 PointerGetDatum(template_name),
3043 ObjectIdGetDatum(namespaceId));
3044 if (OidIsValid(tmploid))
3045 break;
3046 }
3047 }
3048
3049 if (!OidIsValid(tmploid) && !missing_ok)
3050 ereport(ERROR,
3051 (errcode(ERRCODE_UNDEFINED_OBJECT),
3052 errmsg("text search template \"%s\" does not exist",
3053 NameListToString(names))));
3054
3055 return tmploid;
3056}

References activeSearchPath, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, InvalidOid, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by DefineTSDictionary(), and get_object_address().

◆ GetSearchPathMatcher()

SearchPathMatcher * GetSearchPathMatcher ( MemoryContext  context)

Definition at line 3852 of file namespace.c.

3853{
3854 SearchPathMatcher *result;
3855 List *schemas;
3856 MemoryContext oldcxt;
3857
3859
3860 oldcxt = MemoryContextSwitchTo(context);
3861
3862 result = (SearchPathMatcher *) palloc0(sizeof(SearchPathMatcher));
3863 schemas = list_copy(activeSearchPath);
3864 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
3865 {
3866 if (linitial_oid(schemas) == myTempNamespace)
3867 result->addTemp = true;
3868 else
3869 {
3870 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
3871 result->addCatalog = true;
3872 }
3873 schemas = list_delete_first(schemas);
3874 }
3875 result->schemas = schemas;
3877
3878 MemoryContextSwitchTo(oldcxt);
3879
3880 return result;
3881}
void * palloc0(Size size)
Definition: mcxt.c:1347
static uint64 activePathGeneration
Definition: namespace.c:145

References activeCreationNamespace, activePathGeneration, activeSearchPath, SearchPathMatcher::addCatalog, SearchPathMatcher::addTemp, Assert, SearchPathMatcher::generation, linitial_oid, list_copy(), list_delete_first(), MemoryContextSwitchTo(), myTempNamespace, palloc0(), recomputeNamespacePath(), and SearchPathMatcher::schemas.

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

◆ GetTempNamespaceProcNumber()

ProcNumber GetTempNamespaceProcNumber ( Oid  namespaceId)

Definition at line 3766 of file namespace.c.

3767{
3768 int result;
3769 char *nspname;
3770
3771 /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3772 nspname = get_namespace_name(namespaceId);
3773 if (!nspname)
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);
3779 else
3780 result = INVALID_PROC_NUMBER;
3781 pfree(nspname);
3782 return result;
3783}
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366

References get_namespace_name(), INVALID_PROC_NUMBER, and pfree().

Referenced by checkTempNamespaceStatus(), pg_relation_filepath(), and RelationBuildDesc().

◆ GetTempNamespaceState()

void GetTempNamespaceState ( Oid tempNamespaceId,
Oid tempToastNamespaceId 
)

Definition at line 3805 of file namespace.c.

3806{
3807 /* Return namespace OIDs, or 0 if session has not created temp namespace */
3808 *tempNamespaceId = myTempNamespace;
3809 *tempToastNamespaceId = myTempToastNamespace;
3810}

References myTempNamespace, and myTempToastNamespace.

Referenced by InitializeParallelDSM().

◆ GetTempToastNamespace()

Oid GetTempToastNamespace ( void  )

Definition at line 3791 of file namespace.c.

3792{
3794 return myTempToastNamespace;
3795}

References Assert, myTempToastNamespace, and OidIsValid.

Referenced by create_toast_table().

◆ InitializeSearchPath()

void InitializeSearchPath ( void  )

Definition at line 4736 of file namespace.c.

4737{
4739 {
4740 /*
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.
4743 */
4744 MemoryContext oldcxt;
4745
4747 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
4748 MemoryContextSwitchTo(oldcxt);
4749 baseCreationNamespace = PG_CATALOG_NAMESPACE;
4751 baseSearchPathValid = true;
4756 activePathGeneration++; /* pro forma */
4757 }
4758 else
4759 {
4760 /*
4761 * In normal mode, arrange for a callback on any syscache invalidation
4762 * that will affect the search_path cache.
4763 */
4764
4765 /* namespace name or ACLs may have changed */
4766 CacheRegisterSyscacheCallback(NAMESPACEOID,
4768 (Datum) 0);
4769
4770 /* role name may affect the meaning of "$user" */
4773 (Datum) 0);
4774
4775 /* role membership may affect ACLs */
4776 CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
4778 (Datum) 0);
4779
4780 /* database owner may affect ACLs */
4783 (Datum) 0);
4784
4785 /* Force search path to be recomputed on next use */
4786 baseSearchPathValid = false;
4787 searchPathCacheValid = false;
4788 }
4789}
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1704
MemoryContext TopMemoryContext
Definition: mcxt.c:149
static bool baseTempCreationPending
Definition: namespace.c:153
static Oid baseCreationNamespace
Definition: namespace.c:151
static Oid namespaceUser
Definition: namespace.c:155
static void InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: namespace.c:4796
static List * baseSearchPath
Definition: namespace.c:149
#define list_make1_oid(x1)
Definition: pg_list.h:242

References activeCreationNamespace, activePathGeneration, activeSearchPath, activeTempCreationPending, baseCreationNamespace, baseSearchPath, baseSearchPathValid, baseTempCreationPending, CacheRegisterSyscacheCallback(), GetUserId(), InvalidationCallback(), IsBootstrapProcessingMode, list_make1_oid, MemoryContextSwitchTo(), namespaceUser, searchPathCacheValid, and TopMemoryContext.

Referenced by InitPostgres().

◆ InitTempTableNamespace()

static void InitTempTableNamespace ( void  )
static

Definition at line 4390 of file namespace.c.

4391{
4392 char namespaceName[NAMEDATALEN];
4393 Oid namespaceId;
4394 Oid toastspaceId;
4395
4397
4398 /*
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.
4402 *
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.
4407 */
4408 if (object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
4410 ereport(ERROR,
4411 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4412 errmsg("permission denied to create temporary tables in database \"%s\"",
4414
4415 /*
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.
4424 */
4425 if (RecoveryInProgress())
4426 ereport(ERROR,
4427 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
4428 errmsg("cannot create temporary tables during recovery")));
4429
4430 /* Parallel workers can't create temporary tables, either. */
4431 if (IsParallelWorker())
4432 ereport(ERROR,
4433 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
4434 errmsg("cannot create temporary tables during a parallel operation")));
4435
4436 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyProcNumber);
4437
4438 namespaceId = get_namespace_oid(namespaceName, true);
4439 if (!OidIsValid(namespaceId))
4440 {
4441 /*
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.
4448 */
4449 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4450 true);
4451 /* Advance command counter to make namespace visible */
4453 }
4454 else
4455 {
4456 /*
4457 * If the namespace already exists, clean it out (in case the former
4458 * owner crashed without doing so).
4459 */
4460 RemoveTempRelations(namespaceId);
4461 }
4462
4463 /*
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.)
4467 */
4468 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
4469 MyProcNumber);
4470
4471 toastspaceId = get_namespace_oid(namespaceName, true);
4472 if (!OidIsValid(toastspaceId))
4473 {
4474 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4475 true);
4476 /* Advance command counter to make namespace visible */
4478 }
4479
4480 /*
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.
4484 */
4485 myTempNamespace = namespaceId;
4486 myTempToastNamespace = toastspaceId;
4487
4488 /*
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.
4497 */
4498 MyProc->tempNamespaceId = namespaceId;
4499
4500 /* It should not be done already. */
4503
4504 baseSearchPathValid = false; /* need to rebuild list */
4505 searchPathCacheValid = false;
4506}
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3804
ProcNumber MyProcNumber
Definition: globals.c:89
#define IsParallelWorker()
Definition: parallel.h:60
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3535
static void RemoveTempRelations(Oid tempNamespaceId)
Definition: namespace.c:4598
#define ACL_CREATE_TEMP
Definition: parsenodes.h:86
#define NAMEDATALEN
Oid NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
Definition: pg_namespace.c:43
#define snprintf
Definition: port.h:238
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:790
void CommandCounterIncrement(void)
Definition: xact.c:1099
bool RecoveryInProgress(void)
Definition: xlog.c:6334

References ACL_CREATE_TEMP, ACLCHECK_OK, Assert, baseSearchPathValid, CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, get_database_name(), get_namespace_oid(), GetCurrentSubTransactionId(), GetUserId(), InvalidSubTransactionId, IsParallelWorker, MyDatabaseId, MyProc, MyProcNumber, myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, NAMEDATALEN, NamespaceCreate(), object_aclcheck(), OidIsValid, RecoveryInProgress(), RemoveTempRelations(), searchPathCacheValid, snprintf, and PGPROC::tempNamespaceId.

Referenced by AccessTempTableNamespace().

◆ InvalidationCallback()

static void InvalidationCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 4796 of file namespace.c.

4797{
4798 /*
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
4801 * have changed).
4802 */
4803 baseSearchPathValid = false;
4804 searchPathCacheValid = false;
4805}

References baseSearchPathValid, and searchPathCacheValid.

Referenced by InitializeSearchPath().

◆ isAnyTempNamespace()

bool isAnyTempNamespace ( Oid  namespaceId)

Definition at line 3687 of file namespace.c.

3688{
3689 bool result;
3690 char *nspname;
3691
3692 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3693 nspname = get_namespace_name(namespaceId);
3694 if (!nspname)
3695 return false; /* no such namespace? */
3696 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
3697 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
3698 pfree(nspname);
3699 return result;
3700}

References get_namespace_name(), and pfree().

Referenced by AlterTableMoveAll(), check_publication_add_schema(), CheckSetNamespace(), EventTriggerSQLDropAddObject(), isOtherTempNamespace(), and RangeVarAdjustRelationPersistence().

◆ isOtherTempNamespace()

bool isOtherTempNamespace ( Oid  namespaceId)

Definition at line 3710 of file namespace.c.

3711{
3712 /* If it's my own temp namespace, say "false" */
3713 if (isTempOrTempToastNamespace(namespaceId))
3714 return false;
3715 /* Else, if it's any temp namespace, say "true" */
3716 return isAnyTempNamespace(namespaceId);
3717}
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3673

References isAnyTempNamespace(), and isTempOrTempToastNamespace().

Referenced by pg_is_other_temp_schema().

◆ isTempNamespace()

bool isTempNamespace ( Oid  namespaceId)

◆ isTempOrTempToastNamespace()

bool isTempOrTempToastNamespace ( Oid  namespaceId)

Definition at line 3673 of file namespace.c.

3674{
3676 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
3677 return true;
3678 return false;
3679}

References myTempNamespace, myTempToastNamespace, and OidIsValid.

Referenced by create_toast_table(), isOtherTempNamespace(), pg_relation_filepath(), RangeVarAdjustRelationPersistence(), RelationBuildDesc(), and RelationBuildLocalRelation().

◆ isTempToastNamespace()

bool isTempToastNamespace ( Oid  namespaceId)

Definition at line 3661 of file namespace.c.

3662{
3664 return true;
3665 return false;
3666}

References myTempToastNamespace, and OidIsValid.

Referenced by IsToastNamespace().

◆ lookup_collation()

static Oid lookup_collation ( const char *  collname,
Oid  collnamespace,
int32  encoding 
)
static

Definition at line 2322 of file namespace.c.

2323{
2324 Oid collid;
2325 HeapTuple colltup;
2326 Form_pg_collation collform;
2327
2328 /* Check for encoding-specific entry (exact match) */
2329 collid = GetSysCacheOid3(COLLNAMEENCNSP, Anum_pg_collation_oid,
2330 PointerGetDatum(collname),
2332 ObjectIdGetDatum(collnamespace));
2333 if (OidIsValid(collid))
2334 return collid;
2335
2336 /*
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.
2341 */
2342 colltup = SearchSysCache3(COLLNAMEENCNSP,
2343 PointerGetDatum(collname),
2344 Int32GetDatum(-1),
2345 ObjectIdGetDatum(collnamespace));
2346 if (!HeapTupleIsValid(colltup))
2347 return InvalidOid;
2348 collform = (Form_pg_collation) GETSTRUCT(colltup);
2349 if (collform->collprovider == COLLPROVIDER_ICU)
2350 {
2352 collid = collform->oid;
2353 else
2355 }
2356 else
2357 {
2358 collid = collform->oid;
2359 }
2360 ReleaseSysCache(colltup);
2361 return collid;
2362}
bool is_encoding_supported_by_icu(int encoding)
Definition: encnames.c:461
int32 encoding
Definition: pg_database.h:41
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:243
#define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3)
Definition: syscache.h:113

References collid, encoding, GETSTRUCT, GetSysCacheOid3, HeapTupleIsValid, Int32GetDatum(), InvalidOid, is_encoding_supported_by_icu(), ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), ReleaseSysCache(), and SearchSysCache3().

Referenced by CollationGetCollid(), and get_collation_oid().

◆ LookupCreationNamespace()

Oid LookupCreationNamespace ( const char *  nspname)

Definition at line 3428 of file namespace.c.

3429{
3430 Oid namespaceId;
3431 AclResult aclresult;
3432
3433 /* check for pg_temp alias */
3434 if (strcmp(nspname, "pg_temp") == 0)
3435 {
3436 /* Initialize temp namespace */
3438 return myTempNamespace;
3439 }
3440
3441 namespaceId = get_namespace_oid(nspname, false);
3442
3443 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
3444 if (aclresult != ACLCHECK_OK)
3445 aclcheck_error(aclresult, OBJECT_SCHEMA,
3446 nspname);
3447
3448 return namespaceId;
3449}
AclResult
Definition: acl.h:182
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
@ OBJECT_SCHEMA
Definition: parsenodes.h:2348
#define ACL_CREATE
Definition: parsenodes.h:85

References AccessTempTableNamespace(), ACL_CREATE, aclcheck_error(), ACLCHECK_OK, get_namespace_oid(), GetUserId(), myTempNamespace, object_aclcheck(), and OBJECT_SCHEMA.

Referenced by AlterExtensionNamespace(), AlterTypeNamespace(), ExecAlterObjectSchemaStmt(), ImportForeignSchema(), and make_new_heap().

◆ LookupExplicitNamespace()

Oid LookupExplicitNamespace ( const char *  nspname,
bool  missing_ok 
)

Definition at line 3385 of file namespace.c.

3386{
3387 Oid namespaceId;
3388 AclResult aclresult;
3389
3390 /* check for pg_temp alias */
3391 if (strcmp(nspname, "pg_temp") == 0)
3392 {
3394 return myTempNamespace;
3395
3396 /*
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.
3400 */
3401 }
3402
3403 namespaceId = get_namespace_oid(nspname, missing_ok);
3404 if (missing_ok && !OidIsValid(namespaceId))
3405 return InvalidOid;
3406
3407 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_USAGE);
3408 if (aclresult != ACLCHECK_OK)
3409 aclcheck_error(aclresult, OBJECT_SCHEMA,
3410 nspname);
3411 /* Schema search hook for this lookup */
3412 InvokeNamespaceSearchHook(namespaceId, true);
3413
3414 return namespaceId;
3415}
#define ACL_USAGE
Definition: parsenodes.h:84

References ACL_USAGE, aclcheck_error(), ACLCHECK_OK, get_namespace_oid(), GetUserId(), InvalidOid, InvokeNamespaceSearchHook, myTempNamespace, object_aclcheck(), OBJECT_SCHEMA, and OidIsValid.

Referenced by AfterTriggerSetState(), FuncnameGetCandidates(), get_collation_oid(), get_conversion_oid(), get_statistics_object_oid(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), LookupTypeNameExtended(), make_oper_cache_key(), objectsInSchemaToOids(), OpClassCacheLookup(), OpernameGetCandidates(), OpernameGetOprid(), OpFamilyCacheLookup(), RangeVarGetRelidExtended(), ResolveOpClass(), schema_to_xml(), schema_to_xml_and_xmlschema(), and schema_to_xmlschema_internal().

◆ LookupNamespaceNoError()

Oid LookupNamespaceNoError ( const char *  nspname)

Definition at line 3355 of file namespace.c.

3356{
3357 /* check for pg_temp alias */
3358 if (strcmp(nspname, "pg_temp") == 0)
3359 {
3361 {
3363 return myTempNamespace;
3364 }
3365
3366 /*
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".
3370 */
3371 return InvalidOid;
3372 }
3373
3374 return get_namespace_oid(nspname, true);
3375}

References get_namespace_oid(), InvalidOid, InvokeNamespaceSearchHook, myTempNamespace, and OidIsValid.

Referenced by DropErrorMsgNonExistent(), refnameNamespaceItem(), and schema_does_not_exist_skipping().

◆ makeRangeVarFromNameList()

RangeVar * makeRangeVarFromNameList ( const List names)

Definition at line 3554 of file namespace.c.

3555{
3556 RangeVar *rel = makeRangeVar(NULL, NULL, -1);
3557
3558 switch (list_length(names))
3559 {
3560 case 1:
3561 rel->relname = strVal(linitial(names));
3562 break;
3563 case 2:
3564 rel->schemaname = strVal(linitial(names));
3565 rel->relname = strVal(lsecond(names));
3566 break;
3567 case 3:
3568 rel->catalogname = strVal(linitial(names));
3569 rel->schemaname = strVal(lsecond(names));
3570 rel->relname = strVal(lthird(names));
3571 break;
3572 default:
3573 ereport(ERROR,
3574 (errcode(ERRCODE_SYNTAX_ERROR),
3575 errmsg("improper relation name (too many dotted names): %s",
3576 NameListToString(names))));
3577 break;
3578 }
3579
3580 return rel;
3581}
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:426
char * relname
Definition: primnodes.h:82
char * catalogname
Definition: primnodes.h:76
char * schemaname
Definition: primnodes.h:79

References RangeVar::catalogname, ereport, errcode(), errmsg(), ERROR, linitial, list_length(), lsecond, lthird, makeRangeVar(), NameListToString(), RangeVar::relname, RangeVar::schemaname, and strVal.

Referenced by bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), convert_table_name(), currtid_byrelname(), generateSerialExtraStmts(), get_object_address_attrdef(), get_object_address_attribute(), get_object_address_publication_rel(), get_object_address_relobject(), get_raw_page_internal(), get_rel_from_relname(), get_relation_by_qualified_name(), nextval(), owningrel_does_not_exist_skipping(), pg_get_serial_sequence(), pg_get_viewdef_name(), pg_get_viewdef_name_ext(), pg_relpages(), pg_relpages_v1_5(), pgrowlocks(), pgstatindex(), pgstatindex_v1_5(), pgstattuple(), pgstattuple_v1_5(), plpgsql_parse_cwordrowtype(), plpgsql_parse_cwordtype(), process_owned_by(), regclassin(), RelationNameGetTupleDesc(), RemoveRelations(), row_security_active_name(), schema_does_not_exist_skipping(), and text_regclass().

◆ MatchNamedCall()

static bool MatchNamedCall ( HeapTuple  proctup,
int  nargs,
List argnames,
bool  include_out_arguments,
int  pronargs,
int **  argnumbers 
)
static

Definition at line 1585 of file namespace.c.

1588{
1589 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
1590 int numposargs = nargs - list_length(argnames);
1591 int pronallargs;
1592 Oid *p_argtypes;
1593 char **p_argnames;
1594 char *p_argmodes;
1595 bool arggiven[FUNC_MAX_ARGS];
1596 bool isnull;
1597 int ap; /* call args position */
1598 int pp; /* proargs position */
1599 ListCell *lc;
1600
1601 Assert(argnames != NIL);
1602 Assert(numposargs >= 0);
1603 Assert(nargs <= pronargs);
1604
1605 /* Ignore this function if its proargnames is null */
1606 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
1607 &isnull);
1608 if (isnull)
1609 return false;
1610
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);
1615
1616 Assert(include_out_arguments ? (pronargs == pronallargs) : (pronargs <= pronallargs));
1617
1618 /* initialize state for matching */
1619 *argnumbers = (int *) palloc(pronargs * sizeof(int));
1620 memset(arggiven, false, pronargs * sizeof(bool));
1621
1622 /* there are numposargs positional args before the named args */
1623 for (ap = 0; ap < numposargs; ap++)
1624 {
1625 (*argnumbers)[ap] = ap;
1626 arggiven[ap] = true;
1627 }
1628
1629 /* now examine the named args */
1630 foreach(lc, argnames)
1631 {
1632 char *argname = (char *) lfirst(lc);
1633 bool found;
1634 int i;
1635
1636 pp = 0;
1637 found = false;
1638 for (i = 0; i < pronallargs; i++)
1639 {
1640 /* consider only input params, except with include_out_arguments */
1641 if (!include_out_arguments &&
1642 p_argmodes &&
1643 (p_argmodes[i] != FUNC_PARAM_IN &&
1644 p_argmodes[i] != FUNC_PARAM_INOUT &&
1645 p_argmodes[i] != FUNC_PARAM_VARIADIC))
1646 continue;
1647 if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
1648 {
1649 /* fail if argname matches a positional argument */
1650 if (arggiven[pp])
1651 return false;
1652 arggiven[pp] = true;
1653 (*argnumbers)[ap] = pp;
1654 found = true;
1655 break;
1656 }
1657 /* increase pp only for considered parameters */
1658 pp++;
1659 }
1660 /* if name isn't in proargnames, fail */
1661 if (!found)
1662 return false;
1663 ap++;
1664 }
1665
1666 Assert(ap == nargs); /* processed all actual parameters */
1667
1668 /* Check for default arguments */
1669 if (nargs < pronargs)
1670 {
1671 int first_arg_with_default = pronargs - procform->pronargdefaults;
1672
1673 for (pp = numposargs; pp < pronargs; pp++)
1674 {
1675 if (arggiven[pp])
1676 continue;
1677 /* fail if arg not given and no default available */
1678 if (pp < first_arg_with_default)
1679 return false;
1680 (*argnumbers)[ap++] = pp;
1681 }
1682 }
1683
1684 Assert(ap == pronargs); /* processed all function parameters */
1685
1686 return true;
1687}
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1379
@ FUNC_PARAM_IN
Definition: parsenodes.h:3516
@ FUNC_PARAM_INOUT
Definition: parsenodes.h:3518
@ FUNC_PARAM_VARIADIC
Definition: parsenodes.h:3519
#define FUNC_MAX_ARGS
#define lfirst(lc)
Definition: pg_list.h:172

References Assert, FUNC_MAX_ARGS, FUNC_PARAM_IN, FUNC_PARAM_INOUT, FUNC_PARAM_VARIADIC, get_func_arg_info(), GETSTRUCT, i, lfirst, list_length(), NIL, palloc(), pronargs, and SysCacheGetAttr().

Referenced by FuncnameGetCandidates().

◆ NameListToQuotedString()

char * NameListToQuotedString ( const List names)

Definition at line 3628 of file namespace.c.

3629{
3631 ListCell *l;
3632
3633 initStringInfo(&string);
3634
3635 foreach(l, names)
3636 {
3637 if (l != list_head(names))
3638 appendStringInfoChar(&string, '.');
3640 }
3641
3642 return string.data;
3643}
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
char string[11]
Definition: preproc-type.c:52
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12940
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97

References appendStringInfoChar(), appendStringInfoString(), initStringInfo(), lfirst, list_head(), quote_identifier(), and strVal.

◆ NameListToString()

char * NameListToString ( const List names)

Definition at line 3594 of file namespace.c.

3595{
3597 ListCell *l;
3598
3599 initStringInfo(&string);
3600
3601 foreach(l, names)
3602 {
3603 Node *name = (Node *) lfirst(l);
3604
3605 if (l != list_head(names))
3606 appendStringInfoChar(&string, '.');
3607
3608 if (IsA(name, String))
3610 else if (IsA(name, A_Star))
3611 appendStringInfoChar(&string, '*');
3612 else
3613 elog(ERROR, "unexpected node type in name list: %d",
3614 (int) nodeTag(name));
3615 }
3616
3617 return string.data;
3618}
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
Definition: nodes.h:129
Definition: value.h:64
const char * name

References appendStringInfoChar(), appendStringInfoString(), elog, ERROR, initStringInfo(), IsA, lfirst, list_head(), name, nodeTag, and strVal.

Referenced by AggregateCreate(), AlterCollation(), AlterFunction(), AlterStatistics(), AlterTSConfiguration(), AlterTSDictionary(), check_object_ownership(), CreateConversionCommand(), CreateEventTrigger(), CreateProceduralLanguage(), CreateTransform(), CreateTriggerFiringOn(), DeconstructQualifiedName(), defGetString(), DefineOperator(), DefineType(), does_not_exist_skipping(), dropOperators(), dropProcedures(), ExpandColumnRefStar(), findRangeSubOpclass(), findTypeAnalyzeFunction(), findTypeInputFunction(), findTypeOutputFunction(), findTypeReceiveFunction(), findTypeSendFunction(), findTypeSubscriptingFunction(), findTypeTypmodinFunction(), findTypeTypmodoutFunction(), func_signature_string(), get_collation_oid(), get_conversion_oid(), get_object_address_attrdef(), get_object_address_attribute(), get_statistics_object_oid(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), interpret_func_support(), lookup_fdw_handler_func(), LookupFuncName(), LookupFuncWithArgs(), LookupTypeNameExtended(), makeRangeVarFromNameList(), op_signature_string(), OpClassCacheLookup(), OperatorCreate(), OpFamilyCacheLookup(), owningrel_does_not_exist_skipping(), ParseFuncOrColumn(), plpgsql_post_column_ref(), regclassin(), regcollationin(), regconfigin(), regdictionaryin(), RemoveObjects(), ResolveOpClass(), storeOperators(), storeProcedures(), transformColumnRef(), transformRangeTableSample(), ValidateJoinEstimator(), ValidateOperatorReference(), and ValidateRestrictionEstimator().

◆ OpclassIsVisible()

bool OpclassIsVisible ( Oid  opcid)

Definition at line 2154 of file namespace.c.

2155{
2156 return OpclassIsVisibleExt(opcid, NULL);
2157}
static bool OpclassIsVisibleExt(Oid opcid, bool *is_missing)
Definition: namespace.c:2166

References OpclassIsVisibleExt().

Referenced by get_opclass_name(), and getObjectDescription().

◆ OpclassIsVisibleExt()

static bool OpclassIsVisibleExt ( Oid  opcid,
bool *  is_missing 
)
static

Definition at line 2166 of file namespace.c.

2167{
2168 HeapTuple opctup;
2169 Form_pg_opclass opcform;
2170 Oid opcnamespace;
2171 bool visible;
2172
2173 opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
2174 if (!HeapTupleIsValid(opctup))
2175 {
2176 if (is_missing != NULL)
2177 {
2178 *is_missing = true;
2179 return false;
2180 }
2181 elog(ERROR, "cache lookup failed for opclass %u", opcid);
2182 }
2183 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
2184
2186
2187 /*
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.
2191 */
2192 opcnamespace = opcform->opcnamespace;
2193 if (opcnamespace != PG_CATALOG_NAMESPACE &&
2194 !list_member_oid(activeSearchPath, opcnamespace))
2195 visible = false;
2196 else
2197 {
2198 /*
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.
2203 */
2204 char *opcname = NameStr(opcform->opcname);
2205
2206 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
2207 }
2208
2209 ReleaseSysCache(opctup);
2210
2211 return visible;
2212}
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:2121
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, list_member_oid(), NameStr, ObjectIdGetDatum(), OpclassnameGetOpcid(), recomputeNamespacePath(), ReleaseSysCache(), and SearchSysCache1().

Referenced by OpclassIsVisible(), and pg_opclass_is_visible().

◆ OpclassnameGetOpcid()

Oid OpclassnameGetOpcid ( Oid  amid,
const char *  opcname 
)

Definition at line 2121 of file namespace.c.

2122{
2123 Oid opcid;
2124 ListCell *l;
2125
2127
2128 foreach(l, activeSearchPath)
2129 {
2130 Oid namespaceId = lfirst_oid(l);
2131
2132 if (namespaceId == myTempNamespace)
2133 continue; /* do not look in temp namespace */
2134
2135 opcid = GetSysCacheOid3(CLAAMNAMENSP, Anum_pg_opclass_oid,
2136 ObjectIdGetDatum(amid),
2137 PointerGetDatum(opcname),
2138 ObjectIdGetDatum(namespaceId));
2139 if (OidIsValid(opcid))
2140 return opcid;
2141 }
2142
2143 /* Not found in path */
2144 return InvalidOid;
2145}

References activeSearchPath, GetSysCacheOid3, InvalidOid, lfirst_oid, myTempNamespace, ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by OpClassCacheLookup(), OpclassIsVisibleExt(), and ResolveOpClass().

◆ OperatorIsVisible()

bool OperatorIsVisible ( Oid  oprid)

Definition at line 2049 of file namespace.c.

2050{
2051 return OperatorIsVisibleExt(oprid, NULL);
2052}
static bool OperatorIsVisibleExt(Oid oprid, bool *is_missing)
Definition: namespace.c:2061
Oid oprid(Operator op)
Definition: parse_oper.c:238

References OperatorIsVisibleExt(), and oprid().

Referenced by format_operator_extended().

◆ OperatorIsVisibleExt()

static bool OperatorIsVisibleExt ( Oid  oprid,
bool *  is_missing 
)
static

Definition at line 2061 of file namespace.c.

2062{
2063 HeapTuple oprtup;
2064 Form_pg_operator oprform;
2065 Oid oprnamespace;
2066 bool visible;
2067
2068 oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
2069 if (!HeapTupleIsValid(oprtup))
2070 {
2071 if (is_missing != NULL)
2072 {
2073 *is_missing = true;
2074 return false;
2075 }
2076 elog(ERROR, "cache lookup failed for operator %u", oprid);
2077 }
2078 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
2079
2081
2082 /*
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.
2086 */
2087 oprnamespace = oprform->oprnamespace;
2088 if (oprnamespace != PG_CATALOG_NAMESPACE &&
2089 !list_member_oid(activeSearchPath, oprnamespace))
2090 visible = false;
2091 else
2092 {
2093 /*
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.
2098 */
2099 char *oprname = NameStr(oprform->oprname);
2100
2101 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
2102 oprform->oprleft, oprform->oprright)
2103 == oprid);
2104 }
2105
2106 ReleaseSysCache(oprtup);
2107
2108 return visible;
2109}
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1785
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, list_make1, list_member_oid(), makeString(), NameStr, ObjectIdGetDatum(), OpernameGetOprid(), oprid(), recomputeNamespacePath(), ReleaseSysCache(), and SearchSysCache1().

Referenced by OperatorIsVisible(), and pg_operator_is_visible().

◆ OpernameGetCandidates()

FuncCandidateList OpernameGetCandidates ( List names,
char  oprkind,
bool  missing_schema_ok 
)

Definition at line 1888 of file namespace.c.

1889{
1890 FuncCandidateList resultList = NULL;
1891 char *resultSpace = NULL;
1892 int nextResult = 0;
1893 char *schemaname;
1894 char *opername;
1895 Oid namespaceId;
1896 CatCList *catlist;
1897 int i;
1898
1899 /* deconstruct the name list */
1900 DeconstructQualifiedName(names, &schemaname, &opername);
1901
1902 if (schemaname)
1903 {
1904 /* use exact schema given */
1905 namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
1906 if (missing_schema_ok && !OidIsValid(namespaceId))
1907 return NULL;
1908 }
1909 else
1910 {
1911 /* flag to indicate we need namespace search */
1912 namespaceId = InvalidOid;
1914 }
1915
1916 /* Search syscache by name only */
1917 catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
1918
1919 /*
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.
1927 */
1928#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
1929 2 * sizeof(Oid))
1930
1931 if (catlist->n_members > 0)
1932 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1933
1934 for (i = 0; i < catlist->n_members; i++)
1935 {
1936 HeapTuple opertup = &catlist->members[i]->tuple;
1937 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1938 int pathpos = 0;
1939 FuncCandidateList newResult;
1940
1941 /* Ignore operators of wrong kind, if specific kind requested */
1942 if (oprkind && operform->oprkind != oprkind)
1943 continue;
1944
1945 if (OidIsValid(namespaceId))
1946 {
1947 /* Consider only opers in specified namespace */
1948 if (operform->oprnamespace != namespaceId)
1949 continue;
1950 /* No need to check args, they must all be different */
1951 }
1952 else
1953 {
1954 /*
1955 * Consider only opers that are in the search path and are not in
1956 * the temp namespace.
1957 */
1958 ListCell *nsp;
1959
1960 foreach(nsp, activeSearchPath)
1961 {
1962 if (operform->oprnamespace == lfirst_oid(nsp) &&
1963 operform->oprnamespace != myTempNamespace)
1964 break;
1965 pathpos++;
1966 }
1967 if (nsp == NULL)
1968 continue; /* oper is not in search path */
1969
1970 /*
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.
1974 *
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
1979 * result list.
1980 */
1981 if (resultList)
1982 {
1983 FuncCandidateList prevResult;
1984
1985 if (catlist->ordered)
1986 {
1987 if (operform->oprleft == resultList->args[0] &&
1988 operform->oprright == resultList->args[1])
1989 prevResult = resultList;
1990 else
1991 prevResult = NULL;
1992 }
1993 else
1994 {
1995 for (prevResult = resultList;
1996 prevResult;
1997 prevResult = prevResult->next)
1998 {
1999 if (operform->oprleft == prevResult->args[0] &&
2000 operform->oprright == prevResult->args[1])
2001 break;
2002 }
2003 }
2004 if (prevResult)
2005 {
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 */
2014 }
2015 }
2016 }
2017
2018 /*
2019 * Okay to add it to result list
2020 */
2021 newResult = (FuncCandidateList) (resultSpace + nextResult);
2022 nextResult += SPACE_PER_OP;
2023
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;
2035 }
2036
2037 ReleaseSysCacheList(catlist);
2038
2039 return resultList;
2040}
#define SPACE_PER_OP

References activeSearchPath, _FuncCandidateList::argnumbers, _FuncCandidateList::args, Assert, CStringGetDatum(), DeconstructQualifiedName(), GETSTRUCT, i, InvalidOid, lfirst_oid, LookupExplicitNamespace(), catclist::members, myTempNamespace, catclist::n_members, _FuncCandidateList::nargs, _FuncCandidateList::ndargs, _FuncCandidateList::next, _FuncCandidateList::nominalnargs, _FuncCandidateList::nvargs, _FuncCandidateList::oid, OidIsValid, catclist::ordered, palloc(), _FuncCandidateList::pathpos, recomputeNamespacePath(), ReleaseSysCacheList, SearchSysCacheList1, SPACE_PER_OP, and catctup::tuple.

Referenced by left_oper(), oper(), regoperin(), and regoperout().

◆ OpernameGetOprid()

Oid OpernameGetOprid ( List names,
Oid  oprleft,
Oid  oprright 
)

Definition at line 1785 of file namespace.c.

1786{
1787 char *schemaname;
1788 char *opername;
1789 CatCList *catlist;
1790 ListCell *l;
1791
1792 /* deconstruct the name list */
1793 DeconstructQualifiedName(names, &schemaname, &opername);
1794
1795 if (schemaname)
1796 {
1797 /* search only in exact schema given */
1798 Oid namespaceId;
1799
1800 namespaceId = LookupExplicitNamespace(schemaname, true);
1801 if (OidIsValid(namespaceId))
1802 {
1803 HeapTuple opertup;
1804
1805 opertup = SearchSysCache4(OPERNAMENSP,
1806 CStringGetDatum(opername),
1807 ObjectIdGetDatum(oprleft),
1808 ObjectIdGetDatum(oprright),
1809 ObjectIdGetDatum(namespaceId));
1810 if (HeapTupleIsValid(opertup))
1811 {
1812 Form_pg_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
1813 Oid result = operclass->oid;
1814
1815 ReleaseSysCache(opertup);
1816 return result;
1817 }
1818 }
1819
1820 return InvalidOid;
1821 }
1822
1823 /* Search syscache by name and argument types */
1824 catlist = SearchSysCacheList3(OPERNAMENSP,
1825 CStringGetDatum(opername),
1826 ObjectIdGetDatum(oprleft),
1827 ObjectIdGetDatum(oprright));
1828
1829 if (catlist->n_members == 0)
1830 {
1831 /* no hope, fall out early */
1832 ReleaseSysCacheList(catlist);
1833 return InvalidOid;
1834 }
1835
1836 /*
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.
1840 */
1842
1843 foreach(l, activeSearchPath)
1844 {
1845 Oid namespaceId = lfirst_oid(l);
1846 int i;
1847
1848 if (namespaceId == myTempNamespace)
1849 continue; /* do not look in temp namespace */
1850
1851 for (i = 0; i < catlist->n_members; i++)
1852 {
1853 HeapTuple opertup = &catlist->members[i]->tuple;
1854 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1855
1856 if (operform->oprnamespace == namespaceId)
1857 {
1858 Oid result = operform->oid;
1859
1860 ReleaseSysCacheList(catlist);
1861 return result;
1862 }
1863 }
1864 }
1865
1866 ReleaseSysCacheList(catlist);
1867 return InvalidOid;
1868}
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:254
#define SearchSysCacheList3(cacheId, key1, key2, key3)
Definition: syscache.h:131

References activeSearchPath, CStringGetDatum(), DeconstructQualifiedName(), GETSTRUCT, HeapTupleIsValid, i, InvalidOid, lfirst_oid, LookupExplicitNamespace(), catclist::members, myTempNamespace, catclist::n_members, ObjectIdGetDatum(), OidIsValid, recomputeNamespacePath(), ReleaseSysCache(), ReleaseSysCacheList, SearchSysCache4(), SearchSysCacheList3, and catctup::tuple.

Referenced by binary_oper_exact(), left_oper(), LookupOperName(), OperatorIsVisibleExt(), and regoperatorin().

◆ OpfamilyIsVisible()

bool OpfamilyIsVisible ( Oid  opfid)

Definition at line 2256 of file namespace.c.

2257{
2258 return OpfamilyIsVisibleExt(opfid, NULL);
2259}
static bool OpfamilyIsVisibleExt(Oid opfid, bool *is_missing)
Definition: namespace.c:2268

References OpfamilyIsVisibleExt().

Referenced by getOpFamilyDescription().

◆ OpfamilyIsVisibleExt()

static bool OpfamilyIsVisibleExt ( Oid  opfid,
bool *  is_missing 
)
static

Definition at line 2268 of file namespace.c.

2269{
2270 HeapTuple opftup;
2271 Form_pg_opfamily opfform;
2272 Oid opfnamespace;
2273 bool visible;
2274
2275 opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
2276 if (!HeapTupleIsValid(opftup))
2277 {
2278 if (is_missing != NULL)
2279 {
2280 *is_missing = true;
2281 return false;
2282 }
2283 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
2284 }
2285 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
2286
2288
2289 /*
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.
2293 */
2294 opfnamespace = opfform->opfnamespace;
2295 if (opfnamespace != PG_CATALOG_NAMESPACE &&
2296 !list_member_oid(activeSearchPath, opfnamespace))
2297 visible = false;
2298 else
2299 {
2300 /*
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.
2305 */
2306 char *opfname = NameStr(opfform->opfname);
2307
2308 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
2309 }
2310
2311 ReleaseSysCache(opftup);
2312
2313 return visible;
2314}
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
Definition: namespace.c:2223
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, list_member_oid(), NameStr, ObjectIdGetDatum(), OpfamilynameGetOpfid(), recomputeNamespacePath(), ReleaseSysCache(), and SearchSysCache1().

Referenced by OpfamilyIsVisible(), and pg_opfamily_is_visible().

◆ OpfamilynameGetOpfid()

Oid OpfamilynameGetOpfid ( Oid  amid,
const char *  opfname 
)

Definition at line 2223 of file namespace.c.

2224{
2225 Oid opfid;
2226 ListCell *l;
2227
2229
2230 foreach(l, activeSearchPath)
2231 {
2232 Oid namespaceId = lfirst_oid(l);
2233
2234 if (namespaceId == myTempNamespace)
2235 continue; /* do not look in temp namespace */
2236
2237 opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP, Anum_pg_opfamily_oid,
2238 ObjectIdGetDatum(amid),
2239 PointerGetDatum(opfname),
2240 ObjectIdGetDatum(namespaceId));
2241 if (OidIsValid(opfid))
2242 return opfid;
2243 }
2244
2245 /* Not found in path */
2246 return InvalidOid;
2247}

References activeSearchPath, GetSysCacheOid3, InvalidOid, lfirst_oid, myTempNamespace, ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), and recomputeNamespacePath().

Referenced by OpFamilyCacheLookup(), and OpfamilyIsVisibleExt().

◆ pg_collation_is_visible()

Datum pg_collation_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4978 of file namespace.c.

4979{
4980 Oid oid = PG_GETARG_OID(0);
4981 bool result;
4982 bool is_missing = false;
4983
4984 result = CollationIsVisibleExt(oid, &is_missing);
4985
4986 if (is_missing)
4988 PG_RETURN_BOOL(result);
4989}
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

References CollationIsVisibleExt(), PG_GETARG_OID, PG_RETURN_BOOL, and PG_RETURN_NULL.

◆ pg_conversion_is_visible()

Datum pg_conversion_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4992 of file namespace.c.

4993{
4994 Oid oid = PG_GETARG_OID(0);
4995 bool result;
4996 bool is_missing = false;
4997
4998 result = ConversionIsVisibleExt(oid, &is_missing);
4999
5000 if (is_missing)
5002 PG_RETURN_BOOL(result);
5003}

References ConversionIsVisibleExt(), PG_GETARG_OID, PG_RETURN_BOOL, and PG_RETURN_NULL.

◆ pg_function_is_visible()

Datum pg_function_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4922 of file namespace.c.

4923{
4924 Oid oid = PG_GETARG_OID(0);
4925 bool result;
4926 bool is_missing = false;
4927
4928 result = FunctionIsVisibleExt(oid, &is_missing);
4929
4930 if (is_missing)
4932 PG_RETURN_BOOL(result);
4933}

References FunctionIsVisibleExt(), PG_GETARG_OID, PG_RETURN_BOOL, and PG_RETURN_NULL.

◆ pg_is_other_temp_schema()

Datum pg_is_other_temp_schema ( PG_FUNCTION_ARGS  )

Definition at line 5082 of file namespace.c.

5083{
5084 Oid oid = PG_GETARG_OID(0);
5085
5087}
bool isOtherTempNamespace(Oid namespaceId)
Definition: namespace.c:3710

References isOtherTempNamespace(), PG_GETARG_OID, and PG_RETURN_BOOL.

◆ pg_my_temp_schema()

Datum pg_my_temp_schema ( PG_FUNCTION_ARGS  )

Definition at line 5076 of file namespace.c.

5077{
5079}
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

References myTempNamespace, and PG_RETURN_OID.

◆ pg_opclass_is_visible()

Datum pg_opclass_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4950 of file namespace.c.

4951{
4952 Oid oid = PG_GETARG_OID(0);
4953 bool result;
4954 bool is_missing = false;
4955
4956 result = OpclassIsVisibleExt(oid, &is_missing);
4957
4958 if (is_missing)
4960 PG_RETURN_BOOL(result);
4961}

References OpclassIsVisibleExt(), PG_GETARG_OID, PG_RETURN_BOOL, and PG_RETURN_NULL.

◆ pg_operator_is_visible()

Datum pg_operator_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4936 of file namespace.c.

4937{
4938 Oid oid = PG_GETARG_OID(0);
4939 bool result;
4940 bool is_missing = false;
4941
4942 result = OperatorIsVisibleExt(oid, &is_missing);
4943
4944 if (is_missing)
4946 PG_RETURN_BOOL(result);
4947}

References OperatorIsVisibleExt(), PG_GETARG_OID, PG_RETURN_BOOL, and PG_RETURN_NULL.

◆ pg_opfamily_is_visible()

Datum pg_opfamily_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4964 of file namespace.c.

4965{
4966 Oid oid = PG_GETARG_OID(0);
4967 bool result;
4968 bool is_missing = false;
4969
4970 result = OpfamilyIsVisibleExt(oid, &is_missing);
4971
4972 if (is_missing)
4974 PG_RETURN_BOOL(result);
4975}

References OpfamilyIsVisibleExt(), PG_GETARG_OID, PG_RETURN_BOOL, and PG_RETURN_NULL.

◆ pg_statistics_obj_is_visible()

Datum pg_statistics_obj_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 5006 of file namespace.c.

5007{
5008 Oid oid = PG_GETARG_OID(0);
5009 bool result;
5010 bool is_missing = false;
5011
5012 result = StatisticsObjIsVisibleExt(oid, &is_missing);
5013
5014 if (is_missing)
5016 PG_RETURN_BOOL(result);
5017}
static bool StatisticsObjIsVisibleExt(Oid stxid, bool *is_missing)
Definition: namespace.c:2644

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and StatisticsObjIsVisibleExt().

◆ pg_table_is_visible()

Datum pg_table_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4894 of file namespace.c.

4895{
4896 Oid oid = PG_GETARG_OID(0);
4897 bool result;
4898 bool is_missing = false;
4899
4900 result = RelationIsVisibleExt(oid, &is_missing);
4901
4902 if (is_missing)
4904 PG_RETURN_BOOL(result);
4905}
static bool RelationIsVisibleExt(Oid relid, bool *is_missing)
Definition: namespace.c:925

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and RelationIsVisibleExt().

◆ pg_ts_config_is_visible()

Datum pg_ts_config_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 5062 of file namespace.c.

5063{
5064 Oid oid = PG_GETARG_OID(0);
5065 bool result;
5066 bool is_missing = false;
5067
5068 result = TSConfigIsVisibleExt(oid, &is_missing);
5069
5070 if (is_missing)
5072 PG_RETURN_BOOL(result);
5073}
static bool TSConfigIsVisibleExt(Oid cfgid, bool *is_missing)
Definition: namespace.c:3222

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and TSConfigIsVisibleExt().

◆ pg_ts_dict_is_visible()

Datum pg_ts_dict_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 5034 of file namespace.c.

5035{
5036 Oid oid = PG_GETARG_OID(0);
5037 bool result;
5038 bool is_missing = false;
5039
5040 result = TSDictionaryIsVisibleExt(oid, &is_missing);
5041
5042 if (is_missing)
5044 PG_RETURN_BOOL(result);
5045}
static bool TSDictionaryIsVisibleExt(Oid dictId, bool *is_missing)
Definition: namespace.c:2931

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and TSDictionaryIsVisibleExt().

◆ pg_ts_parser_is_visible()

Datum pg_ts_parser_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 5020 of file namespace.c.

5021{
5022 Oid oid = PG_GETARG_OID(0);
5023 bool result;
5024 bool is_missing = false;
5025
5026 result = TSParserIsVisibleExt(oid, &is_missing);
5027
5028 if (is_missing)
5030 PG_RETURN_BOOL(result);
5031}
static bool TSParserIsVisibleExt(Oid prsId, bool *is_missing)
Definition: namespace.c:2786

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and TSParserIsVisibleExt().

◆ pg_ts_template_is_visible()

Datum pg_ts_template_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 5048 of file namespace.c.

5049{
5050 Oid oid = PG_GETARG_OID(0);
5051 bool result;
5052 bool is_missing = false;
5053
5054 result = TSTemplateIsVisibleExt(oid, &is_missing);
5055
5056 if (is_missing)
5058 PG_RETURN_BOOL(result);
5059}
static bool TSTemplateIsVisibleExt(Oid tmplId, bool *is_missing)
Definition: namespace.c:3077

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and TSTemplateIsVisibleExt().

◆ pg_type_is_visible()

Datum pg_type_is_visible ( PG_FUNCTION_ARGS  )

Definition at line 4908 of file namespace.c.

4909{
4910 Oid oid = PG_GETARG_OID(0);
4911 bool result;
4912 bool is_missing = false;
4913
4914 result = TypeIsVisibleExt(oid, &is_missing);
4915
4916 if (is_missing)
4918 PG_RETURN_BOOL(result);
4919}
static bool TypeIsVisibleExt(Oid typid, bool *is_missing)
Definition: namespace.c:1052

References PG_GETARG_OID, PG_RETURN_BOOL, PG_RETURN_NULL, and TypeIsVisibleExt().

◆ preprocessNamespacePath()

static List * preprocessNamespacePath ( const char *  searchPath,
Oid  roleid,
bool *  temp_missing 
)
static

Definition at line 4107 of file namespace.c.

4109{
4110 char *rawname;
4111 List *namelist;
4112 List *oidlist;
4113 ListCell *l;
4114
4115 /* Need a modifiable copy */
4116 rawname = pstrdup(searchPath);
4117
4118 /* Parse string into list of identifiers */
4119 if (!SplitIdentifierString(rawname, ',', &namelist))
4120 {
4121 /* syntax error in name list */
4122 /* this should not happen if GUC checked check_search_path */
4123 elog(ERROR, "invalid list syntax");
4124 }
4125
4126 /*
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.
4131 */
4132 oidlist = NIL;
4133 *temp_missing = false;
4134 foreach(l, namelist)
4135 {
4136 char *curname = (char *) lfirst(l);
4137 Oid namespaceId;
4138
4139 if (strcmp(curname, "$user") == 0)
4140 {
4141 /* $user --- substitute namespace matching user name, if any */
4142 HeapTuple tuple;
4143
4144 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4145 if (HeapTupleIsValid(tuple))
4146 {
4147 char *rname;
4148
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,
4155 oidlist = lappend_oid(oidlist, namespaceId);
4156 }
4157 }
4158 else if (strcmp(curname, "pg_temp") == 0)
4159 {
4160 /* pg_temp --- substitute temp namespace, if any */
4162 oidlist = lappend_oid(oidlist, myTempNamespace);
4163 else
4164 {
4165 /* If it ought to be the creation namespace, set flag */
4166 if (oidlist == NIL)
4167 *temp_missing = true;
4168 }
4169 }
4170 else
4171 {
4172 /* normal namespace reference */
4173 namespaceId = get_namespace_oid(curname, true);
4174 if (OidIsValid(namespaceId) &&
4175 object_aclcheck(NamespaceRelationId, namespaceId, roleid,
4177 oidlist = lappend_oid(oidlist, namespaceId);
4178 }
4179 }
4180
4181 pfree(rawname);
4182 list_free(namelist);
4183
4184 return oidlist;
4185}
NameData rolname
Definition: pg_authid.h:34
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56

References ACL_USAGE, ACLCHECK_OK, elog, ERROR, get_namespace_oid(), GETSTRUCT, HeapTupleIsValid, lappend_oid(), lfirst, list_free(), myTempNamespace, NameStr, NIL, object_aclcheck(), ObjectIdGetDatum(), OidIsValid, pfree(), pstrdup(), ReleaseSysCache(), rolname, SearchSysCache1(), and SplitIdentifierString().

Referenced by cachedNamespacePath().

◆ QualifiedNameGetCreationNamespace()

Oid QualifiedNameGetCreationNamespace ( const List names,
char **  objname_p 
)

Definition at line 3487 of file namespace.c.

3488{
3489 char *schemaname;
3490 Oid namespaceId;
3491
3492 /* deconstruct the name list */
3493 DeconstructQualifiedName(names, &schemaname, objname_p);
3494
3495 if (schemaname)
3496 {
3497 /* check for pg_temp alias */
3498 if (strcmp(schemaname, "pg_temp") == 0)
3499 {
3500 /* Initialize temp namespace */
3502 return myTempNamespace;
3503 }
3504 /* use exact schema given */
3505 namespaceId = get_namespace_oid(schemaname, false);
3506 /* we do not check for USAGE rights here! */
3507 }
3508 else
3509 {
3510 /* use the default creation namespace */
3513 {
3514 /* Need to initialize temp namespace */
3516 return myTempNamespace;
3517 }
3518 namespaceId = activeCreationNamespace;
3519 if (!OidIsValid(namespaceId))
3520 ereport(ERROR,
3521 (errcode(ERRCODE_UNDEFINED_SCHEMA),
3522 errmsg("no schema has been selected to create in")));
3523 }
3524
3525 return namespaceId;
3526}

References AccessTempTableNamespace(), activeCreationNamespace, activeTempCreationPending, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, get_namespace_oid(), myTempNamespace, OidIsValid, and recomputeNamespacePath().

Referenced by compute_return_type(), CreateConversionCommand(), CreateFunction(), CreateStatistics(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineRange(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), DefineType(), and get_other_operator().

◆ RangeVarAdjustRelationPersistence()

void RangeVarAdjustRelationPersistence ( RangeVar newRelation,
Oid  nspid 
)

Definition at line 846 of file namespace.c.

847{
848 switch (newRelation->relpersistence)
849 {
850 case RELPERSISTENCE_TEMP:
852 {
855 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
856 errmsg("cannot create relations in temporary schemas of other sessions")));
857 else
859 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
860 errmsg("cannot create temporary relation in non-temporary schema")));
861 }
862 break;
863 case RELPERSISTENCE_PERMANENT:
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")));
870 break;
871 default:
874 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
875 errmsg("only temporary relations may be created in temporary schemas")));
876 }
877}
int nspid
char relpersistence
Definition: primnodes.h:88

References ereport, errcode(), errmsg(), ERROR, isAnyTempNamespace(), isTempOrTempToastNamespace(), nspid, and RangeVar::relpersistence.

Referenced by DefineCompositeType(), generateSerialExtraStmts(), and RangeVarGetAndCheckCreationNamespace().

◆ RangeVarGetAndCheckCreationNamespace()

Oid RangeVarGetAndCheckCreationNamespace ( RangeVar relation,
LOCKMODE  lockmode,
Oid existing_relation_id 
)

Definition at line 739 of file namespace.c.

742{
743 uint64 inval_count;
744 Oid relid;
745 Oid oldrelid = InvalidOid;
746 Oid nspid;
747 Oid oldnspid = InvalidOid;
748 bool retry = false;
749
750 /*
751 * We check the catalog name and then ignore it.
752 */
753 if (relation->catalogname)
754 {
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)));
761 }
762
763 /*
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.
768 */
769 for (;;)
770 {
771 AclResult aclresult;
772
773 inval_count = SharedInvalidMessageCounter;
774
775 /* Look up creation namespace and check for existing relation. */
778 if (existing_relation_id != NULL)
779 relid = get_relname_relid(relation->relname, nspid);
780 else
781 relid = InvalidOid;
782
783 /*
784 * In bootstrap processing mode, we don't bother with permissions or
785 * locking. Permissions might not be working yet, and locking is
786 * unnecessary.
787 */
789 break;
790
791 /* Check namespace permissions. */
792 aclresult = object_aclcheck(NamespaceRelationId, nspid, GetUserId(), ACL_CREATE);
793 if (aclresult != ACLCHECK_OK)
794 aclcheck_error(aclresult, OBJECT_SCHEMA,
796
797 if (retry)
798 {
799 /* If nothing changed, we're done. */
800 if (relid == oldrelid && nspid == oldnspid)
801 break;
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);
809 }
810
811 /* Lock namespace. */
812 if (nspid != oldnspid)
813 LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
814
815 /* Lock relation, if required if and we have permission. */
816 if (lockmode != NoLock && OidIsValid(relid))
817 {
818 if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
820 relation->relname);
821 if (relid != oldrelid)
822 LockRelationOid(relid, lockmode);
823 }
824
825 /* If no invalidation message were processed, we're done! */
826 if (inval_count == SharedInvalidMessageCounter)
827 break;
828
829 /* Something may have changed, so recheck our work. */
830 retry = true;
831 oldrelid = relid;
832 oldnspid = nspid;
833 }
834
836 if (existing_relation_id != NULL)
837 *existing_relation_id = relid;
838 return nspid;
839}
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4058
uint64_t uint64
Definition: c.h:489
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:226
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:993
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1052
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2003
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1885
void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
Definition: namespace.c:846
Oid RangeVarGetCreationNamespace(const RangeVar *newRelation)
Definition: namespace.c:654
ObjectType get_relkind_objtype(char relkind)
uint64 SharedInvalidMessageCounter
Definition: sinval.c:24

References AccessShareLock, ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, Assert, RangeVar::catalogname, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_namespace_name(), get_rel_relkind(), get_relkind_objtype(), get_relname_relid(), GetUserId(), InvalidOid, IsBootstrapProcessingMode, LockDatabaseObject(), LockRelationOid(), MyDatabaseId, NoLock, nspid, object_aclcheck(), object_ownercheck(), OBJECT_SCHEMA, OidIsValid, RangeVarAdjustRelationPersistence(), RangeVarGetCreationNamespace(), RangeVar::relname, RangeVar::schemaname, SharedInvalidMessageCounter, UnlockDatabaseObject(), and UnlockRelationOid().

Referenced by AlterTableNamespace(), DefineCompositeType(), DefineRelation(), DefineSequence(), DefineVirtualRelation(), and transformCreateStmt().

◆ RangeVarGetCreationNamespace()

Oid RangeVarGetCreationNamespace ( const RangeVar newRelation)

Definition at line 654 of file namespace.c.

655{
656 Oid namespaceId;
657
658 /*
659 * We check the catalog name and then ignore it.
660 */
661 if (newRelation->catalogname)
662 {
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)));
669 }
670
671 if (newRelation->schemaname)
672 {
673 /* check for pg_temp alias */
674 if (strcmp(newRelation->schemaname, "pg_temp") == 0)
675 {
676 /* Initialize temp namespace */
678 return myTempNamespace;
679 }
680 /* use exact schema given */
681 namespaceId = get_namespace_oid(newRelation->schemaname, false);
682 /* we do not check for USAGE rights here! */
683 }
684 else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
685 {
686 /* Initialize temp namespace */
688 return myTempNamespace;
689 }
690 else
691 {
692 /* use the default creation namespace */
695 {
696 /* Need to initialize temp namespace */
698 return myTempNamespace;
699 }
700 namespaceId = activeCreationNamespace;
701 if (!OidIsValid(namespaceId))
703 (errcode(ERRCODE_UNDEFINED_SCHEMA),
704 errmsg("no schema has been selected to create in")));
705 }
706
707 /* Note: callers will check for CREATE rights when appropriate */
708
709 return namespaceId;
710}

References AccessTempTableNamespace(), activeCreationNamespace, activeTempCreationPending, RangeVar::catalogname, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_namespace_oid(), MyDatabaseId, myTempNamespace, OidIsValid, recomputeNamespacePath(), RangeVar::relname, RangeVar::relpersistence, and RangeVar::schemaname.

Referenced by CreateTableAsRelExists(), generateSerialExtraStmts(), and RangeVarGetAndCheckCreationNamespace().

◆ RangeVarGetRelidExtended()

Oid RangeVarGetRelidExtended ( const RangeVar relation,
LOCKMODE  lockmode,
uint32  flags,
RangeVarGetRelidCallback  callback,
void *  callback_arg 
)

Definition at line 441 of file namespace.c.

444{
445 uint64 inval_count;
446 Oid relId;
447 Oid oldRelId = InvalidOid;
448 bool retry = false;
449 bool missing_ok = (flags & RVR_MISSING_OK) != 0;
450
451 /* verify that flags do no conflict */
452 Assert(!((flags & RVR_NOWAIT) && (flags & RVR_SKIP_LOCKED)));
453
454 /*
455 * We check the catalog name and then ignore it.
456 */
457 if (relation->catalogname)
458 {
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)));
465 }
466
467 /*
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.
473 *
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.
482 */
483 for (;;)
484 {
485 /*
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.
489 */
490 inval_count = SharedInvalidMessageCounter;
491
492 /*
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.
499 */
500 if (relation->relpersistence == RELPERSISTENCE_TEMP)
501 {
503 relId = InvalidOid; /* this probably can't happen? */
504 else
505 {
506 if (relation->schemaname)
507 {
508 Oid namespaceId;
509
510 namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
511
512 /*
513 * For missing_ok, allow a non-existent schema name to
514 * return InvalidOid.
515 */
516 if (namespaceId != myTempNamespace)
518 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
519 errmsg("temporary tables cannot specify a schema name")));
520 }
521
522 relId = get_relname_relid(relation->relname, myTempNamespace);
523 }
524 }
525 else if (relation->schemaname)
526 {
527 Oid namespaceId;
528
529 /* use exact schema given */
530 namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
531 if (missing_ok && !OidIsValid(namespaceId))
532 relId = InvalidOid;
533 else
534 relId = get_relname_relid(relation->relname, namespaceId);
535 }
536 else
537 {
538 /* search the namespace path */
539 relId = RelnameGetRelid(relation->relname);
540 }
541
542 /*
543 * Invoke caller-supplied callback, if any.
544 *
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.
551 */
552 if (callback)
553 callback(relation, relId, oldRelId, callback_arg);
554
555 /*
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.
561 */
562 if (lockmode == NoLock)
563 break;
564
565 /*
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.
568 * So we're done.
569 *
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
572 * lock.
573 */
574 if (retry)
575 {
576 if (relId == oldRelId)
577 break;
578 if (OidIsValid(oldRelId))
579 UnlockRelationOid(oldRelId, lockmode);
580 }
581
582 /*
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
587 * lingering.
588 */
589 if (!OidIsValid(relId))
591 else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED)))
592 LockRelationOid(relId, lockmode);
593 else if (!ConditionalLockRelationOid(relId, lockmode))
594 {
595 int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR;
596
597 if (relation->schemaname)
598 ereport(elevel,
599 (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
600 errmsg("could not obtain lock on relation \"%s.%s\"",
601 relation->schemaname, relation->relname)));
602 else
603 ereport(elevel,
604 (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
605 errmsg("could not obtain lock on relation \"%s\"",
606 relation->relname)));
607
608 return InvalidOid;
609 }
610
611 /*
612 * If no invalidation message were processed, we're done!
613 */
614 if (inval_count == SharedInvalidMessageCounter)
615 break;
616
617 /*
618 * Something may have changed. Let's repeat the name lookup, to make
619 * sure this name still references the same relation it did
620 * previously.
621 */
622 retry = true;
623 oldRelId = relId;
624 }
625
626 if (!OidIsValid(relId))
627 {
628 int elevel = missing_ok ? DEBUG1 : ERROR;
629
630 if (relation->schemaname)
631 ereport(elevel,
633 errmsg("relation \"%s.%s\" does not exist",
634 relation->schemaname, relation->relname)));
635 else
636 ereport(elevel,
638 errmsg("relation \"%s\" does not exist",
639 relation->relname)));
640 }
641 return relId;
642}
#define DEBUG1
Definition: elog.h:30
void AcceptInvalidationMessages(void)
Definition: inval.c:863
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:150
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:885
@ RVR_SKIP_LOCKED
Definition: namespace.h:74
@ RVR_NOWAIT
Definition: namespace.h:73
@ RVR_MISSING_OK
Definition: namespace.h:72
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

References AcceptInvalidationMessages(), Assert, callback(), RangeVar::catalogname, ConditionalLockRelationOid(), DEBUG1, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, get_database_name(), get_relname_relid(), InvalidOid, LockRelationOid(), LookupExplicitNamespace(), MyDatabaseId, myTempNamespace, NoLock, OidIsValid, RangeVar::relname, RelnameGetRelid(), RangeVar::relpersistence, RVR_MISSING_OK, RVR_NOWAIT, RVR_SKIP_LOCKED, RangeVar::schemaname, SharedInvalidMessageCounter, and UnlockRelationOid().

Referenced by AlterPolicy(), AlterSequence(), AlterTableLookupRelation(), AlterTableNamespace(), ATExecAttachPartitionIdx(), cluster(), CreatePolicy(), ExecRefreshMatView(), ExecuteTruncate(), expand_vacuum_rel(), LockTableCommand(), ProcessUtilitySlow(), ReindexIndex(), ReindexTable(), RemoveRelations(), rename_policy(), renameatt(), RenameConstraint(), RenameRelation(), RenameRewriteRule(), and renametrig().

◆ recomputeNamespacePath()

static void recomputeNamespacePath ( void  )
static

Definition at line 4299 of file namespace.c.

4300{
4301 Oid roleid = GetUserId();
4302 bool pathChanged;
4303 const SearchPathCacheEntry *entry;
4304
4305 /* Do nothing if path is already valid. */
4306 if (baseSearchPathValid && namespaceUser == roleid)
4307 return;
4308
4310
4311 if (baseCreationNamespace == entry->firstNS &&
4314 {
4315 pathChanged = false;
4316 }
4317 else
4318 {
4319 MemoryContext oldcxt;
4320 List *newpath;
4321
4322 pathChanged = true;
4323
4324 /* Must save OID list in permanent storage. */
4326 newpath = list_copy(entry->finalPath);
4327 MemoryContextSwitchTo(oldcxt);
4328
4329 /* Now safe to assign to state variables. */
4331 baseSearchPath = newpath;
4334 }
4335
4336 /* Mark the path valid. */
4337 baseSearchPathValid = true;
4338 namespaceUser = roleid;
4339
4340 /* And make it active. */
4344
4345 /*
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.)
4348 */
4349 if (pathChanged)
4351}
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
static const SearchPathCacheEntry * cachedNamespacePath(const char *searchPath, Oid roleid)
Definition: namespace.c:4244
char * namespace_search_path
Definition: namespace.c:211

References activeCreationNamespace, activePathGeneration, activeSearchPath, activeTempCreationPending, baseCreationNamespace, baseSearchPath, baseSearchPathValid, baseTempCreationPending, cachedNamespacePath(), equal(), SearchPathCacheEntry::finalPath, SearchPathCacheEntry::firstNS, GetUserId(), list_copy(), list_free(), MemoryContextSwitchTo(), namespace_search_path, namespaceUser, SearchPathCacheEntry::temp_missing, and TopMemoryContext.

Referenced by CollationGetCollid(), CollationIsVisibleExt(), ConversionGetConid(), ConversionIsVisibleExt(), fetch_search_path(), fetch_search_path_array(), FindDefaultConversionProc(), FuncnameGetCandidates(), FunctionIsVisibleExt(), get_collation_oid(), get_conversion_oid(), get_statistics_object_oid(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), GetSearchPathMatcher(), OpclassIsVisibleExt(), OpclassnameGetOpcid(), OperatorIsVisibleExt(), OpernameGetCandidates(), OpernameGetOprid(), OpfamilyIsVisibleExt(), OpfamilynameGetOpfid(), QualifiedNameGetCreationNamespace(), RangeVarGetCreationNamespace(), RelationIsVisibleExt(), RelnameGetRelid(), SearchPathMatchesCurrentEnvironment(), StatisticsObjIsVisibleExt(), TSConfigIsVisibleExt(), TSDictionaryIsVisibleExt(), TSParserIsVisibleExt(), TSTemplateIsVisibleExt(), TypeIsVisibleExt(), and TypenameGetTypidExtended().

◆ RelationIsVisible()

bool RelationIsVisible ( Oid  relid)

Definition at line 913 of file namespace.c.

914{
915 return RelationIsVisibleExt(relid, NULL);
916}

References RelationIsVisibleExt().

Referenced by generate_relation_name(), getRelationDescription(), and regclassout().

◆ RelationIsVisibleExt()

static bool RelationIsVisibleExt ( Oid  relid,
bool *  is_missing 
)
static

Definition at line 925 of file namespace.c.

926{
927 HeapTuple reltup;
928 Form_pg_class relform;
929 Oid relnamespace;
930 bool visible;
931
932 reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
933 if (!HeapTupleIsValid(reltup))
934 {
935 if (is_missing != NULL)
936 {
937 *is_missing = true;
938 return false;
939 }
940 elog(ERROR, "cache lookup failed for relation %u", relid);
941 }
942 relform = (Form_pg_class) GETSTRUCT(reltup);
943
945
946 /*
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.
950 */
951 relnamespace = relform->relnamespace;
952 if (relnamespace != PG_CATALOG_NAMESPACE &&
953 !list_member_oid(activeSearchPath, relnamespace))
954 visible = false;
955 else
956 {
957 /*
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.
961 */
962 char *relname = NameStr(relform->relname);
963 ListCell *l;
964
965 visible = false;
966 foreach(l, activeSearchPath)
967 {
968 Oid namespaceId = lfirst_oid(l);
969
970 if (namespaceId == relnamespace)
971 {
972 /* Found it first in path */
973 visible = true;
974 break;
975 }
976 if (OidIsValid(get_relname_relid(relname, namespaceId)))
977 {
978 /* Found something else first in path */
979 break;
980 }
981 }
982 }
983
984 ReleaseSysCache(reltup);
985
986 return visible;
987}
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153

References activeSearchPath, elog, ERROR, get_relname_relid(), GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), NameStr, ObjectIdGetDatum(), OidIsValid, recomputeNamespacePath(), ReleaseSysCache(), relname, and SearchSysCache1().

Referenced by pg_table_is_visible(), and RelationIsVisible().

◆ RelnameGetRelid()

Oid RelnameGetRelid ( const char *  relname)

Definition at line 885 of file namespace.c.

886{
887 Oid relid;
888 ListCell *l;
889
891
892 foreach(l, activeSearchPath)
893 {
894 Oid namespaceId = lfirst_oid(l);
895
896 relid = get_relname_relid(relname, namespaceId);
897 if (OidIsValid(relid))
898 return relid;
899 }
900
901 /* Not found in path */
902 return InvalidOid;
903}

References activeSearchPath, get_relname_relid(), InvalidOid, lfirst_oid, OidIsValid, recomputeNamespacePath(), and relname.

Referenced by plpgsql_parse_wordrowtype(), and RangeVarGetRelidExtended().

◆ RemoveTempRelations()

static void RemoveTempRelations ( Oid  tempNamespaceId)
static

Definition at line 4598 of file namespace.c.

4599{
4600 ObjectAddress object;
4601
4602 /*
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
4607 * own temp objects.
4608 */
4609 object.classId = NamespaceRelationId;
4610 object.objectId = tempNamespaceId;
4611 object.objectSubId = 0;
4612
4618}
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:273
#define PERFORM_DELETION_SKIP_EXTENSIONS
Definition: dependency.h:96
#define PERFORM_DELETION_QUIETLY
Definition: dependency.h:94
#define PERFORM_DELETION_SKIP_ORIGINAL
Definition: dependency.h:95
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:92
@ DROP_CASCADE
Definition: parsenodes.h:2386

References ObjectAddress::classId, DROP_CASCADE, PERFORM_DELETION_INTERNAL, PERFORM_DELETION_QUIETLY, PERFORM_DELETION_SKIP_EXTENSIONS, PERFORM_DELETION_SKIP_ORIGINAL, and performDeletion().

Referenced by InitTempTableNamespace(), RemoveTempRelationsCallback(), and ResetTempTableNamespace().

◆ RemoveTempRelationsCallback()

static void RemoveTempRelationsCallback ( int  code,
Datum  arg 
)
static

Definition at line 4624 of file namespace.c.

4625{
4626 if (OidIsValid(myTempNamespace)) /* should always be true */
4627 {
4628 /* Need to ensure we have a usable transaction. */
4632
4634
4637 }
4638}
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:212
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:610
void PopActiveSnapshot(void)
Definition: snapmgr.c:703
void StartTransactionCommand(void)
Definition: xact.c:3051
void CommitTransactionCommand(void)
Definition: xact.c:3149
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4854

References AbortOutOfAnyTransaction(), CommitTransactionCommand(), GetTransactionSnapshot(), myTempNamespace, OidIsValid, PopActiveSnapshot(), PushActiveSnapshot(), RemoveTempRelations(), and StartTransactionCommand().

Referenced by AtEOXact_Namespace().

◆ ResetTempTableNamespace()

void ResetTempTableNamespace ( void  )

Definition at line 4644 of file namespace.c.

References myTempNamespace, OidIsValid, and RemoveTempRelations().

Referenced by DiscardAll(), and DiscardCommand().

◆ SearchPathMatchesCurrentEnvironment()

bool SearchPathMatchesCurrentEnvironment ( SearchPathMatcher path)

Definition at line 3911 of file namespace.c.

3912{
3913 ListCell *lc,
3914 *lcp;
3915
3917
3918 /* Quick out if already known equal to active path. */
3919 if (path->generation == activePathGeneration)
3920 return true;
3921
3922 /* We scan down the activeSearchPath to see if it matches the input. */
3924
3925 /* If path->addTemp, first item should be my temp namespace. */
3926 if (path->addTemp)
3927 {
3928 if (lc && lfirst_oid(lc) == myTempNamespace)
3929 lc = lnext(activeSearchPath, lc);
3930 else
3931 return false;
3932 }
3933 /* If path->addCatalog, next item should be pg_catalog. */
3934 if (path->addCatalog)
3935 {
3936 if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
3937 lc = lnext(activeSearchPath, lc);
3938 else
3939 return false;
3940 }
3941 /* We should now be looking at the activeCreationNamespace. */
3942 if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
3943 return false;
3944 /* The remainder of activeSearchPath should match path->schemas. */
3945 foreach(lcp, path->schemas)
3946 {
3947 if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
3948 lc = lnext(activeSearchPath, lc);
3949 else
3950 return false;
3951 }
3952 if (lc)
3953 return false;
3954
3955 /*
3956 * Update path->generation so that future tests will return quickly, so
3957 * long as the active search path doesn't change.
3958 */
3960
3961 return true;
3962}
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

References activeCreationNamespace, activePathGeneration, activeSearchPath, SearchPathMatcher::addCatalog, SearchPathMatcher::addTemp, SearchPathMatcher::generation, InvalidOid, lfirst_oid, list_head(), lnext(), myTempNamespace, recomputeNamespacePath(), and SearchPathMatcher::schemas.

Referenced by CachedPlanAllowsSimpleValidityCheck(), CachedPlanIsSimplyValid(), and RevalidateCachedQuery().

◆ SetTempNamespaceState()

void SetTempNamespaceState ( Oid  tempNamespaceId,
Oid  tempToastNamespaceId 
)

Definition at line 3821 of file namespace.c.

3822{
3823 /* Worker should not have created its own namespaces ... */
3827
3828 /* Assign same namespace OIDs that leader has */
3829 myTempNamespace = tempNamespaceId;
3830 myTempToastNamespace = tempToastNamespaceId;
3831
3832 /*
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
3836 * to destroy it.
3837 */
3838
3839 baseSearchPathValid = false; /* may need to rebuild list */
3840 searchPathCacheValid = false;
3841}

References Assert, baseSearchPathValid, InvalidOid, InvalidSubTransactionId, myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, and searchPathCacheValid.

Referenced by ParallelWorkerMain().

◆ spcache_init()

static void spcache_init ( void  )
static

Definition at line 306 of file namespace.c.

307{
310 return;
311
312 searchPathCacheValid = false;
313 baseSearchPathValid = false;
314
315 /*
316 * Make sure we don't leave dangling pointers if a failure happens during
317 * initialization.
318 */
319 SearchPathCache = NULL;
321
322 if (SearchPathCacheContext == NULL)
323 {
324 /* Make the context we'll keep search path cache hashtable in */
326 "search_path processing cache",
328 }
329 else
330 {
332 }
333
334 /* arbitrary initial starting size of 16 elements */
335 SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL);
337}
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static SearchPathCacheEntry * LastSearchPathCacheEntry
Definition: namespace.c:300
#define SPCACHE_RESET_THRESHOLD
Definition: namespace.c:297
static nsphash_hash * SearchPathCache
Definition: namespace.c:299

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, baseSearchPathValid, LastSearchPathCacheEntry, MemoryContextReset(), SearchPathCache, SearchPathCacheContext, searchPathCacheValid, SPCACHE_RESET_THRESHOLD, and TopMemoryContext.

Referenced by cachedNamespacePath(), and check_search_path().

◆ spcache_insert()

static SearchPathCacheEntry * spcache_insert ( const char *  searchPath,
Oid  roleid 
)
static

Definition at line 374 of file namespace.c.

375{
378 strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
379 {
381 }
382 else
383 {
385 SearchPathCacheKey cachekey = {
386 .searchPath = searchPath,
387 .roleid = roleid
388 };
389
390 /*
391 * searchPath is not saved in SearchPathCacheContext. First perform a
392 * lookup, and copy searchPath only if we need to create a new entry.
393 */
394 entry = nsphash_lookup(SearchPathCache, cachekey);
395
396 if (!entry)
397 {
398 bool found;
399
401 entry = nsphash_insert(SearchPathCache, cachekey, &found);
402 Assert(!found);
403
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 */
410 }
411
413 return entry;
414 }
415}
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1683
SearchPathCacheKey key
Definition: namespace.c:175
const char * searchPath
Definition: namespace.c:169

References Assert, SearchPathCacheEntry::finalPath, SearchPathCacheEntry::firstNS, SearchPathCacheEntry::forceRecompute, InvalidOid, SearchPathCacheEntry::key, LastSearchPathCacheEntry, MemoryContextStrdup(), NIL, SearchPathCacheEntry::oidlist, SearchPathCacheKey::roleid, SearchPathCacheKey::searchPath, SearchPathCache, SearchPathCacheContext, and SearchPathCacheEntry::temp_missing.

Referenced by cachedNamespacePath(), and check_search_path().

◆ spcache_lookup()

static SearchPathCacheEntry * spcache_lookup ( const char *  searchPath,
Oid  roleid 
)
static

Definition at line 344 of file namespace.c.

345{
348 strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
349 {
351 }
352 else
353 {
355 SearchPathCacheKey cachekey = {
356 .searchPath = searchPath,
357 .roleid = roleid
358 };
359
360 entry = nsphash_lookup(SearchPathCache, cachekey);
361 if (entry)
363 return entry;
364 }
365}

References SearchPathCacheEntry::key, LastSearchPathCacheEntry, SearchPathCacheKey::roleid, SearchPathCacheKey::searchPath, and SearchPathCache.

Referenced by check_search_path().

◆ spcachekey_equal()

static bool spcachekey_equal ( SearchPathCacheKey  a,
SearchPathCacheKey  b 
)
inlinestatic

Definition at line 274 of file namespace.c.

275{
276 return a.roleid == b.roleid &&
277 strcmp(a.searchPath, b.searchPath) == 0;
278}
int b
Definition: isn.c:69
int a
Definition: isn.c:68

References a, and b.

◆ spcachekey_hash()

static uint32 spcachekey_hash ( SearchPathCacheKey  key)
inlinestatic

Definition at line 254 of file namespace.c.

255{
257 int sp_len;
258
259 fasthash_init(&hs, 0);
260
261 hs.accum = key.roleid;
262 fasthash_combine(&hs);
263
264 /*
265 * Combine search path into the hash and save the length for tweaking the
266 * final mix.
267 */
268 sp_len = fasthash_accum_cstring(&hs, key.searchPath);
269
270 return fasthash_final32(&hs, sp_len);
271}
static size_t fasthash_accum_cstring(fasthash_state *hs, const char *str)
static uint32 fasthash_final32(fasthash_state *hs, uint64 tweak)
static void fasthash_combine(fasthash_state *hs)
static void fasthash_init(fasthash_state *hs, uint64 seed)

References fasthash_state::accum, fasthash_accum_cstring(), fasthash_combine(), fasthash_final32(), fasthash_init(), and sort-test::key.

◆ StatisticsObjIsVisible()

bool StatisticsObjIsVisible ( Oid  stxid)

Definition at line 2632 of file namespace.c.

2633{
2634 return StatisticsObjIsVisibleExt(stxid, NULL);
2635}

References StatisticsObjIsVisibleExt().

Referenced by getObjectDescription().

◆ StatisticsObjIsVisibleExt()

static bool StatisticsObjIsVisibleExt ( Oid  stxid,
bool *  is_missing 
)
static

Definition at line 2644 of file namespace.c.

2645{
2646 HeapTuple stxtup;
2647 Form_pg_statistic_ext stxform;
2648 Oid stxnamespace;
2649 bool visible;
2650
2651 stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stxid));
2652 if (!HeapTupleIsValid(stxtup))
2653 {
2654 if (is_missing != NULL)
2655 {
2656 *is_missing = true;
2657 return false;
2658 }
2659 elog(ERROR, "cache lookup failed for statistics object %u", stxid);
2660 }
2661 stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
2662
2664
2665 /*
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.
2669 */
2670 stxnamespace = stxform->stxnamespace;
2671 if (stxnamespace != PG_CATALOG_NAMESPACE &&
2672 !list_member_oid(activeSearchPath, stxnamespace))
2673 visible = false;
2674 else
2675 {
2676 /*
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.
2680 */
2681 char *stxname = NameStr(stxform->stxname);
2682 ListCell *l;
2683
2684 visible = false;
2685 foreach(l, activeSearchPath)
2686 {
2687 Oid namespaceId = lfirst_oid(l);
2688
2689 if (namespaceId == stxnamespace)
2690 {
2691 /* Found it first in path */
2692 visible = true;
2693 break;
2694 }
2695 if (SearchSysCacheExists2(STATEXTNAMENSP,
2696 PointerGetDatum(stxname),
2697 ObjectIdGetDatum(namespaceId)))
2698 {
2699 /* Found something else first in path */
2700 break;
2701 }
2702 }
2703 }
2704
2705 ReleaseSysCache(stxtup);
2706
2707 return visible;
2708}
FormData_pg_statistic_ext * Form_pg_statistic_ext
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:102

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), NameStr, ObjectIdGetDatum(), PointerGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCacheExists2.

Referenced by pg_statistics_obj_is_visible(), and StatisticsObjIsVisible().

◆ TSConfigIsVisible()

bool TSConfigIsVisible ( Oid  cfgid)

Definition at line 3210 of file namespace.c.

3211{
3212 return TSConfigIsVisibleExt(cfgid, NULL);
3213}

References TSConfigIsVisibleExt().

Referenced by getObjectDescription(), and regconfigout().

◆ TSConfigIsVisibleExt()

static bool TSConfigIsVisibleExt ( Oid  cfgid,
bool *  is_missing 
)
static

Definition at line 3222 of file namespace.c.

3223{
3224 HeapTuple tup;
3225 Form_pg_ts_config form;
3226 Oid namespace;
3227 bool visible;
3228
3229 tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
3230 if (!HeapTupleIsValid(tup))
3231 {
3232 if (is_missing != NULL)
3233 {
3234 *is_missing = true;
3235 return false;
3236 }
3237 elog(ERROR, "cache lookup failed for text search configuration %u",
3238 cfgid);
3239 }
3240 form = (Form_pg_ts_config) GETSTRUCT(tup);
3241
3243
3244 /*
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.
3248 */
3249 namespace = form->cfgnamespace;
3250 if (namespace != PG_CATALOG_NAMESPACE &&
3251 !list_member_oid(activeSearchPath, namespace))
3252 visible = false;
3253 else
3254 {
3255 /*
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.
3259 */
3260 char *name = NameStr(form->cfgname);
3261 ListCell *l;
3262
3263 visible = false;
3264 foreach(l, activeSearchPath)
3265 {
3266 Oid namespaceId = lfirst_oid(l);
3267
3268 if (namespaceId == myTempNamespace)
3269 continue; /* do not look in temp namespace */
3270
3271 if (namespaceId == namespace)
3272 {
3273 /* Found it first in path */
3274 visible = true;
3275 break;
3276 }
3277 if (SearchSysCacheExists2(TSCONFIGNAMENSP,
3279 ObjectIdGetDatum(namespaceId)))
3280 {
3281 /* Found something else first in path */
3282 break;
3283 }
3284 }
3285 }
3286
3287 ReleaseSysCache(tup);
3288
3289 return visible;
3290}
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), myTempNamespace, name, NameStr, ObjectIdGetDatum(), PointerGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCacheExists2.

Referenced by pg_ts_config_is_visible(), and TSConfigIsVisible().

◆ TSDictionaryIsVisible()

bool TSDictionaryIsVisible ( Oid  dictId)

Definition at line 2919 of file namespace.c.

2920{
2921 return TSDictionaryIsVisibleExt(dictId, NULL);
2922}

References TSDictionaryIsVisibleExt().

Referenced by getObjectDescription(), and regdictionaryout().

◆ TSDictionaryIsVisibleExt()

static bool TSDictionaryIsVisibleExt ( Oid  dictId,
bool *  is_missing 
)
static

Definition at line 2931 of file namespace.c.

2932{
2933 HeapTuple tup;
2934 Form_pg_ts_dict form;
2935 Oid namespace;
2936 bool visible;
2937
2938 tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
2939 if (!HeapTupleIsValid(tup))
2940 {
2941 if (is_missing != NULL)
2942 {
2943 *is_missing = true;
2944 return false;
2945 }
2946 elog(ERROR, "cache lookup failed for text search dictionary %u",
2947 dictId);
2948 }
2949 form = (Form_pg_ts_dict) GETSTRUCT(tup);
2950
2952
2953 /*
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.
2957 */
2958 namespace = form->dictnamespace;
2959 if (namespace != PG_CATALOG_NAMESPACE &&
2960 !list_member_oid(activeSearchPath, namespace))
2961 visible = false;
2962 else
2963 {
2964 /*
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.
2968 */
2969 char *name = NameStr(form->dictname);
2970 ListCell *l;
2971
2972 visible = false;
2973 foreach(l, activeSearchPath)
2974 {
2975 Oid namespaceId = lfirst_oid(l);
2976
2977 if (namespaceId == myTempNamespace)
2978 continue; /* do not look in temp namespace */
2979
2980 if (namespaceId == namespace)
2981 {
2982 /* Found it first in path */
2983 visible = true;
2984 break;
2985 }
2986 if (SearchSysCacheExists2(TSDICTNAMENSP,
2988 ObjectIdGetDatum(namespaceId)))
2989 {
2990 /* Found something else first in path */
2991 break;
2992 }
2993 }
2994 }
2995
2996 ReleaseSysCache(tup);
2997
2998 return visible;
2999}
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), myTempNamespace, name, NameStr, ObjectIdGetDatum(), PointerGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCacheExists2.

Referenced by pg_ts_dict_is_visible(), and TSDictionaryIsVisible().

◆ TSParserIsVisible()

bool TSParserIsVisible ( Oid  prsId)

Definition at line 2774 of file namespace.c.

2775{
2776 return TSParserIsVisibleExt(prsId, NULL);
2777}

References TSParserIsVisibleExt().

Referenced by getObjectDescription().

◆ TSParserIsVisibleExt()

static bool TSParserIsVisibleExt ( Oid  prsId,
bool *  is_missing 
)
static

Definition at line 2786 of file namespace.c.

2787{
2788 HeapTuple tup;
2789 Form_pg_ts_parser form;
2790 Oid namespace;
2791 bool visible;
2792
2793 tup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
2794 if (!HeapTupleIsValid(tup))
2795 {
2796 if (is_missing != NULL)
2797 {
2798 *is_missing = true;
2799 return false;
2800 }
2801 elog(ERROR, "cache lookup failed for text search parser %u", prsId);
2802 }
2803 form = (Form_pg_ts_parser) GETSTRUCT(tup);
2804
2806
2807 /*
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.
2811 */
2812 namespace = form->prsnamespace;
2813 if (namespace != PG_CATALOG_NAMESPACE &&
2814 !list_member_oid(activeSearchPath, namespace))
2815 visible = false;
2816 else
2817 {
2818 /*
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.
2822 */
2823 char *name = NameStr(form->prsname);
2824 ListCell *l;
2825
2826 visible = false;
2827 foreach(l, activeSearchPath)
2828 {
2829 Oid namespaceId = lfirst_oid(l);
2830
2831 if (namespaceId == myTempNamespace)
2832 continue; /* do not look in temp namespace */
2833
2834 if (namespaceId == namespace)
2835 {
2836 /* Found it first in path */
2837 visible = true;
2838 break;
2839 }
2840 if (SearchSysCacheExists2(TSPARSERNAMENSP,
2842 ObjectIdGetDatum(namespaceId)))
2843 {
2844 /* Found something else first in path */
2845 break;
2846 }
2847 }
2848 }
2849
2850 ReleaseSysCache(tup);
2851
2852 return visible;
2853}
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), myTempNamespace, name, NameStr, ObjectIdGetDatum(), PointerGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCacheExists2.

Referenced by pg_ts_parser_is_visible(), and TSParserIsVisible().

◆ TSTemplateIsVisible()

bool TSTemplateIsVisible ( Oid  tmplId)

Definition at line 3065 of file namespace.c.

3066{
3067 return TSTemplateIsVisibleExt(tmplId, NULL);
3068}

References TSTemplateIsVisibleExt().

Referenced by getObjectDescription().

◆ TSTemplateIsVisibleExt()

static bool TSTemplateIsVisibleExt ( Oid  tmplId,
bool *  is_missing 
)
static

Definition at line 3077 of file namespace.c.

3078{
3079 HeapTuple tup;
3081 Oid namespace;
3082 bool visible;
3083
3084 tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
3085 if (!HeapTupleIsValid(tup))
3086 {
3087 if (is_missing != NULL)
3088 {
3089 *is_missing = true;
3090 return false;
3091 }
3092 elog(ERROR, "cache lookup failed for text search template %u", tmplId);
3093 }
3094 form = (Form_pg_ts_template) GETSTRUCT(tup);
3095
3097
3098 /*
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.
3102 */
3103 namespace = form->tmplnamespace;
3104 if (namespace != PG_CATALOG_NAMESPACE &&
3105 !list_member_oid(activeSearchPath, namespace))
3106 visible = false;
3107 else
3108 {
3109 /*
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.
3113 */
3114 char *name = NameStr(form->tmplname);
3115 ListCell *l;
3116
3117 visible = false;
3118 foreach(l, activeSearchPath)
3119 {
3120 Oid namespaceId = lfirst_oid(l);
3121
3122 if (namespaceId == myTempNamespace)
3123 continue; /* do not look in temp namespace */
3124
3125 if (namespaceId == namespace)
3126 {
3127 /* Found it first in path */
3128 visible = true;
3129 break;
3130 }
3131 if (SearchSysCacheExists2(TSTEMPLATENAMENSP,
3133 ObjectIdGetDatum(namespaceId)))
3134 {
3135 /* Found something else first in path */
3136 break;
3137 }
3138 }
3139 }
3140
3141 ReleaseSysCache(tup);
3142
3143 return visible;
3144}
FormData_pg_ts_template * Form_pg_ts_template

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), myTempNamespace, name, NameStr, ObjectIdGetDatum(), PointerGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCacheExists2.

Referenced by pg_ts_template_is_visible(), and TSTemplateIsVisible().

◆ TypeIsVisible()

bool TypeIsVisible ( Oid  typid)

Definition at line 1040 of file namespace.c.

1041{
1042 return TypeIsVisibleExt(typid, NULL);
1043}

References TypeIsVisibleExt().

Referenced by format_type_extended().

◆ TypeIsVisibleExt()

static bool TypeIsVisibleExt ( Oid  typid,
bool *  is_missing 
)
static

Definition at line 1052 of file namespace.c.

1053{
1054 HeapTuple typtup;
1055 Form_pg_type typform;
1056 Oid typnamespace;
1057 bool visible;
1058
1059 typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1060 if (!HeapTupleIsValid(typtup))
1061 {
1062 if (is_missing != NULL)
1063 {
1064 *is_missing = true;
1065 return false;
1066 }
1067 elog(ERROR, "cache lookup failed for type %u", typid);
1068 }
1069 typform = (Form_pg_type) GETSTRUCT(typtup);
1070
1072
1073 /*
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.
1077 */
1078 typnamespace = typform->typnamespace;
1079 if (typnamespace != PG_CATALOG_NAMESPACE &&
1080 !list_member_oid(activeSearchPath, typnamespace))
1081 visible = false;
1082 else
1083 {
1084 /*
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.
1088 */
1089 char *typname = NameStr(typform->typname);
1090 ListCell *l;
1091
1092 visible = false;
1093 foreach(l, activeSearchPath)
1094 {
1095 Oid namespaceId = lfirst_oid(l);
1096
1097 if (namespaceId == typnamespace)
1098 {
1099 /* Found it first in path */
1100 visible = true;
1101 break;
1102 }
1103 if (SearchSysCacheExists2(TYPENAMENSP,
1105 ObjectIdGetDatum(namespaceId)))
1106 {
1107 /* Found something else first in path */
1108 break;
1109 }
1110 }
1111 }
1112
1113 ReleaseSysCache(typtup);
1114
1115 return visible;
1116}
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41

References activeSearchPath, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_member_oid(), NameStr, ObjectIdGetDatum(), PointerGetDatum(), recomputeNamespacePath(), ReleaseSysCache(), SearchSysCache1(), SearchSysCacheExists2, and typname.

Referenced by pg_type_is_visible(), and TypeIsVisible().

◆ TypenameGetTypid()

Oid TypenameGetTypid ( const char *  typname)

Definition at line 995 of file namespace.c.

996{
997 return TypenameGetTypidExtended(typname, true);
998}
Oid TypenameGetTypidExtended(const char *typname, bool temp_ok)
Definition: namespace.c:1008

References TypenameGetTypidExtended(), and typname.

◆ TypenameGetTypidExtended()

Oid TypenameGetTypidExtended ( const char *  typname,
bool  temp_ok 
)

Definition at line 1008 of file namespace.c.

1009{
1010 Oid typid;
1011 ListCell *l;
1012
1014
1015 foreach(l, activeSearchPath)
1016 {
1017 Oid namespaceId = lfirst_oid(l);
1018
1019 if (!temp_ok && namespaceId == myTempNamespace)
1020 continue; /* do not look in temp namespace */
1021
1022 typid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
1024 ObjectIdGetDatum(namespaceId));
1025 if (OidIsValid(typid))
1026 return typid;
1027 }
1028
1029 /* Not found in path */
1030 return InvalidOid;
1031}

References activeSearchPath, GetSysCacheOid2, InvalidOid, lfirst_oid, myTempNamespace, ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), recomputeNamespacePath(), and typname.

Referenced by LookupTypeNameExtended(), and TypenameGetTypid().

Variable Documentation

◆ activeCreationNamespace

◆ activePathGeneration

uint64 activePathGeneration = 1
static

◆ activeSearchPath

◆ activeTempCreationPending

bool activeTempCreationPending = false
static

◆ baseCreationNamespace

Oid baseCreationNamespace = InvalidOid
static

Definition at line 151 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ baseSearchPath

List* baseSearchPath = NIL
static

Definition at line 149 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ baseSearchPathValid

◆ baseTempCreationPending

bool baseTempCreationPending = false
static

Definition at line 153 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ LastSearchPathCacheEntry

SearchPathCacheEntry* LastSearchPathCacheEntry = NULL
static

Definition at line 300 of file namespace.c.

Referenced by spcache_init(), spcache_insert(), and spcache_lookup().

◆ myTempNamespace

◆ myTempNamespaceSubID

◆ myTempToastNamespace

◆ namespace_search_path

char* namespace_search_path = NULL

Definition at line 211 of file namespace.c.

Referenced by CreateSchemaCommand(), and recomputeNamespacePath().

◆ namespaceUser

Oid namespaceUser = InvalidOid
static

Definition at line 155 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ SearchPathCache

nsphash_hash* SearchPathCache = NULL
static

Definition at line 299 of file namespace.c.

Referenced by spcache_init(), spcache_insert(), and spcache_lookup().

◆ SearchPathCacheContext

MemoryContext SearchPathCacheContext = NULL
static

Definition at line 165 of file namespace.c.

Referenced by cachedNamespacePath(), check_search_path(), spcache_init(), and spcache_insert().

◆ searchPathCacheValid