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:802
unsigned int Oid
Definition: postgres_ext.h:31

◆ 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:766
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:849
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:451
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:649
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:36
PGPROC * MyProc
Definition: proc.c:67
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  */
4522  if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
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:126
void list_free(List *list)
Definition: list.c:1546
static List * finalNamespacePath(List *oidlist, Oid *firstNS)
Definition: namespace.c:4198
static MemoryContext SearchPathCacheContext
Definition: namespace.c:165
static void spcache_init(void)
Definition: namespace.c:306
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
object_access_hook_type object_access_hook
Definition: objectaccess.c:22
#define NIL
Definition: pg_list.h:68
MemoryContextSwitchTo(old_ctx)

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:514
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)
3740  return TEMP_NAMESPACE_NOT_TEMP;
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:3142
#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 }
signed int int32
Definition: c.h:496
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:737
#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:252
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:322
#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 
4232  if (OidIsValid(myTempNamespace) &&
4233  !list_member_oid(finalPath, myTempNamespace))
4234  finalPath = lcons_oid(myTempNamespace, finalPath);
4235 
4236  return finalPath;
4237 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
List * lcons_oid(Oid datum, List *list)
Definition: list.c:531
#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:989
#define funcname
Definition: indent_codes.h:69
int j
Definition: isn.c:74
int i
Definition: isn.c:73
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:64
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
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:596
#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",
4017  NameListToString(collname), GetDatabaseEncodingName())));
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;
3876  result->generation = activePathGeneration;
3877 
3878  MemoryContextSwitchTo(oldcxt);
3879 
3880  return result;
3881 }
void * palloc0(Size size)
Definition: mcxt.c:1347
static uint64 activePathGeneration
Definition: namespace.c:145
tree context
Definition: radixtree.h:1835

References activeCreationNamespace, activePathGeneration, activeSearchPath, SearchPathMatcher::addCatalog, SearchPathMatcher::addTemp, Assert, context, 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;
4750  baseTempCreationPending = false;
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 */
4781  CacheRegisterSyscacheCallback(DATABASEOID,
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:1516
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:3891
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:6333

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)

Definition at line 3649 of file namespace.c.

3650 {
3651  if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
3652  return true;
3653  return false;
3654 }

References myTempNamespace, and OidIsValid.

Referenced by CreateExtensionInternal(), EventTriggerSQLDropAddObject(), ExecCheckXactReadOnly(), get_namespace_name_or_temp(), pg_namespace_aclmask_ext(), ReindexMultipleTables(), and RemoveObjects().

◆ isTempOrTempToastNamespace()

bool isTempOrTempToastNamespace ( Oid  namespaceId)

Definition at line 3673 of file namespace.c.

3674 {
3675  if (OidIsValid(myTempNamespace) &&
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 {
3663  if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
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
2354  collid = InvalidOid;
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:212
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 */
3437  AccessTempTableNamespace(false);
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:2703
@ OBJECT_SCHEMA
Definition: parsenodes.h:2294
#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:424
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:3459
@ FUNC_PARAM_INOUT
Definition: parsenodes.h:3461
@ FUNC_PARAM_VARIADIC
Definition: parsenodes.h:3462
#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:12840
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

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))
3609  appendStringInfoString(&string, strVal(name));
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)
4987  PG_RETURN_NULL();
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)
5001  PG_RETURN_NULL();
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)
4931  PG_RETURN_NULL();
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)
4959  PG_RETURN_NULL();
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)
4945  PG_RETURN_NULL();
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)
4973  PG_RETURN_NULL();
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)
5015  PG_RETURN_NULL();
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)
4903  PG_RETURN_NULL();
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)
5071  PG_RETURN_NULL();
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)
5043  PG_RETURN_NULL();
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)
5029  PG_RETURN_NULL();
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)
5057  PG_RETURN_NULL();
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)
4917  PG_RETURN_NULL();
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,
4154  ACL_USAGE) == ACLCHECK_OK)
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,
4176  ACL_USAGE) == ACLCHECK_OK)
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 */
3501  AccessTempTableNamespace(false);
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  {
854  ereport(ERROR,
855  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
856  errmsg("cannot create relations in temporary schemas of other sessions")));
857  else
858  ereport(ERROR,
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))
867  ereport(ERROR,
868  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
869  errmsg("cannot create relations in temporary schemas of other sessions")));
870  break;
871  default:
873  ereport(ERROR,
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)
756  ereport(ERROR,
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:4145
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:227
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:994
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1053
#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)
664  ereport(ERROR,
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))
702  ereport(ERROR,
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)
460  ereport(ERROR,
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)
517  ereport(ERROR,
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:806
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:151
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 
4309  entry = cachedNamespacePath(namespace_search_path, roleid);
4310 
4311  if (baseCreationNamespace == entry->firstNS &&
4313  equal(entry->finalPath, baseSearchPath))
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;
4332  baseCreationNamespace = entry->firstNS;
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 
4613  performDeletion(&object, DROP_CASCADE,
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:2332

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:216
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
void StartTransactionCommand(void)
Definition: xact.c:3039
void CommitTransactionCommand(void)
Definition: xact.c:3137
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4855

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.

4645 {
4648 }

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);
336  searchPathCacheValid = true;
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 {
377  LastSearchPathCacheEntry->key.roleid == roleid &&
378  strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
379  {
381  }
382  else
383  {
384  SearchPathCacheEntry *entry;
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 
400  cachekey.searchPath = MemoryContextStrdup(SearchPathCacheContext, searchPath);
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 
412  LastSearchPathCacheEntry = entry;
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 {
347  LastSearchPathCacheEntry->key.roleid == roleid &&
348  strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
349  {
351  }
352  else
353  {
354  SearchPathCacheEntry *entry;
355  SearchPathCacheKey cachekey = {
356  .searchPath = searchPath,
357  .roleid = roleid
358  };
359 
360  entry = nsphash_lookup(SearchPathCache, cachekey);
361  if (entry)
362  LastSearchPathCacheEntry = 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:70
int a
Definition: isn.c:69

References a, and b.

◆ spcachekey_hash()

static uint32 spcachekey_hash ( SearchPathCacheKey  key)
inlinestatic

Definition at line 254 of file namespace.c.

255 {
256  fasthash_state hs;
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;
3080  Form_pg_ts_template form;
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

◆ 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