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:811
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 4347 of file namespace.c.

4348 {
4349  /*
4350  * Make note that this temporary namespace has been accessed in this
4351  * transaction.
4352  */
4354 
4355  /*
4356  * If the caller attempting to access a temporary schema expects the
4357  * creation of the namespace to be pending and should be enforced, then go
4358  * through the creation.
4359  */
4360  if (!force && OidIsValid(myTempNamespace))
4361  return;
4362 
4363  /*
4364  * The temporary tablespace does not exist yet and is wanted, so
4365  * initialize it.
4366  */
4368 }
#define OidIsValid(objectId)
Definition: c.h:775
static Oid myTempNamespace
Definition: namespace.c:201
static void InitTempTableNamespace(void)
Definition: namespace.c:4375
int MyXactFlags
Definition: xact.c:134
#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 4698 of file namespace.c.

4699 {
4700  /* don't access search_path during bootstrap */
4702 
4703  /*
4704  * We mark the path as needing recomputation, but don't do anything until
4705  * it's needed. This avoids trying to do database access during GUC
4706  * initialization, or outside a transaction.
4707  *
4708  * This does not invalidate the search path cache, so if this value had
4709  * been previously set and no syscache invalidations happened,
4710  * recomputation may not be necessary.
4711  */
4712  baseSearchPathValid = false;
4713 }
#define Assert(condition)
Definition: c.h:858
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454
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 4543 of file namespace.c.

4545 {
4546 
4547  if (myTempNamespaceSubID == mySubid)
4548  {
4549  if (isCommit)
4550  myTempNamespaceSubID = parentSubid;
4551  else
4552  {
4554  /* TEMP namespace creation failed, so reset state */
4557  baseSearchPathValid = false; /* need to rebuild list */
4558  searchPathCacheValid = false;
4559 
4560  /*
4561  * Reset the temporary namespace flag in MyProc. We assume that
4562  * this operation is atomic.
4563  *
4564  * Because this subtransaction is aborting, the pg_namespace row
4565  * is not visible to anyone else anyway, but that doesn't matter:
4566  * it's not a problem if objects contained in this namespace are
4567  * removed concurrently.
4568  */
4570  }
4571  }
4572 }
#define InvalidSubTransactionId
Definition: c.h:658
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:66
Oid tempNamespaceId
Definition: proc.h:205

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 4497 of file namespace.c.

4498 {
4499  /*
4500  * If we abort the transaction in which a temp namespace was selected,
4501  * we'll have to do any creation or cleanout work over again. So, just
4502  * forget the namespace entirely until next time. On the other hand, if
4503  * we commit then register an exit callback to clean out the temp tables
4504  * at backend shutdown. (We only want to register the callback once per
4505  * session, so this is a good place to do it.)
4506  */
4507  if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
4508  {
4509  if (isCommit)
4511  else
4512  {
4515  baseSearchPathValid = false; /* need to rebuild list */
4516  searchPathCacheValid = false;
4517 
4518  /*
4519  * Reset the temporary namespace flag in MyProc. We assume that
4520  * this operation is atomic.
4521  *
4522  * Because this transaction is aborting, the pg_namespace row is
4523  * not visible to anyone else anyway, but that doesn't matter:
4524  * it's not a problem if objects contained in this namespace are
4525  * removed concurrently.
4526  */
4528  }
4530  }
4531 
4532 }
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:4609

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 4229 of file namespace.c.

4230 {
4231  MemoryContext oldcxt;
4232  SearchPathCacheEntry *entry;
4233 
4234  spcache_init();
4235 
4236  entry = spcache_insert(searchPath, roleid);
4237 
4238  /*
4239  * An OOM may have resulted in a cache entry with missing 'oidlist' or
4240  * 'finalPath', so just compute whatever is missing.
4241  */
4242 
4243  if (entry->oidlist == NIL)
4244  {
4246  entry->oidlist = preprocessNamespacePath(searchPath, roleid,
4247  &entry->temp_missing);
4248  MemoryContextSwitchTo(oldcxt);
4249  }
4250 
4251  /*
4252  * If a hook is set, we must recompute finalPath from the oidlist each
4253  * time, because the hook may affect the result. This is still much faster
4254  * than recomputing from the string (and doing catalog lookups and ACL
4255  * checks).
4256  */
4257  if (entry->finalPath == NIL || object_access_hook ||
4258  entry->forceRecompute)
4259  {
4260  list_free(entry->finalPath);
4261  entry->finalPath = NIL;
4262 
4264  entry->finalPath = finalNamespacePath(entry->oidlist,
4265  &entry->firstNS);
4266  MemoryContextSwitchTo(oldcxt);
4267 
4268  /*
4269  * If an object_access_hook is set when finalPath is calculated, the
4270  * result may be affected by the hook. Force recomputation of
4271  * finalPath the next time this cache entry is used, even if the
4272  * object_access_hook is not set at that time.
4273  */
4274  entry->forceRecompute = object_access_hook ? true : false;
4275  }
4276 
4277  return entry;
4278 }
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:4183
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:359
static List * preprocessNamespacePath(const char *searchPath, Oid roleid, bool *temp_missing)
Definition: namespace.c:4092
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 4642 of file namespace.c.

4643 {
4644  Oid roleid = InvalidOid;
4645  const char *searchPath = *newval;
4646  char *rawname;
4647  List *namelist;
4648  bool use_cache = (SearchPathCacheContext != NULL);
4649 
4650  /*
4651  * We used to try to check that the named schemas exist, but there are
4652  * many valid use-cases for having search_path settings that include
4653  * schemas that don't exist; and often, we are not inside a transaction
4654  * here and so can't consult the system catalogs anyway. So now, the only
4655  * requirement is syntactic validity of the identifier list.
4656  *
4657  * Checking only the syntactic validity also allows us to use the search
4658  * path cache (if available) to avoid calling SplitIdentifierString() on
4659  * the same string repeatedly.
4660  */
4661  if (use_cache)
4662  {
4663  spcache_init();
4664 
4665  roleid = GetUserId();
4666 
4667  if (spcache_lookup(searchPath, roleid) != NULL)
4668  return true;
4669  }
4670 
4671  /*
4672  * Ensure validity check succeeds before creating cache entry.
4673  */
4674 
4675  rawname = pstrdup(searchPath); /* need a modifiable copy */
4676 
4677  /* Parse string into list of identifiers */
4678  if (!SplitIdentifierString(rawname, ',', &namelist))
4679  {
4680  /* syntax error in name list */
4681  GUC_check_errdetail("List syntax is invalid.");
4682  pfree(rawname);
4683  list_free(namelist);
4684  return false;
4685  }
4686  pfree(rawname);
4687  list_free(namelist);
4688 
4689  /* OK to create empty cache entry */
4690  if (use_cache)
4691  (void) spcache_insert(searchPath, roleid);
4692 
4693  return true;
4694 }
#define newval
#define GUC_check_errdetail
Definition: guc.h:447
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:329
Definition: pg_list.h:54
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3457

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 3444 of file namespace.c.

3445 {
3446  /* disallow renaming into or out of temp schemas */
3447  if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
3448  ereport(ERROR,
3449  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3450  errmsg("cannot move objects into or out of temporary schemas")));
3451 
3452  /* same for TOAST schema */
3453  if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
3454  ereport(ERROR,
3455  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3456  errmsg("cannot move objects into or out of TOAST schema")));
3457 }
int errcode(int sqlerrcode)
Definition: elog.c:855
int errmsg(const char *fmt,...)
Definition: elog.c:1068
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3672

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

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

◆ checkTempNamespaceStatus()

TempNamespaceStatus checkTempNamespaceStatus ( Oid  namespaceId)

Definition at line 3714 of file namespace.c.

3715 {
3716  PGPROC *proc;
3717  ProcNumber procNumber;
3718 
3720 
3721  procNumber = GetTempNamespaceProcNumber(namespaceId);
3722 
3723  /* No such namespace, or its name shows it's not temp? */
3724  if (procNumber == INVALID_PROC_NUMBER)
3725  return TEMP_NAMESPACE_NOT_TEMP;
3726 
3727  /* Is the backend alive? */
3728  proc = ProcNumberGetProc(procNumber);
3729  if (proc == NULL)
3730  return TEMP_NAMESPACE_IDLE;
3731 
3732  /* Is the backend connected to the same database we are looking at? */
3733  if (proc->databaseId != MyDatabaseId)
3734  return TEMP_NAMESPACE_IDLE;
3735 
3736  /* Does the backend own the temporary namespace? */
3737  if (proc->tempNamespaceId != namespaceId)
3738  return TEMP_NAMESPACE_IDLE;
3739 
3740  /* Yup, so namespace is busy */
3741  return TEMP_NAMESPACE_IN_USE;
3742 }
Oid MyDatabaseId
Definition: globals.c:92
ProcNumber GetTempNamespaceProcNumber(Oid namespaceId)
Definition: namespace.c:3751
@ 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:157
Oid databaseId
Definition: proc.h:202

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 2358 of file namespace.c.

2359 {
2360  int32 dbencoding = GetDatabaseEncoding();
2361  ListCell *l;
2362 
2364 
2365  foreach(l, activeSearchPath)
2366  {
2367  Oid namespaceId = lfirst_oid(l);
2368  Oid collid;
2369 
2370  if (namespaceId == myTempNamespace)
2371  continue; /* do not look in temp namespace */
2372 
2373  collid = lookup_collation(collname, namespaceId, dbencoding);
2374  if (OidIsValid(collid))
2375  return collid;
2376  }
2377 
2378  /* Not found in path */
2379  return InvalidOid;
2380 }
signed int int32
Definition: c.h:494
Oid collid
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
static Oid lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
Definition: namespace.c:2307
static List * activeSearchPath
Definition: namespace.c:136
static void recomputeNamespacePath(void)
Definition: namespace.c:4284
#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 2392 of file namespace.c.

2393 {
2394  return CollationIsVisibleExt(collid, NULL);
2395 }
static bool CollationIsVisibleExt(Oid collid, bool *is_missing)
Definition: namespace.c:2404

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 2404 of file namespace.c.

2405 {
2406  HeapTuple colltup;
2407  Form_pg_collation collform;
2408  Oid collnamespace;
2409  bool visible;
2410 
2411  colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
2412  if (!HeapTupleIsValid(colltup))
2413  {
2414  if (is_missing != NULL)
2415  {
2416  *is_missing = true;
2417  return false;
2418  }
2419  elog(ERROR, "cache lookup failed for collation %u", collid);
2420  }
2421  collform = (Form_pg_collation) GETSTRUCT(colltup);
2422 
2424 
2425  /*
2426  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2427  * the system namespace are surely in the path and so we needn't even do
2428  * list_member_oid() for them.
2429  */
2430  collnamespace = collform->collnamespace;
2431  if (collnamespace != PG_CATALOG_NAMESPACE &&
2432  !list_member_oid(activeSearchPath, collnamespace))
2433  visible = false;
2434  else
2435  {
2436  /*
2437  * If it is in the path, it might still not be visible; it could be
2438  * hidden by another collation of the same name earlier in the path,
2439  * or it might not work with the current DB encoding. So we must do a
2440  * slow check to see if this collation would be found by
2441  * CollationGetCollid.
2442  */
2443  char *collname = NameStr(collform->collname);
2444 
2445  visible = (CollationGetCollid(collname) == collid);
2446  }
2447 
2448  ReleaseSysCache(colltup);
2449 
2450  return visible;
2451 }
#define NameStr(name)
Definition: c.h:746
#define elog(elevel,...)
Definition: elog.h:224
#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:2358
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:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218

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 2462 of file namespace.c.

2463 {
2464  Oid conid;
2465  ListCell *l;
2466 
2468 
2469  foreach(l, activeSearchPath)
2470  {
2471  Oid namespaceId = lfirst_oid(l);
2472 
2473  if (namespaceId == myTempNamespace)
2474  continue; /* do not look in temp namespace */
2475 
2476  conid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
2477  PointerGetDatum(conname),
2478  ObjectIdGetDatum(namespaceId));
2479  if (OidIsValid(conid))
2480  return conid;
2481  }
2482 
2483  /* Not found in path */
2484  return InvalidOid;
2485 }
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:106

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

Referenced by ConversionIsVisibleExt().

◆ ConversionIsVisible()

bool ConversionIsVisible ( Oid  conid)

Definition at line 2494 of file namespace.c.

2495 {
2496  return ConversionIsVisibleExt(conid, NULL);
2497 }
static bool ConversionIsVisibleExt(Oid conid, bool *is_missing)
Definition: namespace.c:2506

References ConversionIsVisibleExt().

Referenced by getObjectDescription().

◆ ConversionIsVisibleExt()

static bool ConversionIsVisibleExt ( Oid  conid,
bool is_missing 
)
static

Definition at line 2506 of file namespace.c.

2507 {
2508  HeapTuple contup;
2509  Form_pg_conversion conform;
2510  Oid connamespace;
2511  bool visible;
2512 
2513  contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
2514  if (!HeapTupleIsValid(contup))
2515  {
2516  if (is_missing != NULL)
2517  {
2518  *is_missing = true;
2519  return false;
2520  }
2521  elog(ERROR, "cache lookup failed for conversion %u", conid);
2522  }
2523  conform = (Form_pg_conversion) GETSTRUCT(contup);
2524 
2526 
2527  /*
2528  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2529  * the system namespace are surely in the path and so we needn't even do
2530  * list_member_oid() for them.
2531  */
2532  connamespace = conform->connamespace;
2533  if (connamespace != PG_CATALOG_NAMESPACE &&
2534  !list_member_oid(activeSearchPath, connamespace))
2535  visible = false;
2536  else
2537  {
2538  /*
2539  * If it is in the path, it might still not be visible; it could be
2540  * hidden by another conversion of the same name earlier in the path.
2541  * So we must do a slow check to see if this conversion would be found
2542  * by ConversionGetConid.
2543  */
2544  char *conname = NameStr(conform->conname);
2545 
2546  visible = (ConversionGetConid(conname) == conid);
2547  }
2548 
2549  ReleaseSysCache(contup);
2550 
2551  return visible;
2552 }
Oid ConversionGetConid(const char *conname)
Definition: namespace.c:2462
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 3874 of file namespace.c.

3875 {
3876  SearchPathMatcher *result;
3877 
3878  result = (SearchPathMatcher *) palloc(sizeof(SearchPathMatcher));
3879  result->schemas = list_copy(path->schemas);
3880  result->addCatalog = path->addCatalog;
3881  result->addTemp = path->addTemp;
3882  result->generation = path->generation;
3883 
3884  return result;
3885 }
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 3286 of file namespace.c.

3289 {
3290  char *catalogname;
3291  char *schemaname = NULL;
3292  char *objname = NULL;
3293 
3294  switch (list_length(names))
3295  {
3296  case 1:
3297  objname = strVal(linitial(names));
3298  break;
3299  case 2:
3300  schemaname = strVal(linitial(names));
3301  objname = strVal(lsecond(names));
3302  break;
3303  case 3:
3304  catalogname = strVal(linitial(names));
3305  schemaname = strVal(lsecond(names));
3306  objname = strVal(lthird(names));
3307 
3308  /*
3309  * We check the catalog name and then ignore it.
3310  */
3311  if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
3312  ereport(ERROR,
3313  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3314  errmsg("cross-database references are not implemented: %s",
3315  NameListToString(names))));
3316  break;
3317  default:
3318  ereport(ERROR,
3319  (errcode(ERRCODE_SYNTAX_ERROR),
3320  errmsg("improper qualified name (too many dotted names): %s",
3321  NameListToString(names))));
3322  break;
3323  }
3324 
3325  *nspname_p = schemaname;
3326  *objname_p = objname;
3327 }
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3166
char * NameListToString(const List *names)
Definition: namespace.c:3579
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 4809 of file namespace.c.

4810 {
4811  List *result;
4812 
4814 
4815  /*
4816  * If the temp namespace should be first, force it to exist. This is so
4817  * that callers can trust the result to reflect the actual default
4818  * creation namespace. It's a bit bogus to do this here, since
4819  * current_schema() is supposedly a stable function without side-effects,
4820  * but the alternatives seem worse.
4821  */
4823  {
4826  }
4827 
4828  result = list_copy(activeSearchPath);
4829  if (!includeImplicit)
4830  {
4831  while (result && linitial_oid(result) != activeCreationNamespace)
4832  result = list_delete_first(result);
4833  }
4834 
4835  return result;
4836 }
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:4347
#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 4849 of file namespace.c.

4850 {
4851  int count = 0;
4852  ListCell *l;
4853 
4855 
4856  foreach(l, activeSearchPath)
4857  {
4858  Oid namespaceId = lfirst_oid(l);
4859 
4860  if (namespaceId == myTempNamespace)
4861  continue; /* do not include temp namespace */
4862 
4863  if (count < sarray_len)
4864  sarray[count] = namespaceId;
4865  count++;
4866  }
4867 
4868  return count;
4869 }

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 4183 of file namespace.c.

4184 {
4185  List *finalPath = NIL;
4186  ListCell *lc;
4187 
4188  foreach(lc, oidlist)
4189  {
4190  Oid namespaceId = lfirst_oid(lc);
4191 
4192  if (!list_member_oid(finalPath, namespaceId))
4193  {
4194  if (InvokeNamespaceSearchHook(namespaceId, false))
4195  finalPath = lappend_oid(finalPath, namespaceId);
4196  }
4197  }
4198 
4199  /*
4200  * Remember the first member of the explicit list. (Note: this is
4201  * nominally wrong if temp_missing, but we need it anyway to distinguish
4202  * explicit from implicit mention of pg_catalog.)
4203  */
4204  if (finalPath == NIL)
4205  *firstNS = InvalidOid;
4206  else
4207  *firstNS = linitial_oid(finalPath);
4208 
4209  /*
4210  * Add any implicitly-searched namespaces to the list. Note these go on
4211  * the front, not the back; also notice that we do not check USAGE
4212  * permissions for these.
4213  */
4214  if (!list_member_oid(finalPath, PG_CATALOG_NAMESPACE))
4215  finalPath = lcons_oid(PG_CATALOG_NAMESPACE, finalPath);
4216 
4217  if (OidIsValid(myTempNamespace) &&
4218  !list_member_oid(finalPath, myTempNamespace))
4219  finalPath = lcons_oid(myTempNamespace, finalPath);
4220 
4221  return finalPath;
4222 }
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 4065 of file namespace.c.

4066 {
4067  Oid proc;
4068  ListCell *l;
4069 
4071 
4072  foreach(l, activeSearchPath)
4073  {
4074  Oid namespaceId = lfirst_oid(l);
4075 
4076  if (namespaceId == myTempNamespace)
4077  continue; /* do not look in temp namespace */
4078 
4079  proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
4080  if (OidIsValid(proc))
4081  return proc;
4082  }
4083 
4084  /* Not found in path */
4085  return InvalidOid;
4086 }
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 1177 of file namespace.c.

1180 {
1181  FuncCandidateList resultList = NULL;
1182  bool any_special = false;
1183  char *schemaname;
1184  char *funcname;
1185  Oid namespaceId;
1186  CatCList *catlist;
1187  int i;
1188 
1189  /* check for caller error */
1190  Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
1191 
1192  /* deconstruct the name list */
1193  DeconstructQualifiedName(names, &schemaname, &funcname);
1194 
1195  if (schemaname)
1196  {
1197  /* use exact schema given */
1198  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
1199  if (!OidIsValid(namespaceId))
1200  return NULL;
1201  }
1202  else
1203  {
1204  /* flag to indicate we need namespace search */
1205  namespaceId = InvalidOid;
1207  }
1208 
1209  /* Search syscache by name only */
1210  catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname));
1211 
1212  for (i = 0; i < catlist->n_members; i++)
1213  {
1214  HeapTuple proctup = &catlist->members[i]->tuple;
1215  Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
1216  Oid *proargtypes = procform->proargtypes.values;
1217  int pronargs = procform->pronargs;
1218  int effective_nargs;
1219  int pathpos = 0;
1220  bool variadic;
1221  bool use_defaults;
1222  Oid va_elem_type;
1223  int *argnumbers = NULL;
1224  FuncCandidateList newResult;
1225 
1226  if (OidIsValid(namespaceId))
1227  {
1228  /* Consider only procs in specified namespace */
1229  if (procform->pronamespace != namespaceId)
1230  continue;
1231  }
1232  else
1233  {
1234  /*
1235  * Consider only procs that are in the search path and are not in
1236  * the temp namespace.
1237  */
1238  ListCell *nsp;
1239 
1240  foreach(nsp, activeSearchPath)
1241  {
1242  if (procform->pronamespace == lfirst_oid(nsp) &&
1243  procform->pronamespace != myTempNamespace)
1244  break;
1245  pathpos++;
1246  }
1247  if (nsp == NULL)
1248  continue; /* proc is not in search path */
1249  }
1250 
1251  /*
1252  * If we are asked to match to OUT arguments, then use the
1253  * proallargtypes array (which includes those); otherwise use
1254  * proargtypes (which doesn't). Of course, if proallargtypes is null,
1255  * we always use proargtypes.
1256  */
1257  if (include_out_arguments)
1258  {
1259  Datum proallargtypes;
1260  bool isNull;
1261 
1262  proallargtypes = SysCacheGetAttr(PROCNAMEARGSNSP, proctup,
1263  Anum_pg_proc_proallargtypes,
1264  &isNull);
1265  if (!isNull)
1266  {
1267  ArrayType *arr = DatumGetArrayTypeP(proallargtypes);
1268 
1269  pronargs = ARR_DIMS(arr)[0];
1270  if (ARR_NDIM(arr) != 1 ||
1271  pronargs < 0 ||
1272  ARR_HASNULL(arr) ||
1273  ARR_ELEMTYPE(arr) != OIDOID)
1274  elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
1275  Assert(pronargs >= procform->pronargs);
1276  proargtypes = (Oid *) ARR_DATA_PTR(arr);
1277  }
1278  }
1279 
1280  if (argnames != NIL)
1281  {
1282  /*
1283  * Call uses named or mixed notation
1284  *
1285  * Named or mixed notation can match a variadic function only if
1286  * expand_variadic is off; otherwise there is no way to match the
1287  * presumed-nameless parameters expanded from the variadic array.
1288  */
1289  if (OidIsValid(procform->provariadic) && expand_variadic)
1290  continue;
1291  va_elem_type = InvalidOid;
1292  variadic = false;
1293 
1294  /*
1295  * Check argument count.
1296  */
1297  Assert(nargs >= 0); /* -1 not supported with argnames */
1298 
1299  if (pronargs > nargs && expand_defaults)
1300  {
1301  /* Ignore if not enough default expressions */
1302  if (nargs + procform->pronargdefaults < pronargs)
1303  continue;
1304  use_defaults = true;
1305  }
1306  else
1307  use_defaults = false;
1308 
1309  /* Ignore if it doesn't match requested argument count */
1310  if (pronargs != nargs && !use_defaults)
1311  continue;
1312 
1313  /* Check for argument name match, generate positional mapping */
1314  if (!MatchNamedCall(proctup, nargs, argnames,
1315  include_out_arguments, pronargs,
1316  &argnumbers))
1317  continue;
1318 
1319  /* Named argument matching is always "special" */
1320  any_special = true;
1321  }
1322  else
1323  {
1324  /*
1325  * Call uses positional notation
1326  *
1327  * Check if function is variadic, and get variadic element type if
1328  * so. If expand_variadic is false, we should just ignore
1329  * variadic-ness.
1330  */
1331  if (pronargs <= nargs && expand_variadic)
1332  {
1333  va_elem_type = procform->provariadic;
1334  variadic = OidIsValid(va_elem_type);
1335  any_special |= variadic;
1336  }
1337  else
1338  {
1339  va_elem_type = InvalidOid;
1340  variadic = false;
1341  }
1342 
1343  /*
1344  * Check if function can match by using parameter defaults.
1345  */
1346  if (pronargs > nargs && expand_defaults)
1347  {
1348  /* Ignore if not enough default expressions */
1349  if (nargs + procform->pronargdefaults < pronargs)
1350  continue;
1351  use_defaults = true;
1352  any_special = true;
1353  }
1354  else
1355  use_defaults = false;
1356 
1357  /* Ignore if it doesn't match requested argument count */
1358  if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
1359  continue;
1360  }
1361 
1362  /*
1363  * We must compute the effective argument list so that we can easily
1364  * compare it to earlier results. We waste a palloc cycle if it gets
1365  * masked by an earlier result, but really that's a pretty infrequent
1366  * case so it's not worth worrying about.
1367  */
1368  effective_nargs = Max(pronargs, nargs);
1369  newResult = (FuncCandidateList)
1370  palloc(offsetof(struct _FuncCandidateList, args) +
1371  effective_nargs * sizeof(Oid));
1372  newResult->pathpos = pathpos;
1373  newResult->oid = procform->oid;
1374  newResult->nominalnargs = pronargs;
1375  newResult->nargs = effective_nargs;
1376  newResult->argnumbers = argnumbers;
1377  if (argnumbers)
1378  {
1379  /* Re-order the argument types into call's logical order */
1380  for (int j = 0; j < pronargs; j++)
1381  newResult->args[j] = proargtypes[argnumbers[j]];
1382  }
1383  else
1384  {
1385  /* Simple positional case, just copy proargtypes as-is */
1386  memcpy(newResult->args, proargtypes, pronargs * sizeof(Oid));
1387  }
1388  if (variadic)
1389  {
1390  newResult->nvargs = effective_nargs - pronargs + 1;
1391  /* Expand variadic argument into N copies of element type */
1392  for (int j = pronargs - 1; j < effective_nargs; j++)
1393  newResult->args[j] = va_elem_type;
1394  }
1395  else
1396  newResult->nvargs = 0;
1397  newResult->ndargs = use_defaults ? pronargs - nargs : 0;
1398 
1399  /*
1400  * Does it have the same arguments as something we already accepted?
1401  * If so, decide what to do to avoid returning duplicate argument
1402  * lists. We can skip this check for the single-namespace case if no
1403  * special (named, variadic or defaults) match has been made, since
1404  * then the unique index on pg_proc guarantees all the matches have
1405  * different argument lists.
1406  */
1407  if (resultList != NULL &&
1408  (any_special || !OidIsValid(namespaceId)))
1409  {
1410  /*
1411  * If we have an ordered list from SearchSysCacheList (the normal
1412  * case), then any conflicting proc must immediately adjoin this
1413  * one in the list, so we only need to look at the newest result
1414  * item. If we have an unordered list, we have to scan the whole
1415  * result list. Also, if either the current candidate or any
1416  * previous candidate is a special match, we can't assume that
1417  * conflicts are adjacent.
1418  *
1419  * We ignore defaulted arguments in deciding what is a match.
1420  */
1421  FuncCandidateList prevResult;
1422 
1423  if (catlist->ordered && !any_special)
1424  {
1425  /* ndargs must be 0 if !any_special */
1426  if (effective_nargs == resultList->nargs &&
1427  memcmp(newResult->args,
1428  resultList->args,
1429  effective_nargs * sizeof(Oid)) == 0)
1430  prevResult = resultList;
1431  else
1432  prevResult = NULL;
1433  }
1434  else
1435  {
1436  int cmp_nargs = newResult->nargs - newResult->ndargs;
1437 
1438  for (prevResult = resultList;
1439  prevResult;
1440  prevResult = prevResult->next)
1441  {
1442  if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
1443  memcmp(newResult->args,
1444  prevResult->args,
1445  cmp_nargs * sizeof(Oid)) == 0)
1446  break;
1447  }
1448  }
1449 
1450  if (prevResult)
1451  {
1452  /*
1453  * We have a match with a previous result. Decide which one
1454  * to keep, or mark it ambiguous if we can't decide. The
1455  * logic here is preference > 0 means prefer the old result,
1456  * preference < 0 means prefer the new, preference = 0 means
1457  * ambiguous.
1458  */
1459  int preference;
1460 
1461  if (pathpos != prevResult->pathpos)
1462  {
1463  /*
1464  * Prefer the one that's earlier in the search path.
1465  */
1466  preference = pathpos - prevResult->pathpos;
1467  }
1468  else if (variadic && prevResult->nvargs == 0)
1469  {
1470  /*
1471  * With variadic functions we could have, for example,
1472  * both foo(numeric) and foo(variadic numeric[]) in the
1473  * same namespace; if so we prefer the non-variadic match
1474  * on efficiency grounds.
1475  */
1476  preference = 1;
1477  }
1478  else if (!variadic && prevResult->nvargs > 0)
1479  {
1480  preference = -1;
1481  }
1482  else
1483  {
1484  /*----------
1485  * We can't decide. This can happen with, for example,
1486  * both foo(numeric, variadic numeric[]) and
1487  * foo(variadic numeric[]) in the same namespace, or
1488  * both foo(int) and foo (int, int default something)
1489  * in the same namespace, or both foo(a int, b text)
1490  * and foo(b text, a int) in the same namespace.
1491  *----------
1492  */
1493  preference = 0;
1494  }
1495 
1496  if (preference > 0)
1497  {
1498  /* keep previous result */
1499  pfree(newResult);
1500  continue;
1501  }
1502  else if (preference < 0)
1503  {
1504  /* remove previous result from the list */
1505  if (prevResult == resultList)
1506  resultList = prevResult->next;
1507  else
1508  {
1509  FuncCandidateList prevPrevResult;
1510 
1511  for (prevPrevResult = resultList;
1512  prevPrevResult;
1513  prevPrevResult = prevPrevResult->next)
1514  {
1515  if (prevResult == prevPrevResult->next)
1516  {
1517  prevPrevResult->next = prevResult->next;
1518  break;
1519  }
1520  }
1521  Assert(prevPrevResult); /* assert we found it */
1522  }
1523  pfree(prevResult);
1524  /* fall through to add newResult to list */
1525  }
1526  else
1527  {
1528  /* mark old result as ambiguous, discard new */
1529  prevResult->oid = InvalidOid;
1530  pfree(newResult);
1531  continue;
1532  }
1533  }
1534  }
1535 
1536  /*
1537  * Okay to add it to result list
1538  */
1539  newResult->next = resultList;
1540  resultList = newResult;
1541  }
1542 
1543  ReleaseSysCacheList(catlist);
1544 
1545  return resultList;
1546 }
#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:998
#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:3370
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:3286
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, bool include_out_arguments, int pronargs, int **argnumbers)
Definition: namespace.c:1570
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:479
#define ReleaseSysCacheList(x)
Definition: syscache.h:129
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:122

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 1681 of file namespace.c.

1682 {
1683  return FunctionIsVisibleExt(funcid, NULL);
1684 }
static bool FunctionIsVisibleExt(Oid funcid, bool *is_missing)
Definition: namespace.c:1693

References FunctionIsVisibleExt().

Referenced by format_procedure_extended().

◆ FunctionIsVisibleExt()

static bool FunctionIsVisibleExt ( Oid  funcid,
bool is_missing 
)
static

Definition at line 1693 of file namespace.c.

1694 {
1695  HeapTuple proctup;
1696  Form_pg_proc procform;
1697  Oid pronamespace;
1698  bool visible;
1699 
1700  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1701  if (!HeapTupleIsValid(proctup))
1702  {
1703  if (is_missing != NULL)
1704  {
1705  *is_missing = true;
1706  return false;
1707  }
1708  elog(ERROR, "cache lookup failed for function %u", funcid);
1709  }
1710  procform = (Form_pg_proc) GETSTRUCT(proctup);
1711 
1713 
1714  /*
1715  * Quick check: if it ain't in the path at all, it ain't visible. Items in
1716  * the system namespace are surely in the path and so we needn't even do
1717  * list_member_oid() for them.
1718  */
1719  pronamespace = procform->pronamespace;
1720  if (pronamespace != PG_CATALOG_NAMESPACE &&
1721  !list_member_oid(activeSearchPath, pronamespace))
1722  visible = false;
1723  else
1724  {
1725  /*
1726  * If it is in the path, it might still not be visible; it could be
1727  * hidden by another proc of the same name and arguments earlier in
1728  * the path. So we must do a slow check to see if this is the same
1729  * proc that would be found by FuncnameGetCandidates.
1730  */
1731  char *proname = NameStr(procform->proname);
1732  int nargs = procform->pronargs;
1733  FuncCandidateList clist;
1734 
1735  visible = false;
1736 
1738  nargs, NIL, false, false, false, false);
1739 
1740  for (; clist; clist = clist->next)
1741  {
1742  if (memcmp(clist->args, procform->proargtypes.values,
1743  nargs * sizeof(Oid)) == 0)
1744  {
1745  /* Found the expected entry; is it the right proc? */
1746  visible = (clist->oid == funcid);
1747  break;
1748  }
1749  }
1750  }
1751 
1752  ReleaseSysCache(proctup);
1753 
1754  return visible;
1755 }
FuncCandidateList FuncnameGetCandidates(List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool include_out_arguments, bool missing_ok)
Definition: namespace.c:1177
#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 3956 of file namespace.c.

3957 {
3958  char *schemaname;
3959  char *collation_name;
3960  int32 dbencoding = GetDatabaseEncoding();
3961  Oid namespaceId;
3962  Oid colloid;
3963  ListCell *l;
3964 
3965  /* deconstruct the name list */
3966  DeconstructQualifiedName(collname, &schemaname, &collation_name);
3967 
3968  if (schemaname)
3969  {
3970  /* use exact schema given */
3971  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3972  if (missing_ok && !OidIsValid(namespaceId))
3973  return InvalidOid;
3974 
3975  colloid = lookup_collation(collation_name, namespaceId, dbencoding);
3976  if (OidIsValid(colloid))
3977  return colloid;
3978  }
3979  else
3980  {
3981  /* search for it in search path */
3983 
3984  foreach(l, activeSearchPath)
3985  {
3986  namespaceId = lfirst_oid(l);
3987 
3988  if (namespaceId == myTempNamespace)
3989  continue; /* do not look in temp namespace */
3990 
3991  colloid = lookup_collation(collation_name, namespaceId, dbencoding);
3992  if (OidIsValid(colloid))
3993  return colloid;
3994  }
3995  }
3996 
3997  /* Not found in path */
3998  if (!missing_ok)
3999  ereport(ERROR,
4000  (errcode(ERRCODE_UNDEFINED_OBJECT),
4001  errmsg("collation \"%s\" for encoding \"%s\" does not exist",
4002  NameListToString(collname), GetDatabaseEncodingName())));
4003  return InvalidOid;
4004 }
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 4010 of file namespace.c.

4011 {
4012  char *schemaname;
4013  char *conversion_name;
4014  Oid namespaceId;
4015  Oid conoid = InvalidOid;
4016  ListCell *l;
4017 
4018  /* deconstruct the name list */
4019  DeconstructQualifiedName(conname, &schemaname, &conversion_name);
4020 
4021  if (schemaname)
4022  {
4023  /* use exact schema given */
4024  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
4025  if (missing_ok && !OidIsValid(namespaceId))
4026  conoid = InvalidOid;
4027  else
4028  conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
4029  PointerGetDatum(conversion_name),
4030  ObjectIdGetDatum(namespaceId));
4031  }
4032  else
4033  {
4034  /* search for it in search path */
4036 
4037  foreach(l, activeSearchPath)
4038  {
4039  namespaceId = lfirst_oid(l);
4040 
4041  if (namespaceId == myTempNamespace)
4042  continue; /* do not look in temp namespace */
4043 
4044  conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
4045  PointerGetDatum(conversion_name),
4046  ObjectIdGetDatum(namespaceId));
4047  if (OidIsValid(conoid))
4048  return conoid;
4049  }
4050  }
4051 
4052  /* Not found in path */
4053  if (!OidIsValid(conoid) && !missing_ok)
4054  ereport(ERROR,
4055  (errcode(ERRCODE_UNDEFINED_OBJECT),
4056  errmsg("conversion \"%s\" does not exist",
4057  NameListToString(conname))));
4058  return conoid;
4059 }

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 2560 of file namespace.c.

2561 {
2562  char *schemaname;
2563  char *stats_name;
2564  Oid namespaceId;
2565  Oid stats_oid = InvalidOid;
2566  ListCell *l;
2567 
2568  /* deconstruct the name list */
2569  DeconstructQualifiedName(names, &schemaname, &stats_name);
2570 
2571  if (schemaname)
2572  {
2573  /* use exact schema given */
2574  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2575  if (missing_ok && !OidIsValid(namespaceId))
2576  stats_oid = InvalidOid;
2577  else
2578  stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2579  PointerGetDatum(stats_name),
2580  ObjectIdGetDatum(namespaceId));
2581  }
2582  else
2583  {
2584  /* search for it in search path */
2586 
2587  foreach(l, activeSearchPath)
2588  {
2589  namespaceId = lfirst_oid(l);
2590 
2591  if (namespaceId == myTempNamespace)
2592  continue; /* do not look in temp namespace */
2593  stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2594  PointerGetDatum(stats_name),
2595  ObjectIdGetDatum(namespaceId));
2596  if (OidIsValid(stats_oid))
2597  break;
2598  }
2599  }
2600 
2601  if (!OidIsValid(stats_oid) && !missing_ok)
2602  ereport(ERROR,
2603  (errcode(ERRCODE_UNDEFINED_OBJECT),
2604  errmsg("statistics object \"%s\" does not exist",
2605  NameListToString(names))));
2606 
2607  return stats_oid;
2608 }

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 3137 of file namespace.c.

3138 {
3139  char *schemaname;
3140  char *config_name;
3141  Oid namespaceId;
3142  Oid cfgoid = InvalidOid;
3143  ListCell *l;
3144 
3145  /* deconstruct the name list */
3146  DeconstructQualifiedName(names, &schemaname, &config_name);
3147 
3148  if (schemaname)
3149  {
3150  /* use exact schema given */
3151  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3152  if (missing_ok && !OidIsValid(namespaceId))
3153  cfgoid = InvalidOid;
3154  else
3155  cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
3156  PointerGetDatum(config_name),
3157  ObjectIdGetDatum(namespaceId));
3158  }
3159  else
3160  {
3161  /* search for it in search path */
3163 
3164  foreach(l, activeSearchPath)
3165  {
3166  namespaceId = lfirst_oid(l);
3167 
3168  if (namespaceId == myTempNamespace)
3169  continue; /* do not look in temp namespace */
3170 
3171  cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
3172  PointerGetDatum(config_name),
3173  ObjectIdGetDatum(namespaceId));
3174  if (OidIsValid(cfgoid))
3175  break;
3176  }
3177  }
3178 
3179  if (!OidIsValid(cfgoid) && !missing_ok)
3180  ereport(ERROR,
3181  (errcode(ERRCODE_UNDEFINED_OBJECT),
3182  errmsg("text search configuration \"%s\" does not exist",
3183  NameListToString(names))));
3184 
3185  return cfgoid;
3186 }

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 2846 of file namespace.c.

2847 {
2848  char *schemaname;
2849  char *dict_name;
2850  Oid namespaceId;
2851  Oid dictoid = InvalidOid;
2852  ListCell *l;
2853 
2854  /* deconstruct the name list */
2855  DeconstructQualifiedName(names, &schemaname, &dict_name);
2856 
2857  if (schemaname)
2858  {
2859  /* use exact schema given */
2860  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2861  if (missing_ok && !OidIsValid(namespaceId))
2862  dictoid = InvalidOid;
2863  else
2864  dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2865  PointerGetDatum(dict_name),
2866  ObjectIdGetDatum(namespaceId));
2867  }
2868  else
2869  {
2870  /* search for it in search path */
2872 
2873  foreach(l, activeSearchPath)
2874  {
2875  namespaceId = lfirst_oid(l);
2876 
2877  if (namespaceId == myTempNamespace)
2878  continue; /* do not look in temp namespace */
2879 
2880  dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2881  PointerGetDatum(dict_name),
2882  ObjectIdGetDatum(namespaceId));
2883  if (OidIsValid(dictoid))
2884  break;
2885  }
2886  }
2887 
2888  if (!OidIsValid(dictoid) && !missing_ok)
2889  ereport(ERROR,
2890  (errcode(ERRCODE_UNDEFINED_OBJECT),
2891  errmsg("text search dictionary \"%s\" does not exist",
2892  NameListToString(names))));
2893 
2894  return dictoid;
2895 }

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 2701 of file namespace.c.

2702 {
2703  char *schemaname;
2704  char *parser_name;
2705  Oid namespaceId;
2706  Oid prsoid = InvalidOid;
2707  ListCell *l;
2708 
2709  /* deconstruct the name list */
2710  DeconstructQualifiedName(names, &schemaname, &parser_name);
2711 
2712  if (schemaname)
2713  {
2714  /* use exact schema given */
2715  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2716  if (missing_ok && !OidIsValid(namespaceId))
2717  prsoid = InvalidOid;
2718  else
2719  prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2720  PointerGetDatum(parser_name),
2721  ObjectIdGetDatum(namespaceId));
2722  }
2723  else
2724  {
2725  /* search for it in search path */
2727 
2728  foreach(l, activeSearchPath)
2729  {
2730  namespaceId = lfirst_oid(l);
2731 
2732  if (namespaceId == myTempNamespace)
2733  continue; /* do not look in temp namespace */
2734 
2735  prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2736  PointerGetDatum(parser_name),
2737  ObjectIdGetDatum(namespaceId));
2738  if (OidIsValid(prsoid))
2739  break;
2740  }
2741  }
2742 
2743  if (!OidIsValid(prsoid) && !missing_ok)
2744  ereport(ERROR,
2745  (errcode(ERRCODE_UNDEFINED_OBJECT),
2746  errmsg("text search parser \"%s\" does not exist",
2747  NameListToString(names))));
2748 
2749  return prsoid;
2750 }

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 2992 of file namespace.c.

2993 {
2994  char *schemaname;
2995  char *template_name;
2996  Oid namespaceId;
2997  Oid tmploid = InvalidOid;
2998  ListCell *l;
2999 
3000  /* deconstruct the name list */
3001  DeconstructQualifiedName(names, &schemaname, &template_name);
3002 
3003  if (schemaname)
3004  {
3005  /* use exact schema given */
3006  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3007  if (missing_ok && !OidIsValid(namespaceId))
3008  tmploid = InvalidOid;
3009  else
3010  tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
3011  PointerGetDatum(template_name),
3012  ObjectIdGetDatum(namespaceId));
3013  }
3014  else
3015  {
3016  /* search for it in search path */
3018 
3019  foreach(l, activeSearchPath)
3020  {
3021  namespaceId = lfirst_oid(l);
3022 
3023  if (namespaceId == myTempNamespace)
3024  continue; /* do not look in temp namespace */
3025 
3026  tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
3027  PointerGetDatum(template_name),
3028  ObjectIdGetDatum(namespaceId));
3029  if (OidIsValid(tmploid))
3030  break;
3031  }
3032  }
3033 
3034  if (!OidIsValid(tmploid) && !missing_ok)
3035  ereport(ERROR,
3036  (errcode(ERRCODE_UNDEFINED_OBJECT),
3037  errmsg("text search template \"%s\" does not exist",
3038  NameListToString(names))));
3039 
3040  return tmploid;
3041 }

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 3837 of file namespace.c.

3838 {
3839  SearchPathMatcher *result;
3840  List *schemas;
3841  MemoryContext oldcxt;
3842 
3844 
3845  oldcxt = MemoryContextSwitchTo(context);
3846 
3847  result = (SearchPathMatcher *) palloc0(sizeof(SearchPathMatcher));
3848  schemas = list_copy(activeSearchPath);
3849  while (schemas && linitial_oid(schemas) != activeCreationNamespace)
3850  {
3851  if (linitial_oid(schemas) == myTempNamespace)
3852  result->addTemp = true;
3853  else
3854  {
3855  Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
3856  result->addCatalog = true;
3857  }
3858  schemas = list_delete_first(schemas);
3859  }
3860  result->schemas = schemas;
3861  result->generation = activePathGeneration;
3862 
3863  MemoryContextSwitchTo(oldcxt);
3864 
3865  return result;
3866 }
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 3751 of file namespace.c.

3752 {
3753  int result;
3754  char *nspname;
3755 
3756  /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3757  nspname = get_namespace_name(namespaceId);
3758  if (!nspname)
3759  return INVALID_PROC_NUMBER; /* no such namespace? */
3760  if (strncmp(nspname, "pg_temp_", 8) == 0)
3761  result = atoi(nspname + 8);
3762  else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
3763  result = atoi(nspname + 14);
3764  else
3765  result = INVALID_PROC_NUMBER;
3766  pfree(nspname);
3767  return result;
3768 }
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 3790 of file namespace.c.

3791 {
3792  /* Return namespace OIDs, or 0 if session has not created temp namespace */
3793  *tempNamespaceId = myTempNamespace;
3794  *tempToastNamespaceId = myTempToastNamespace;
3795 }

References myTempNamespace, and myTempToastNamespace.

Referenced by InitializeParallelDSM().

◆ GetTempToastNamespace()

Oid GetTempToastNamespace ( void  )

Definition at line 3776 of file namespace.c.

3777 {
3779  return myTempToastNamespace;
3780 }

References Assert, myTempToastNamespace, and OidIsValid.

Referenced by create_toast_table().

◆ InitializeSearchPath()

void InitializeSearchPath ( void  )

Definition at line 4721 of file namespace.c.

4722 {
4724  {
4725  /*
4726  * In bootstrap mode, the search path must be 'pg_catalog' so that
4727  * tables are created in the proper namespace; ignore the GUC setting.
4728  */
4729  MemoryContext oldcxt;
4730 
4732  baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
4733  MemoryContextSwitchTo(oldcxt);
4734  baseCreationNamespace = PG_CATALOG_NAMESPACE;
4735  baseTempCreationPending = false;
4736  baseSearchPathValid = true;
4741  activePathGeneration++; /* pro forma */
4742  }
4743  else
4744  {
4745  /* Make the context we'll keep search path cache hashtable in */
4747  "search_path processing cache",
4749 
4750  /*
4751  * In normal mode, arrange for a callback on any syscache invalidation
4752  * that will affect the search_path cache.
4753  */
4754 
4755  /* namespace name or ACLs may have changed */
4756  CacheRegisterSyscacheCallback(NAMESPACEOID,
4758  (Datum) 0);
4759 
4760  /* role name may affect the meaning of "$user" */
4763  (Datum) 0);
4764 
4765  /* role membership may affect ACLs */
4766  CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
4768  (Datum) 0);
4769 
4770  /* database owner may affect ACLs */
4771  CacheRegisterSyscacheCallback(DATABASEOID,
4773  (Datum) 0);
4774 
4775  /* Force search path to be recomputed on next use */
4776  baseSearchPathValid = false;
4777  searchPathCacheValid = false;
4778  }
4779 }
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1516
MemoryContext TopMemoryContext
Definition: mcxt.c:149
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
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:4786
static List * baseSearchPath
Definition: namespace.c:149
#define list_make1_oid(x1)
Definition: pg_list.h:242

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

Referenced by InitPostgres().

◆ InitTempTableNamespace()

static void InitTempTableNamespace ( void  )
static

Definition at line 4375 of file namespace.c.

4376 {
4377  char namespaceName[NAMEDATALEN];
4378  Oid namespaceId;
4379  Oid toastspaceId;
4380 
4382 
4383  /*
4384  * First, do permission check to see if we are authorized to make temp
4385  * tables. We use a nonstandard error message here since "databasename:
4386  * permission denied" might be a tad cryptic.
4387  *
4388  * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
4389  * that's necessary since current user ID could change during the session.
4390  * But there's no need to make the namespace in the first place until a
4391  * temp table creation request is made by someone with appropriate rights.
4392  */
4393  if (object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
4395  ereport(ERROR,
4396  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4397  errmsg("permission denied to create temporary tables in database \"%s\"",
4399 
4400  /*
4401  * Do not allow a Hot Standby session to make temp tables. Aside from
4402  * problems with modifying the system catalogs, there is a naming
4403  * conflict: pg_temp_N belongs to the session with proc number N on the
4404  * primary, not to a hot standby session with the same proc number. We
4405  * should not be able to get here anyway due to XactReadOnly checks, but
4406  * let's just make real sure. Note that this also backstops various
4407  * operations that allow XactReadOnly transactions to modify temp tables;
4408  * they'd need RecoveryInProgress checks if not for this.
4409  */
4410  if (RecoveryInProgress())
4411  ereport(ERROR,
4412  (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
4413  errmsg("cannot create temporary tables during recovery")));
4414 
4415  /* Parallel workers can't create temporary tables, either. */
4416  if (IsParallelWorker())
4417  ereport(ERROR,
4418  (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
4419  errmsg("cannot create temporary tables during a parallel operation")));
4420 
4421  snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyProcNumber);
4422 
4423  namespaceId = get_namespace_oid(namespaceName, true);
4424  if (!OidIsValid(namespaceId))
4425  {
4426  /*
4427  * First use of this temp namespace in this database; create it. The
4428  * temp namespaces are always owned by the superuser. We leave their
4429  * permissions at default --- i.e., no access except to superuser ---
4430  * to ensure that unprivileged users can't peek at other backends'
4431  * temp tables. This works because the places that access the temp
4432  * namespace for my own backend skip permissions checks on it.
4433  */
4434  namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4435  true);
4436  /* Advance command counter to make namespace visible */
4438  }
4439  else
4440  {
4441  /*
4442  * If the namespace already exists, clean it out (in case the former
4443  * owner crashed without doing so).
4444  */
4445  RemoveTempRelations(namespaceId);
4446  }
4447 
4448  /*
4449  * If the corresponding toast-table namespace doesn't exist yet, create
4450  * it. (We assume there is no need to clean it out if it does exist, since
4451  * dropping a parent table should make its toast table go away.)
4452  */
4453  snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
4454  MyProcNumber);
4455 
4456  toastspaceId = get_namespace_oid(namespaceName, true);
4457  if (!OidIsValid(toastspaceId))
4458  {
4459  toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4460  true);
4461  /* Advance command counter to make namespace visible */
4463  }
4464 
4465  /*
4466  * Okay, we've prepared the temp namespace ... but it's not committed yet,
4467  * so all our work could be undone by transaction rollback. Set flag for
4468  * AtEOXact_Namespace to know what to do.
4469  */
4470  myTempNamespace = namespaceId;
4471  myTempToastNamespace = toastspaceId;
4472 
4473  /*
4474  * Mark MyProc as owning this namespace which other processes can use to
4475  * decide if a temporary namespace is in use or not. We assume that
4476  * assignment of namespaceId is an atomic operation. Even if it is not,
4477  * the temporary relation which resulted in the creation of this temporary
4478  * namespace is still locked until the current transaction commits, and
4479  * its pg_namespace row is not visible yet. However it does not matter:
4480  * this flag makes the namespace as being in use, so no objects created on
4481  * it would be removed concurrently.
4482  */
4483  MyProc->tempNamespaceId = namespaceId;
4484 
4485  /* It should not be done already. */
4488 
4489  baseSearchPathValid = false; /* need to rebuild list */
4490  searchPathCacheValid = false;
4491 }
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3888
ProcNumber MyProcNumber
Definition: globals.c:88
#define IsParallelWorker()
Definition: parallel.h:60
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3520
static void RemoveTempRelations(Oid tempNamespaceId)
Definition: namespace.c:4583
#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:789
void CommandCounterIncrement(void)
Definition: xact.c:1098
bool RecoveryInProgress(void)
Definition: xlog.c:6291

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 4786 of file namespace.c.

4787 {
4788  /*
4789  * Force search path to be recomputed on next use, also invalidating the
4790  * search path cache (because namespace names, ACLs, or role names may
4791  * have changed).
4792  */
4793  baseSearchPathValid = false;
4794  searchPathCacheValid = false;
4795 }

References baseSearchPathValid, and searchPathCacheValid.

Referenced by InitializeSearchPath().

◆ isAnyTempNamespace()

bool isAnyTempNamespace ( Oid  namespaceId)

Definition at line 3672 of file namespace.c.

3673 {
3674  bool result;
3675  char *nspname;
3676 
3677  /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3678  nspname = get_namespace_name(namespaceId);
3679  if (!nspname)
3680  return false; /* no such namespace? */
3681  result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
3682  (strncmp(nspname, "pg_toast_temp_", 14) == 0);
3683  pfree(nspname);
3684  return result;
3685 }

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 3695 of file namespace.c.

3696 {
3697  /* If it's my own temp namespace, say "false" */
3698  if (isTempOrTempToastNamespace(namespaceId))
3699  return false;
3700  /* Else, if it's any temp namespace, say "true" */
3701  return isAnyTempNamespace(namespaceId);
3702 }
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3658

References isAnyTempNamespace(), and isTempOrTempToastNamespace().

Referenced by pg_is_other_temp_schema().

◆ isTempNamespace()

bool isTempNamespace ( Oid  namespaceId)

Definition at line 3634 of file namespace.c.

3635 {
3636  if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
3637  return true;
3638  return false;
3639 }

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 3658 of file namespace.c.

3659 {
3660  if (OidIsValid(myTempNamespace) &&
3661  (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
3662  return true;
3663  return false;
3664 }

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 3646 of file namespace.c.

3647 {
3648  if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
3649  return true;
3650  return false;
3651 }

References myTempToastNamespace, and OidIsValid.

Referenced by IsToastNamespace().

◆ lookup_collation()

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

Definition at line 2307 of file namespace.c.

2308 {
2309  Oid collid;
2310  HeapTuple colltup;
2311  Form_pg_collation collform;
2312 
2313  /* Check for encoding-specific entry (exact match) */
2314  collid = GetSysCacheOid3(COLLNAMEENCNSP, Anum_pg_collation_oid,
2315  PointerGetDatum(collname),
2317  ObjectIdGetDatum(collnamespace));
2318  if (OidIsValid(collid))
2319  return collid;
2320 
2321  /*
2322  * Check for any-encoding entry. This takes a bit more work: while libc
2323  * collations with collencoding = -1 do work with all encodings, ICU
2324  * collations only work with certain encodings, so we have to check that
2325  * aspect before deciding it's a match.
2326  */
2327  colltup = SearchSysCache3(COLLNAMEENCNSP,
2328  PointerGetDatum(collname),
2329  Int32GetDatum(-1),
2330  ObjectIdGetDatum(collnamespace));
2331  if (!HeapTupleIsValid(colltup))
2332  return InvalidOid;
2333  collform = (Form_pg_collation) GETSTRUCT(colltup);
2334  if (collform->collprovider == COLLPROVIDER_ICU)
2335  {
2337  collid = collform->oid;
2338  else
2339  collid = InvalidOid;
2340  }
2341  else
2342  {
2343  collid = collform->oid;
2344  }
2345  ReleaseSysCache(colltup);
2346  return collid;
2347 }
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:240
#define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3)
Definition: syscache.h:108

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 3413 of file namespace.c.

3414 {
3415  Oid namespaceId;
3416  AclResult aclresult;
3417 
3418  /* check for pg_temp alias */
3419  if (strcmp(nspname, "pg_temp") == 0)
3420  {
3421  /* Initialize temp namespace */
3422  AccessTempTableNamespace(false);
3423  return myTempNamespace;
3424  }
3425 
3426  namespaceId = get_namespace_oid(nspname, false);
3427 
3428  aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
3429  if (aclresult != ACLCHECK_OK)
3430  aclcheck_error(aclresult, OBJECT_SCHEMA,
3431  nspname);
3432 
3433  return namespaceId;
3434 }
AclResult
Definition: acl.h:182
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2700
@ OBJECT_SCHEMA
Definition: parsenodes.h:2297
#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 3370 of file namespace.c.

3371 {
3372  Oid namespaceId;
3373  AclResult aclresult;
3374 
3375  /* check for pg_temp alias */
3376  if (strcmp(nspname, "pg_temp") == 0)
3377  {
3379  return myTempNamespace;
3380 
3381  /*
3382  * Since this is used only for looking up existing objects, there is
3383  * no point in trying to initialize the temp namespace here; and doing
3384  * so might create problems for some callers --- just fall through.
3385  */
3386  }
3387 
3388  namespaceId = get_namespace_oid(nspname, missing_ok);
3389  if (missing_ok && !OidIsValid(namespaceId))
3390  return InvalidOid;
3391 
3392  aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_USAGE);
3393  if (aclresult != ACLCHECK_OK)
3394  aclcheck_error(aclresult, OBJECT_SCHEMA,
3395  nspname);
3396  /* Schema search hook for this lookup */
3397  InvokeNamespaceSearchHook(namespaceId, true);
3398 
3399  return namespaceId;
3400 }
#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 3340 of file namespace.c.

3341 {
3342  /* check for pg_temp alias */
3343  if (strcmp(nspname, "pg_temp") == 0)
3344  {
3346  {
3348  return myTempNamespace;
3349  }
3350 
3351  /*
3352  * Since this is used only for looking up existing objects, there is
3353  * no point in trying to initialize the temp namespace here; and doing
3354  * so might create problems for some callers. Just report "not found".
3355  */
3356  return InvalidOid;
3357  }
3358 
3359  return get_namespace_oid(nspname, true);
3360 }

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 3539 of file namespace.c.

3540 {
3541  RangeVar *rel = makeRangeVar(NULL, NULL, -1);
3542 
3543  switch (list_length(names))
3544  {
3545  case 1:
3546  rel->relname = strVal(linitial(names));
3547  break;
3548  case 2:
3549  rel->schemaname = strVal(linitial(names));
3550  rel->relname = strVal(lsecond(names));
3551  break;
3552  case 3:
3553  rel->catalogname = strVal(linitial(names));
3554  rel->schemaname = strVal(lsecond(names));
3555  rel->relname = strVal(lthird(names));
3556  break;
3557  default:
3558  ereport(ERROR,
3559  (errcode(ERRCODE_SYNTAX_ERROR),
3560  errmsg("improper relation name (too many dotted names): %s",
3561  NameListToString(names))));
3562  break;
3563  }
3564 
3565  return rel;
3566 }
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 1570 of file namespace.c.

1573 {
1574  Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
1575  int numposargs = nargs - list_length(argnames);
1576  int pronallargs;
1577  Oid *p_argtypes;
1578  char **p_argnames;
1579  char *p_argmodes;
1580  bool arggiven[FUNC_MAX_ARGS];
1581  bool isnull;
1582  int ap; /* call args position */
1583  int pp; /* proargs position */
1584  ListCell *lc;
1585 
1586  Assert(argnames != NIL);
1587  Assert(numposargs >= 0);
1588  Assert(nargs <= pronargs);
1589 
1590  /* Ignore this function if its proargnames is null */
1591  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
1592  &isnull);
1593  if (isnull)
1594  return false;
1595 
1596  /* OK, let's extract the argument names and types */
1597  pronallargs = get_func_arg_info(proctup,
1598  &p_argtypes, &p_argnames, &p_argmodes);
1599  Assert(p_argnames != NULL);
1600 
1601  Assert(include_out_arguments ? (pronargs == pronallargs) : (pronargs <= pronallargs));
1602 
1603  /* initialize state for matching */
1604  *argnumbers = (int *) palloc(pronargs * sizeof(int));
1605  memset(arggiven, false, pronargs * sizeof(bool));
1606 
1607  /* there are numposargs positional args before the named args */
1608  for (ap = 0; ap < numposargs; ap++)
1609  {
1610  (*argnumbers)[ap] = ap;
1611  arggiven[ap] = true;
1612  }
1613 
1614  /* now examine the named args */
1615  foreach(lc, argnames)
1616  {
1617  char *argname = (char *) lfirst(lc);
1618  bool found;
1619  int i;
1620 
1621  pp = 0;
1622  found = false;
1623  for (i = 0; i < pronallargs; i++)
1624  {
1625  /* consider only input params, except with include_out_arguments */
1626  if (!include_out_arguments &&
1627  p_argmodes &&
1628  (p_argmodes[i] != FUNC_PARAM_IN &&
1629  p_argmodes[i] != FUNC_PARAM_INOUT &&
1630  p_argmodes[i] != FUNC_PARAM_VARIADIC))
1631  continue;
1632  if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
1633  {
1634  /* fail if argname matches a positional argument */
1635  if (arggiven[pp])
1636  return false;
1637  arggiven[pp] = true;
1638  (*argnumbers)[ap] = pp;
1639  found = true;
1640  break;
1641  }
1642  /* increase pp only for considered parameters */
1643  pp++;
1644  }
1645  /* if name isn't in proargnames, fail */
1646  if (!found)
1647  return false;
1648  ap++;
1649  }
1650 
1651  Assert(ap == nargs); /* processed all actual parameters */
1652 
1653  /* Check for default arguments */
1654  if (nargs < pronargs)
1655  {
1656  int first_arg_with_default = pronargs - procform->pronargdefaults;
1657 
1658  for (pp = numposargs; pp < pronargs; pp++)
1659  {
1660  if (arggiven[pp])
1661  continue;
1662  /* fail if arg not given and no default available */
1663  if (pp < first_arg_with_default)
1664  return false;
1665  (*argnumbers)[ap++] = pp;
1666  }
1667  }
1668 
1669  Assert(ap == pronargs); /* processed all function parameters */
1670 
1671  return true;
1672 }
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:3447
@ FUNC_PARAM_INOUT
Definition: parsenodes.h:3449
@ FUNC_PARAM_VARIADIC
Definition: parsenodes.h:3450
#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 3613 of file namespace.c.

3614 {
3616  ListCell *l;
3617 
3618  initStringInfo(&string);
3619 
3620  foreach(l, names)
3621  {
3622  if (l != list_head(names))
3623  appendStringInfoChar(&string, '.');
3625  }
3626 
3627  return string.data;
3628 }
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:12596
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 3579 of file namespace.c.

3580 {
3582  ListCell *l;
3583 
3584  initStringInfo(&string);
3585 
3586  foreach(l, names)
3587  {
3588  Node *name = (Node *) lfirst(l);
3589 
3590  if (l != list_head(names))
3591  appendStringInfoChar(&string, '.');
3592 
3593  if (IsA(name, String))
3594  appendStringInfoString(&string, strVal(name));
3595  else if (IsA(name, A_Star))
3596  appendStringInfoChar(&string, '*');
3597  else
3598  elog(ERROR, "unexpected node type in name list: %d",
3599  (int) nodeTag(name));
3600  }
3601 
3602  return string.data;
3603 }
#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 2139 of file namespace.c.

2140 {
2141  return OpclassIsVisibleExt(opcid, NULL);
2142 }
static bool OpclassIsVisibleExt(Oid opcid, bool *is_missing)
Definition: namespace.c:2151

References OpclassIsVisibleExt().

Referenced by get_opclass_name(), and getObjectDescription().

◆ OpclassIsVisibleExt()

static bool OpclassIsVisibleExt ( Oid  opcid,
bool is_missing 
)
static

Definition at line 2151 of file namespace.c.

2152 {
2153  HeapTuple opctup;
2154  Form_pg_opclass opcform;
2155  Oid opcnamespace;
2156  bool visible;
2157 
2158  opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
2159  if (!HeapTupleIsValid(opctup))
2160  {
2161  if (is_missing != NULL)
2162  {
2163  *is_missing = true;
2164  return false;
2165  }
2166  elog(ERROR, "cache lookup failed for opclass %u", opcid);
2167  }
2168  opcform = (Form_pg_opclass) GETSTRUCT(opctup);
2169 
2171 
2172  /*
2173  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2174  * the system namespace are surely in the path and so we needn't even do
2175  * list_member_oid() for them.
2176  */
2177  opcnamespace = opcform->opcnamespace;
2178  if (opcnamespace != PG_CATALOG_NAMESPACE &&
2179  !list_member_oid(activeSearchPath, opcnamespace))
2180  visible = false;
2181  else
2182  {
2183  /*
2184  * If it is in the path, it might still not be visible; it could be
2185  * hidden by another opclass of the same name earlier in the path. So
2186  * we must do a slow check to see if this opclass would be found by
2187  * OpclassnameGetOpcid.
2188  */
2189  char *opcname = NameStr(opcform->opcname);
2190 
2191  visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
2192  }
2193 
2194  ReleaseSysCache(opctup);
2195 
2196  return visible;
2197 }
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:2106
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 2106 of file namespace.c.

2107 {
2108  Oid opcid;
2109  ListCell *l;
2110 
2112 
2113  foreach(l, activeSearchPath)
2114  {
2115  Oid namespaceId = lfirst_oid(l);
2116 
2117  if (namespaceId == myTempNamespace)
2118  continue; /* do not look in temp namespace */
2119 
2120  opcid = GetSysCacheOid3(CLAAMNAMENSP, Anum_pg_opclass_oid,
2121  ObjectIdGetDatum(amid),
2122  PointerGetDatum(opcname),
2123  ObjectIdGetDatum(namespaceId));
2124  if (OidIsValid(opcid))
2125  return opcid;
2126  }
2127 
2128  /* Not found in path */
2129  return InvalidOid;
2130 }

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 2034 of file namespace.c.

2035 {
2036  return OperatorIsVisibleExt(oprid, NULL);
2037 }
static bool OperatorIsVisibleExt(Oid oprid, bool *is_missing)
Definition: namespace.c:2046
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 2046 of file namespace.c.

2047 {
2048  HeapTuple oprtup;
2049  Form_pg_operator oprform;
2050  Oid oprnamespace;
2051  bool visible;
2052 
2053  oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
2054  if (!HeapTupleIsValid(oprtup))
2055  {
2056  if (is_missing != NULL)
2057  {
2058  *is_missing = true;
2059  return false;
2060  }
2061  elog(ERROR, "cache lookup failed for operator %u", oprid);
2062  }
2063  oprform = (Form_pg_operator) GETSTRUCT(oprtup);
2064 
2066 
2067  /*
2068  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2069  * the system namespace are surely in the path and so we needn't even do
2070  * list_member_oid() for them.
2071  */
2072  oprnamespace = oprform->oprnamespace;
2073  if (oprnamespace != PG_CATALOG_NAMESPACE &&
2074  !list_member_oid(activeSearchPath, oprnamespace))
2075  visible = false;
2076  else
2077  {
2078  /*
2079  * If it is in the path, it might still not be visible; it could be
2080  * hidden by another operator of the same name and arguments earlier
2081  * in the path. So we must do a slow check to see if this is the same
2082  * operator that would be found by OpernameGetOprid.
2083  */
2084  char *oprname = NameStr(oprform->oprname);
2085 
2086  visible = (OpernameGetOprid(list_make1(makeString(oprname)),
2087  oprform->oprleft, oprform->oprright)
2088  == oprid);
2089  }
2090 
2091  ReleaseSysCache(oprtup);
2092 
2093  return visible;
2094 }
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1770
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 1873 of file namespace.c.

1874 {
1875  FuncCandidateList resultList = NULL;
1876  char *resultSpace = NULL;
1877  int nextResult = 0;
1878  char *schemaname;
1879  char *opername;
1880  Oid namespaceId;
1881  CatCList *catlist;
1882  int i;
1883 
1884  /* deconstruct the name list */
1885  DeconstructQualifiedName(names, &schemaname, &opername);
1886 
1887  if (schemaname)
1888  {
1889  /* use exact schema given */
1890  namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
1891  if (missing_schema_ok && !OidIsValid(namespaceId))
1892  return NULL;
1893  }
1894  else
1895  {
1896  /* flag to indicate we need namespace search */
1897  namespaceId = InvalidOid;
1899  }
1900 
1901  /* Search syscache by name only */
1902  catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
1903 
1904  /*
1905  * In typical scenarios, most if not all of the operators found by the
1906  * catcache search will end up getting returned; and there can be quite a
1907  * few, for common operator names such as '=' or '+'. To reduce the time
1908  * spent in palloc, we allocate the result space as an array large enough
1909  * to hold all the operators. The original coding of this routine did a
1910  * separate palloc for each operator, but profiling revealed that the
1911  * pallocs used an unreasonably large fraction of parsing time.
1912  */
1913 #define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
1914  2 * sizeof(Oid))
1915 
1916  if (catlist->n_members > 0)
1917  resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1918 
1919  for (i = 0; i < catlist->n_members; i++)
1920  {
1921  HeapTuple opertup = &catlist->members[i]->tuple;
1922  Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1923  int pathpos = 0;
1924  FuncCandidateList newResult;
1925 
1926  /* Ignore operators of wrong kind, if specific kind requested */
1927  if (oprkind && operform->oprkind != oprkind)
1928  continue;
1929 
1930  if (OidIsValid(namespaceId))
1931  {
1932  /* Consider only opers in specified namespace */
1933  if (operform->oprnamespace != namespaceId)
1934  continue;
1935  /* No need to check args, they must all be different */
1936  }
1937  else
1938  {
1939  /*
1940  * Consider only opers that are in the search path and are not in
1941  * the temp namespace.
1942  */
1943  ListCell *nsp;
1944 
1945  foreach(nsp, activeSearchPath)
1946  {
1947  if (operform->oprnamespace == lfirst_oid(nsp) &&
1948  operform->oprnamespace != myTempNamespace)
1949  break;
1950  pathpos++;
1951  }
1952  if (nsp == NULL)
1953  continue; /* oper is not in search path */
1954 
1955  /*
1956  * Okay, it's in the search path, but does it have the same
1957  * arguments as something we already accepted? If so, keep only
1958  * the one that appears earlier in the search path.
1959  *
1960  * If we have an ordered list from SearchSysCacheList (the normal
1961  * case), then any conflicting oper must immediately adjoin this
1962  * one in the list, so we only need to look at the newest result
1963  * item. If we have an unordered list, we have to scan the whole
1964  * result list.
1965  */
1966  if (resultList)
1967  {
1968  FuncCandidateList prevResult;
1969 
1970  if (catlist->ordered)
1971  {
1972  if (operform->oprleft == resultList->args[0] &&
1973  operform->oprright == resultList->args[1])
1974  prevResult = resultList;
1975  else
1976  prevResult = NULL;
1977  }
1978  else
1979  {
1980  for (prevResult = resultList;
1981  prevResult;
1982  prevResult = prevResult->next)
1983  {
1984  if (operform->oprleft == prevResult->args[0] &&
1985  operform->oprright == prevResult->args[1])
1986  break;
1987  }
1988  }
1989  if (prevResult)
1990  {
1991  /* We have a match with a previous result */
1992  Assert(pathpos != prevResult->pathpos);
1993  if (pathpos > prevResult->pathpos)
1994  continue; /* keep previous result */
1995  /* replace previous result */
1996  prevResult->pathpos = pathpos;
1997  prevResult->oid = operform->oid;
1998  continue; /* args are same, of course */
1999  }
2000  }
2001  }
2002 
2003  /*
2004  * Okay to add it to result list
2005  */
2006  newResult = (FuncCandidateList) (resultSpace + nextResult);
2007  nextResult += SPACE_PER_OP;
2008 
2009  newResult->pathpos = pathpos;
2010  newResult->oid = operform->oid;
2011  newResult->nominalnargs = 2;
2012  newResult->nargs = 2;
2013  newResult->nvargs = 0;
2014  newResult->ndargs = 0;
2015  newResult->argnumbers = NULL;
2016  newResult->args[0] = operform->oprleft;
2017  newResult->args[1] = operform->oprright;
2018  newResult->next = resultList;
2019  resultList = newResult;
2020  }
2021 
2022  ReleaseSysCacheList(catlist);
2023 
2024  return resultList;
2025 }
#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 1770 of file namespace.c.

1771 {
1772  char *schemaname;
1773  char *opername;
1774  CatCList *catlist;
1775  ListCell *l;
1776 
1777  /* deconstruct the name list */
1778  DeconstructQualifiedName(names, &schemaname, &opername);
1779 
1780  if (schemaname)
1781  {
1782  /* search only in exact schema given */
1783  Oid namespaceId;
1784 
1785  namespaceId = LookupExplicitNamespace(schemaname, true);
1786  if (OidIsValid(namespaceId))
1787  {
1788  HeapTuple opertup;
1789 
1790  opertup = SearchSysCache4(OPERNAMENSP,
1791  CStringGetDatum(opername),
1792  ObjectIdGetDatum(oprleft),
1793  ObjectIdGetDatum(oprright),
1794  ObjectIdGetDatum(namespaceId));
1795  if (HeapTupleIsValid(opertup))
1796  {
1797  Form_pg_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
1798  Oid result = operclass->oid;
1799 
1800  ReleaseSysCache(opertup);
1801  return result;
1802  }
1803  }
1804 
1805  return InvalidOid;
1806  }
1807 
1808  /* Search syscache by name and argument types */
1809  catlist = SearchSysCacheList3(OPERNAMENSP,
1810  CStringGetDatum(opername),
1811  ObjectIdGetDatum(oprleft),
1812  ObjectIdGetDatum(oprright));
1813 
1814  if (catlist->n_members == 0)
1815  {
1816  /* no hope, fall out early */
1817  ReleaseSysCacheList(catlist);
1818  return InvalidOid;
1819  }
1820 
1821  /*
1822  * We have to find the list member that is first in the search path, if
1823  * there's more than one. This doubly-nested loop looks ugly, but in
1824  * practice there should usually be few catlist members.
1825  */
1827 
1828  foreach(l, activeSearchPath)
1829  {
1830  Oid namespaceId = lfirst_oid(l);
1831  int i;
1832 
1833  if (namespaceId == myTempNamespace)
1834  continue; /* do not look in temp namespace */
1835 
1836  for (i = 0; i < catlist->n_members; i++)
1837  {
1838  HeapTuple opertup = &catlist->members[i]->tuple;
1839  Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1840 
1841  if (operform->oprnamespace == namespaceId)
1842  {
1843  Oid result = operform->oid;
1844 
1845  ReleaseSysCacheList(catlist);
1846  return result;
1847  }
1848  }
1849  }
1850 
1851  ReleaseSysCacheList(catlist);
1852  return InvalidOid;
1853 }
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:251
#define SearchSysCacheList3(cacheId, key1, key2, key3)
Definition: syscache.h:126

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 2241 of file namespace.c.

2242 {
2243  return OpfamilyIsVisibleExt(opfid, NULL);
2244 }
static bool OpfamilyIsVisibleExt(Oid opfid, bool *is_missing)
Definition: namespace.c:2253

References OpfamilyIsVisibleExt().

Referenced by getOpFamilyDescription().

◆ OpfamilyIsVisibleExt()

static bool OpfamilyIsVisibleExt ( Oid  opfid,
bool is_missing 
)
static

Definition at line 2253 of file namespace.c.

2254 {
2255  HeapTuple opftup;
2256  Form_pg_opfamily opfform;
2257  Oid opfnamespace;
2258  bool visible;
2259 
2260  opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
2261  if (!HeapTupleIsValid(opftup))
2262  {
2263  if (is_missing != NULL)
2264  {
2265  *is_missing = true;
2266  return false;
2267  }
2268  elog(ERROR, "cache lookup failed for opfamily %u", opfid);
2269  }
2270  opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
2271 
2273 
2274  /*
2275  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2276  * the system namespace are surely in the path and so we needn't even do
2277  * list_member_oid() for them.
2278  */
2279  opfnamespace = opfform->opfnamespace;
2280  if (opfnamespace != PG_CATALOG_NAMESPACE &&
2281  !list_member_oid(activeSearchPath, opfnamespace))
2282  visible = false;
2283  else
2284  {
2285  /*
2286  * If it is in the path, it might still not be visible; it could be
2287  * hidden by another opfamily of the same name earlier in the path. So
2288  * we must do a slow check to see if this opfamily would be found by
2289  * OpfamilynameGetOpfid.
2290  */
2291  char *opfname = NameStr(opfform->opfname);
2292 
2293  visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
2294  }
2295 
2296  ReleaseSysCache(opftup);
2297 
2298  return visible;
2299 }
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
Definition: namespace.c:2208
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 2208 of file namespace.c.

2209 {
2210  Oid opfid;
2211  ListCell *l;
2212 
2214 
2215  foreach(l, activeSearchPath)
2216  {
2217  Oid namespaceId = lfirst_oid(l);
2218 
2219  if (namespaceId == myTempNamespace)
2220  continue; /* do not look in temp namespace */
2221 
2222  opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP, Anum_pg_opfamily_oid,
2223  ObjectIdGetDatum(amid),
2224  PointerGetDatum(opfname),
2225  ObjectIdGetDatum(namespaceId));
2226  if (OidIsValid(opfid))
2227  return opfid;
2228  }
2229 
2230  /* Not found in path */
2231  return InvalidOid;
2232 }

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 4968 of file namespace.c.

4969 {
4970  Oid oid = PG_GETARG_OID(0);
4971  bool result;
4972  bool is_missing = false;
4973 
4974  result = CollationIsVisibleExt(oid, &is_missing);
4975 
4976  if (is_missing)
4977  PG_RETURN_NULL();
4978  PG_RETURN_BOOL(result);
4979 }
#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 4982 of file namespace.c.

4983 {
4984  Oid oid = PG_GETARG_OID(0);
4985  bool result;
4986  bool is_missing = false;
4987 
4988  result = ConversionIsVisibleExt(oid, &is_missing);
4989 
4990  if (is_missing)
4991  PG_RETURN_NULL();
4992  PG_RETURN_BOOL(result);
4993 }

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 4912 of file namespace.c.

4913 {
4914  Oid oid = PG_GETARG_OID(0);
4915  bool result;
4916  bool is_missing = false;
4917 
4918  result = FunctionIsVisibleExt(oid, &is_missing);
4919 
4920  if (is_missing)
4921  PG_RETURN_NULL();
4922  PG_RETURN_BOOL(result);
4923 }

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 5072 of file namespace.c.

5073 {
5074  Oid oid = PG_GETARG_OID(0);
5075 
5077 }
bool isOtherTempNamespace(Oid namespaceId)
Definition: namespace.c:3695

References isOtherTempNamespace(), PG_GETARG_OID, and PG_RETURN_BOOL.

◆ pg_my_temp_schema()

Datum pg_my_temp_schema ( PG_FUNCTION_ARGS  )

Definition at line 5066 of file namespace.c.

5067 {
5069 }
#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 4940 of file namespace.c.

4941 {
4942  Oid oid = PG_GETARG_OID(0);
4943  bool result;
4944  bool is_missing = false;
4945 
4946  result = OpclassIsVisibleExt(oid, &is_missing);
4947 
4948  if (is_missing)
4949  PG_RETURN_NULL();
4950  PG_RETURN_BOOL(result);
4951 }

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 4926 of file namespace.c.

4927 {
4928  Oid oid = PG_GETARG_OID(0);
4929  bool result;
4930  bool is_missing = false;
4931 
4932  result = OperatorIsVisibleExt(oid, &is_missing);
4933 
4934  if (is_missing)
4935  PG_RETURN_NULL();
4936  PG_RETURN_BOOL(result);
4937 }

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 4954 of file namespace.c.

4955 {
4956  Oid oid = PG_GETARG_OID(0);
4957  bool result;
4958  bool is_missing = false;
4959 
4960  result = OpfamilyIsVisibleExt(oid, &is_missing);
4961 
4962  if (is_missing)
4963  PG_RETURN_NULL();
4964  PG_RETURN_BOOL(result);
4965 }

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 4996 of file namespace.c.

4997 {
4998  Oid oid = PG_GETARG_OID(0);
4999  bool result;
5000  bool is_missing = false;
5001 
5002  result = StatisticsObjIsVisibleExt(oid, &is_missing);
5003 
5004  if (is_missing)
5005  PG_RETURN_NULL();
5006  PG_RETURN_BOOL(result);
5007 }
static bool StatisticsObjIsVisibleExt(Oid stxid, bool *is_missing)
Definition: namespace.c:2629

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 4884 of file namespace.c.

4885 {
4886  Oid oid = PG_GETARG_OID(0);
4887  bool result;
4888  bool is_missing = false;
4889 
4890  result = RelationIsVisibleExt(oid, &is_missing);
4891 
4892  if (is_missing)
4893  PG_RETURN_NULL();
4894  PG_RETURN_BOOL(result);
4895 }
static bool RelationIsVisibleExt(Oid relid, bool *is_missing)
Definition: namespace.c:910

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 5052 of file namespace.c.

5053 {
5054  Oid oid = PG_GETARG_OID(0);
5055  bool result;
5056  bool is_missing = false;
5057 
5058  result = TSConfigIsVisibleExt(oid, &is_missing);
5059 
5060  if (is_missing)
5061  PG_RETURN_NULL();
5062  PG_RETURN_BOOL(result);
5063 }
static bool TSConfigIsVisibleExt(Oid cfgid, bool *is_missing)
Definition: namespace.c:3207

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 5024 of file namespace.c.

5025 {
5026  Oid oid = PG_GETARG_OID(0);
5027  bool result;
5028  bool is_missing = false;
5029 
5030  result = TSDictionaryIsVisibleExt(oid, &is_missing);
5031 
5032  if (is_missing)
5033  PG_RETURN_NULL();
5034  PG_RETURN_BOOL(result);
5035 }
static bool TSDictionaryIsVisibleExt(Oid dictId, bool *is_missing)
Definition: namespace.c:2916

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 5010 of file namespace.c.

5011 {
5012  Oid oid = PG_GETARG_OID(0);
5013  bool result;
5014  bool is_missing = false;
5015 
5016  result = TSParserIsVisibleExt(oid, &is_missing);
5017 
5018  if (is_missing)
5019  PG_RETURN_NULL();
5020  PG_RETURN_BOOL(result);
5021 }
static bool TSParserIsVisibleExt(Oid prsId, bool *is_missing)
Definition: namespace.c:2771

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 5038 of file namespace.c.

5039 {
5040  Oid oid = PG_GETARG_OID(0);
5041  bool result;
5042  bool is_missing = false;
5043 
5044  result = TSTemplateIsVisibleExt(oid, &is_missing);
5045 
5046  if (is_missing)
5047  PG_RETURN_NULL();
5048  PG_RETURN_BOOL(result);
5049 }
static bool TSTemplateIsVisibleExt(Oid tmplId, bool *is_missing)
Definition: namespace.c:3062

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 4898 of file namespace.c.

4899 {
4900  Oid oid = PG_GETARG_OID(0);
4901  bool result;
4902  bool is_missing = false;
4903 
4904  result = TypeIsVisibleExt(oid, &is_missing);
4905 
4906  if (is_missing)
4907  PG_RETURN_NULL();
4908  PG_RETURN_BOOL(result);
4909 }
static bool TypeIsVisibleExt(Oid typid, bool *is_missing)
Definition: namespace.c:1037

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 4092 of file namespace.c.

4094 {
4095  char *rawname;
4096  List *namelist;
4097  List *oidlist;
4098  ListCell *l;
4099 
4100  /* Need a modifiable copy */
4101  rawname = pstrdup(searchPath);
4102 
4103  /* Parse string into list of identifiers */
4104  if (!SplitIdentifierString(rawname, ',', &namelist))
4105  {
4106  /* syntax error in name list */
4107  /* this should not happen if GUC checked check_search_path */
4108  elog(ERROR, "invalid list syntax");
4109  }
4110 
4111  /*
4112  * Convert the list of names to a list of OIDs. If any names are not
4113  * recognizable or we don't have read access, just leave them out of the
4114  * list. (We can't raise an error, since the search_path setting has
4115  * already been accepted.) Don't make duplicate entries, either.
4116  */
4117  oidlist = NIL;
4118  *temp_missing = false;
4119  foreach(l, namelist)
4120  {
4121  char *curname = (char *) lfirst(l);
4122  Oid namespaceId;
4123 
4124  if (strcmp(curname, "$user") == 0)
4125  {
4126  /* $user --- substitute namespace matching user name, if any */
4127  HeapTuple tuple;
4128 
4129  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4130  if (HeapTupleIsValid(tuple))
4131  {
4132  char *rname;
4133 
4134  rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
4135  namespaceId = get_namespace_oid(rname, true);
4136  ReleaseSysCache(tuple);
4137  if (OidIsValid(namespaceId) &&
4138  object_aclcheck(NamespaceRelationId, namespaceId, roleid,
4139  ACL_USAGE) == ACLCHECK_OK)
4140  oidlist = lappend_oid(oidlist, namespaceId);
4141  }
4142  }
4143  else if (strcmp(curname, "pg_temp") == 0)
4144  {
4145  /* pg_temp --- substitute temp namespace, if any */
4147  oidlist = lappend_oid(oidlist, myTempNamespace);
4148  else
4149  {
4150  /* If it ought to be the creation namespace, set flag */
4151  if (oidlist == NIL)
4152  *temp_missing = true;
4153  }
4154  }
4155  else
4156  {
4157  /* normal namespace reference */
4158  namespaceId = get_namespace_oid(curname, true);
4159  if (OidIsValid(namespaceId) &&
4160  object_aclcheck(NamespaceRelationId, namespaceId, roleid,
4161  ACL_USAGE) == ACLCHECK_OK)
4162  oidlist = lappend_oid(oidlist, namespaceId);
4163  }
4164  }
4165 
4166  pfree(rawname);
4167  list_free(namelist);
4168 
4169  return oidlist;
4170 }
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 3472 of file namespace.c.

3473 {
3474  char *schemaname;
3475  Oid namespaceId;
3476 
3477  /* deconstruct the name list */
3478  DeconstructQualifiedName(names, &schemaname, objname_p);
3479 
3480  if (schemaname)
3481  {
3482  /* check for pg_temp alias */
3483  if (strcmp(schemaname, "pg_temp") == 0)
3484  {
3485  /* Initialize temp namespace */
3486  AccessTempTableNamespace(false);
3487  return myTempNamespace;
3488  }
3489  /* use exact schema given */
3490  namespaceId = get_namespace_oid(schemaname, false);
3491  /* we do not check for USAGE rights here! */
3492  }
3493  else
3494  {
3495  /* use the default creation namespace */
3498  {
3499  /* Need to initialize temp namespace */
3501  return myTempNamespace;
3502  }
3503  namespaceId = activeCreationNamespace;
3504  if (!OidIsValid(namespaceId))
3505  ereport(ERROR,
3506  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3507  errmsg("no schema has been selected to create in")));
3508  }
3509 
3510  return namespaceId;
3511 }

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 831 of file namespace.c.

832 {
833  switch (newRelation->relpersistence)
834  {
835  case RELPERSISTENCE_TEMP:
837  {
839  ereport(ERROR,
840  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
841  errmsg("cannot create relations in temporary schemas of other sessions")));
842  else
843  ereport(ERROR,
844  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
845  errmsg("cannot create temporary relation in non-temporary schema")));
846  }
847  break;
848  case RELPERSISTENCE_PERMANENT:
850  newRelation->relpersistence = RELPERSISTENCE_TEMP;
851  else if (isAnyTempNamespace(nspid))
852  ereport(ERROR,
853  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
854  errmsg("cannot create relations in temporary schemas of other sessions")));
855  break;
856  default:
858  ereport(ERROR,
859  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
860  errmsg("only temporary relations may be created in temporary schemas")));
861  }
862 }
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 724 of file namespace.c.

727 {
728  uint64 inval_count;
729  Oid relid;
730  Oid oldrelid = InvalidOid;
731  Oid nspid;
732  Oid oldnspid = InvalidOid;
733  bool retry = false;
734 
735  /*
736  * We check the catalog name and then ignore it.
737  */
738  if (relation->catalogname)
739  {
740  if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
741  ereport(ERROR,
742  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
743  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
744  relation->catalogname, relation->schemaname,
745  relation->relname)));
746  }
747 
748  /*
749  * As in RangeVarGetRelidExtended(), we guard against concurrent DDL
750  * operations by tracking whether any invalidation messages are processed
751  * while we're doing the name lookups and acquiring locks. See comments
752  * in that function for a more detailed explanation of this logic.
753  */
754  for (;;)
755  {
756  AclResult aclresult;
757 
758  inval_count = SharedInvalidMessageCounter;
759 
760  /* Look up creation namespace and check for existing relation. */
763  if (existing_relation_id != NULL)
764  relid = get_relname_relid(relation->relname, nspid);
765  else
766  relid = InvalidOid;
767 
768  /*
769  * In bootstrap processing mode, we don't bother with permissions or
770  * locking. Permissions might not be working yet, and locking is
771  * unnecessary.
772  */
774  break;
775 
776  /* Check namespace permissions. */
777  aclresult = object_aclcheck(NamespaceRelationId, nspid, GetUserId(), ACL_CREATE);
778  if (aclresult != ACLCHECK_OK)
779  aclcheck_error(aclresult, OBJECT_SCHEMA,
781 
782  if (retry)
783  {
784  /* If nothing changed, we're done. */
785  if (relid == oldrelid && nspid == oldnspid)
786  break;
787  /* If creation namespace has changed, give up old lock. */
788  if (nspid != oldnspid)
789  UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
791  /* If name points to something different, give up old lock. */
792  if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
793  UnlockRelationOid(oldrelid, lockmode);
794  }
795 
796  /* Lock namespace. */
797  if (nspid != oldnspid)
798  LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
799 
800  /* Lock relation, if required if and we have permission. */
801  if (lockmode != NoLock && OidIsValid(relid))
802  {
803  if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
805  relation->relname);
806  if (relid != oldrelid)
807  LockRelationOid(relid, lockmode);
808  }
809 
810  /* If no invalidation message were processed, we're done! */
811  if (inval_count == SharedInvalidMessageCounter)
812  break;
813 
814  /* Something may have changed, so recheck our work. */
815  retry = true;
816  oldrelid = relid;
817  oldnspid = nspid;
818  }
819 
821  if (existing_relation_id != NULL)
822  *existing_relation_id = relid;
823  return nspid;
824 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4142
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:831
Oid RangeVarGetCreationNamespace(const RangeVar *newRelation)
Definition: namespace.c:639
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(), ATExecMergePartitions(), ATExecSplitPartition(), DefineCompositeType(), DefineRelation(), DefineSequence(), DefineVirtualRelation(), and transformCreateStmt().

◆ RangeVarGetCreationNamespace()

Oid RangeVarGetCreationNamespace ( const RangeVar newRelation)

Definition at line 639 of file namespace.c.

640 {
641  Oid namespaceId;
642 
643  /*
644  * We check the catalog name and then ignore it.
645  */
646  if (newRelation->catalogname)
647  {
648  if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
649  ereport(ERROR,
650  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
651  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
652  newRelation->catalogname, newRelation->schemaname,
653  newRelation->relname)));
654  }
655 
656  if (newRelation->schemaname)
657  {
658  /* check for pg_temp alias */
659  if (strcmp(newRelation->schemaname, "pg_temp") == 0)
660  {
661  /* Initialize temp namespace */
663  return myTempNamespace;
664  }
665  /* use exact schema given */
666  namespaceId = get_namespace_oid(newRelation->schemaname, false);
667  /* we do not check for USAGE rights here! */
668  }
669  else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
670  {
671  /* Initialize temp namespace */
673  return myTempNamespace;
674  }
675  else
676  {
677  /* use the default creation namespace */
680  {
681  /* Need to initialize temp namespace */
683  return myTempNamespace;
684  }
685  namespaceId = activeCreationNamespace;
686  if (!OidIsValid(namespaceId))
687  ereport(ERROR,
688  (errcode(ERRCODE_UNDEFINED_SCHEMA),
689  errmsg("no schema has been selected to create in")));
690  }
691 
692  /* Note: callers will check for CREATE rights when appropriate */
693 
694  return namespaceId;
695 }

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 426 of file namespace.c.

429 {
430  uint64 inval_count;
431  Oid relId;
432  Oid oldRelId = InvalidOid;
433  bool retry = false;
434  bool missing_ok = (flags & RVR_MISSING_OK) != 0;
435 
436  /* verify that flags do no conflict */
437  Assert(!((flags & RVR_NOWAIT) && (flags & RVR_SKIP_LOCKED)));
438 
439  /*
440  * We check the catalog name and then ignore it.
441  */
442  if (relation->catalogname)
443  {
444  if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
445  ereport(ERROR,
446  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
447  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
448  relation->catalogname, relation->schemaname,
449  relation->relname)));
450  }
451 
452  /*
453  * DDL operations can change the results of a name lookup. Since all such
454  * operations will generate invalidation messages, we keep track of
455  * whether any such messages show up while we're performing the operation,
456  * and retry until either (1) no more invalidation messages show up or (2)
457  * the answer doesn't change.
458  *
459  * But if lockmode = NoLock, then we assume that either the caller is OK
460  * with the answer changing under them, or that they already hold some
461  * appropriate lock, and therefore return the first answer we get without
462  * checking for invalidation messages. Also, if the requested lock is
463  * already held, LockRelationOid will not AcceptInvalidationMessages, so
464  * we may fail to notice a change. We could protect against that case by
465  * calling AcceptInvalidationMessages() before beginning this loop, but
466  * that would add a significant amount overhead, so for now we don't.
467  */
468  for (;;)
469  {
470  /*
471  * Remember this value, so that, after looking up the relation name
472  * and locking its OID, we can check whether any invalidation messages
473  * have been processed that might require a do-over.
474  */
475  inval_count = SharedInvalidMessageCounter;
476 
477  /*
478  * Some non-default relpersistence value may have been specified. The
479  * parser never generates such a RangeVar in simple DML, but it can
480  * happen in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY
481  * KEY)". Such a command will generate an added CREATE INDEX
482  * operation, which must be careful to find the temp table, even when
483  * pg_temp is not first in the search path.
484  */
485  if (relation->relpersistence == RELPERSISTENCE_TEMP)
486  {
488  relId = InvalidOid; /* this probably can't happen? */
489  else
490  {
491  if (relation->schemaname)
492  {
493  Oid namespaceId;
494 
495  namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
496 
497  /*
498  * For missing_ok, allow a non-existent schema name to
499  * return InvalidOid.
500  */
501  if (namespaceId != myTempNamespace)
502  ereport(ERROR,
503  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
504  errmsg("temporary tables cannot specify a schema name")));
505  }
506 
507  relId = get_relname_relid(relation->relname, myTempNamespace);
508  }
509  }
510  else if (relation->schemaname)
511  {
512  Oid namespaceId;
513 
514  /* use exact schema given */
515  namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
516  if (missing_ok && !OidIsValid(namespaceId))
517  relId = InvalidOid;
518  else
519  relId = get_relname_relid(relation->relname, namespaceId);
520  }
521  else
522  {
523  /* search the namespace path */
524  relId = RelnameGetRelid(relation->relname);
525  }
526 
527  /*
528  * Invoke caller-supplied callback, if any.
529  *
530  * This callback is a good place to check permissions: we haven't
531  * taken the table lock yet (and it's really best to check permissions
532  * before locking anything!), but we've gotten far enough to know what
533  * OID we think we should lock. Of course, concurrent DDL might
534  * change things while we're waiting for the lock, but in that case
535  * the callback will be invoked again for the new OID.
536  */
537  if (callback)
538  callback(relation, relId, oldRelId, callback_arg);
539 
540  /*
541  * If no lock requested, we assume the caller knows what they're
542  * doing. They should have already acquired a heavyweight lock on
543  * this relation earlier in the processing of this same statement, so
544  * it wouldn't be appropriate to AcceptInvalidationMessages() here, as
545  * that might pull the rug out from under them.
546  */
547  if (lockmode == NoLock)
548  break;
549 
550  /*
551  * If, upon retry, we get back the same OID we did last time, then the
552  * invalidation messages we processed did not change the final answer.
553  * So we're done.
554  *
555  * If we got a different OID, we've locked the relation that used to
556  * have this name rather than the one that does now. So release the
557  * lock.
558  */
559  if (retry)
560  {
561  if (relId == oldRelId)
562  break;
563  if (OidIsValid(oldRelId))
564  UnlockRelationOid(oldRelId, lockmode);
565  }
566 
567  /*
568  * Lock relation. This will also accept any pending invalidation
569  * messages. If we got back InvalidOid, indicating not found, then
570  * there's nothing to lock, but we accept invalidation messages
571  * anyway, to flush any negative catcache entries that may be
572  * lingering.
573  */
574  if (!OidIsValid(relId))
576  else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED)))
577  LockRelationOid(relId, lockmode);
578  else if (!ConditionalLockRelationOid(relId, lockmode))
579  {
580  int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR;
581 
582  if (relation->schemaname)
583  ereport(elevel,
584  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
585  errmsg("could not obtain lock on relation \"%s.%s\"",
586  relation->schemaname, relation->relname)));
587  else
588  ereport(elevel,
589  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
590  errmsg("could not obtain lock on relation \"%s\"",
591  relation->relname)));
592 
593  return InvalidOid;
594  }
595 
596  /*
597  * If no invalidation message were processed, we're done!
598  */
599  if (inval_count == SharedInvalidMessageCounter)
600  break;
601 
602  /*
603  * Something may have changed. Let's repeat the name lookup, to make
604  * sure this name still references the same relation it did
605  * previously.
606  */
607  retry = true;
608  oldRelId = relId;
609  }
610 
611  if (!OidIsValid(relId))
612  {
613  int elevel = missing_ok ? DEBUG1 : ERROR;
614 
615  if (relation->schemaname)
616  ereport(elevel,
618  errmsg("relation \"%s.%s\" does not exist",
619  relation->schemaname, relation->relname)));
620  else
621  ereport(elevel,
623  errmsg("relation \"%s\" does not exist",
624  relation->relname)));
625  }
626  return relId;
627 }
#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:870
@ 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 4284 of file namespace.c.

4285 {
4286  Oid roleid = GetUserId();
4287  bool pathChanged;
4288  const SearchPathCacheEntry *entry;
4289 
4290  /* Do nothing if path is already valid. */
4291  if (baseSearchPathValid && namespaceUser == roleid)
4292  return;
4293 
4294  entry = cachedNamespacePath(namespace_search_path, roleid);
4295 
4296  if (baseCreationNamespace == entry->firstNS &&
4298  equal(entry->finalPath, baseSearchPath))
4299  {
4300  pathChanged = false;
4301  }
4302  else
4303  {
4304  MemoryContext oldcxt;
4305  List *newpath;
4306 
4307  pathChanged = true;
4308 
4309  /* Must save OID list in permanent storage. */
4311  newpath = list_copy(entry->finalPath);
4312  MemoryContextSwitchTo(oldcxt);
4313 
4314  /* Now safe to assign to state variables. */
4316  baseSearchPath = newpath;
4317  baseCreationNamespace = entry->firstNS;
4319  }
4320 
4321  /* Mark the path valid. */
4322  baseSearchPathValid = true;
4323  namespaceUser = roleid;
4324 
4325  /* And make it active. */
4329 
4330  /*
4331  * Bump the generation only if something actually changed. (Notice that
4332  * what we compared to was the old state of the base path variables.)
4333  */
4334  if (pathChanged)
4336 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
static const SearchPathCacheEntry * cachedNamespacePath(const char *searchPath, Oid roleid)
Definition: namespace.c:4229
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 898 of file namespace.c.

899 {
900  return RelationIsVisibleExt(relid, NULL);
901 }

References RelationIsVisibleExt().

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

◆ RelationIsVisibleExt()

static bool RelationIsVisibleExt ( Oid  relid,
bool is_missing 
)
static

Definition at line 910 of file namespace.c.

911 {
912  HeapTuple reltup;
913  Form_pg_class relform;
914  Oid relnamespace;
915  bool visible;
916 
917  reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
918  if (!HeapTupleIsValid(reltup))
919  {
920  if (is_missing != NULL)
921  {
922  *is_missing = true;
923  return false;
924  }
925  elog(ERROR, "cache lookup failed for relation %u", relid);
926  }
927  relform = (Form_pg_class) GETSTRUCT(reltup);
928 
930 
931  /*
932  * Quick check: if it ain't in the path at all, it ain't visible. Items in
933  * the system namespace are surely in the path and so we needn't even do
934  * list_member_oid() for them.
935  */
936  relnamespace = relform->relnamespace;
937  if (relnamespace != PG_CATALOG_NAMESPACE &&
938  !list_member_oid(activeSearchPath, relnamespace))
939  visible = false;
940  else
941  {
942  /*
943  * If it is in the path, it might still not be visible; it could be
944  * hidden by another relation of the same name earlier in the path. So
945  * we must do a slow check for conflicting relations.
946  */
947  char *relname = NameStr(relform->relname);
948  ListCell *l;
949 
950  visible = false;
951  foreach(l, activeSearchPath)
952  {
953  Oid namespaceId = lfirst_oid(l);
954 
955  if (namespaceId == relnamespace)
956  {
957  /* Found it first in path */
958  visible = true;
959  break;
960  }
961  if (OidIsValid(get_relname_relid(relname, namespaceId)))
962  {
963  /* Found something else first in path */
964  break;
965  }
966  }
967  }
968 
969  ReleaseSysCache(reltup);
970 
971  return visible;
972 }
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 870 of file namespace.c.

871 {
872  Oid relid;
873  ListCell *l;
874 
876 
877  foreach(l, activeSearchPath)
878  {
879  Oid namespaceId = lfirst_oid(l);
880 
881  relid = get_relname_relid(relname, namespaceId);
882  if (OidIsValid(relid))
883  return relid;
884  }
885 
886  /* Not found in path */
887  return InvalidOid;
888 }

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 4583 of file namespace.c.

4584 {
4585  ObjectAddress object;
4586 
4587  /*
4588  * We want to get rid of everything in the target namespace, but not the
4589  * namespace itself (deleting it only to recreate it later would be a
4590  * waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
4591  * deletion, and we want to not drop any extensions that might happen to
4592  * own temp objects.
4593  */
4594  object.classId = NamespaceRelationId;
4595  object.objectId = tempNamespaceId;
4596  object.objectSubId = 0;
4597 
4598  performDeletion(&object, DROP_CASCADE,
4603 }
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:2335

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 4609 of file namespace.c.

4610 {
4611  if (OidIsValid(myTempNamespace)) /* should always be true */
4612  {
4613  /* Need to ensure we have a usable transaction. */
4617 
4619 
4622  }
4623 }
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:3033
void CommitTransactionCommand(void)
Definition: xact.c:3131
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4849

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

Referenced by AtEOXact_Namespace().

◆ ResetTempTableNamespace()

void ResetTempTableNamespace ( void  )

Definition at line 4629 of file namespace.c.

4630 {
4633 }

References myTempNamespace, OidIsValid, and RemoveTempRelations().

Referenced by DiscardAll(), and DiscardCommand().

◆ SearchPathMatchesCurrentEnvironment()

bool SearchPathMatchesCurrentEnvironment ( SearchPathMatcher path)

Definition at line 3896 of file namespace.c.

3897 {
3898  ListCell *lc,
3899  *lcp;
3900 
3902 
3903  /* Quick out if already known equal to active path. */
3904  if (path->generation == activePathGeneration)
3905  return true;
3906 
3907  /* We scan down the activeSearchPath to see if it matches the input. */
3909 
3910  /* If path->addTemp, first item should be my temp namespace. */
3911  if (path->addTemp)
3912  {
3913  if (lc && lfirst_oid(lc) == myTempNamespace)
3914  lc = lnext(activeSearchPath, lc);
3915  else
3916  return false;
3917  }
3918  /* If path->addCatalog, next item should be pg_catalog. */
3919  if (path->addCatalog)
3920  {
3921  if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
3922  lc = lnext(activeSearchPath, lc);
3923  else
3924  return false;
3925  }
3926  /* We should now be looking at the activeCreationNamespace. */
3927  if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
3928  return false;
3929  /* The remainder of activeSearchPath should match path->schemas. */
3930  foreach(lcp, path->schemas)
3931  {
3932  if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
3933  lc = lnext(activeSearchPath, lc);
3934  else
3935  return false;
3936  }
3937  if (lc)
3938  return false;
3939 
3940  /*
3941  * Update path->generation so that future tests will return quickly, so
3942  * long as the active search path doesn't change.
3943  */
3945 
3946  return true;
3947 }
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 3806 of file namespace.c.

3807 {
3808  /* Worker should not have created its own namespaces ... */
3812 
3813  /* Assign same namespace OIDs that leader has */
3814  myTempNamespace = tempNamespaceId;
3815  myTempToastNamespace = tempToastNamespaceId;
3816 
3817  /*
3818  * It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
3819  * Even if the namespace is new so far as the leader is concerned, it's
3820  * not new to the worker, and we certainly wouldn't want the worker trying
3821  * to destroy it.
3822  */
3823 
3824  baseSearchPathValid = false; /* may need to rebuild list */
3825  searchPathCacheValid = false;
3826 }

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 {
309 
312  return;
313 
314  /* make sure we don't leave dangling pointers if nsphash_create fails */
315  SearchPathCache = NULL;
317 
319  /* arbitrary initial starting size of 16 elements */
320  SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL);
321  searchPathCacheValid = true;
322 }
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
static SearchPathCacheEntry * LastSearchPathCacheEntry
Definition: namespace.c:300
#define SPCACHE_RESET_THRESHOLD
Definition: namespace.c:297
static nsphash_hash * SearchPathCache
Definition: namespace.c:299

References Assert, LastSearchPathCacheEntry, MemoryContextReset(), SearchPathCache, SearchPathCacheContext, searchPathCacheValid, and SPCACHE_RESET_THRESHOLD.

Referenced by cachedNamespacePath(), and check_search_path().

◆ spcache_insert()

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

Definition at line 359 of file namespace.c.

360 {
362  LastSearchPathCacheEntry->key.roleid == roleid &&
363  strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
364  {
366  }
367  else
368  {
369  SearchPathCacheEntry *entry;
370  SearchPathCacheKey cachekey = {
371  .searchPath = searchPath,
372  .roleid = roleid
373  };
374 
375  /*
376  * searchPath is not saved in SearchPathCacheContext. First perform a
377  * lookup, and copy searchPath only if we need to create a new entry.
378  */
379  entry = nsphash_lookup(SearchPathCache, cachekey);
380 
381  if (!entry)
382  {
383  bool found;
384 
385  cachekey.searchPath = MemoryContextStrdup(SearchPathCacheContext, searchPath);
386  entry = nsphash_insert(SearchPathCache, cachekey, &found);
387  Assert(!found);
388 
389  entry->oidlist = NIL;
390  entry->finalPath = NIL;
391  entry->firstNS = InvalidOid;
392  entry->temp_missing = false;
393  entry->forceRecompute = false;
394  /* do not touch entry->status, used by simplehash */
395  }
396 
397  LastSearchPathCacheEntry = entry;
398  return entry;
399  }
400 }
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 329 of file namespace.c.

330 {
332  LastSearchPathCacheEntry->key.roleid == roleid &&
333  strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
334  {
336  }
337  else
338  {
339  SearchPathCacheEntry *entry;
340  SearchPathCacheKey cachekey = {
341  .searchPath = searchPath,
342  .roleid = roleid
343  };
344 
345  entry = nsphash_lookup(SearchPathCache, cachekey);
346  if (entry)
347  LastSearchPathCacheEntry = entry;
348  return entry;
349  }
350 }

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 2617 of file namespace.c.

2618 {
2619  return StatisticsObjIsVisibleExt(stxid, NULL);
2620 }

References StatisticsObjIsVisibleExt().

Referenced by getObjectDescription().

◆ StatisticsObjIsVisibleExt()

static bool StatisticsObjIsVisibleExt ( Oid  stxid,
bool is_missing 
)
static

Definition at line 2629 of file namespace.c.

2630 {
2631  HeapTuple stxtup;
2632  Form_pg_statistic_ext stxform;
2633  Oid stxnamespace;
2634  bool visible;
2635 
2636  stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stxid));
2637  if (!HeapTupleIsValid(stxtup))
2638  {
2639  if (is_missing != NULL)
2640  {
2641  *is_missing = true;
2642  return false;
2643  }
2644  elog(ERROR, "cache lookup failed for statistics object %u", stxid);
2645  }
2646  stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
2647 
2649 
2650  /*
2651  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2652  * the system namespace are surely in the path and so we needn't even do
2653  * list_member_oid() for them.
2654  */
2655  stxnamespace = stxform->stxnamespace;
2656  if (stxnamespace != PG_CATALOG_NAMESPACE &&
2657  !list_member_oid(activeSearchPath, stxnamespace))
2658  visible = false;
2659  else
2660  {
2661  /*
2662  * If it is in the path, it might still not be visible; it could be
2663  * hidden by another statistics object of the same name earlier in the
2664  * path. So we must do a slow check for conflicting objects.
2665  */
2666  char *stxname = NameStr(stxform->stxname);
2667  ListCell *l;
2668 
2669  visible = false;
2670  foreach(l, activeSearchPath)
2671  {
2672  Oid namespaceId = lfirst_oid(l);
2673 
2674  if (namespaceId == stxnamespace)
2675  {
2676  /* Found it first in path */
2677  visible = true;
2678  break;
2679  }
2680  if (SearchSysCacheExists2(STATEXTNAMENSP,
2681  PointerGetDatum(stxname),
2682  ObjectIdGetDatum(namespaceId)))
2683  {
2684  /* Found something else first in path */
2685  break;
2686  }
2687  }
2688  }
2689 
2690  ReleaseSysCache(stxtup);
2691 
2692  return visible;
2693 }
FormData_pg_statistic_ext * Form_pg_statistic_ext
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:97

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 3195 of file namespace.c.

3196 {
3197  return TSConfigIsVisibleExt(cfgid, NULL);
3198 }

References TSConfigIsVisibleExt().

Referenced by getObjectDescription(), and regconfigout().

◆ TSConfigIsVisibleExt()

static bool TSConfigIsVisibleExt ( Oid  cfgid,
bool is_missing 
)
static

Definition at line 3207 of file namespace.c.

3208 {
3209  HeapTuple tup;
3210  Form_pg_ts_config form;
3211  Oid namespace;
3212  bool visible;
3213 
3214  tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
3215  if (!HeapTupleIsValid(tup))
3216  {
3217  if (is_missing != NULL)
3218  {
3219  *is_missing = true;
3220  return false;
3221  }
3222  elog(ERROR, "cache lookup failed for text search configuration %u",
3223  cfgid);
3224  }
3225  form = (Form_pg_ts_config) GETSTRUCT(tup);
3226 
3228 
3229  /*
3230  * Quick check: if it ain't in the path at all, it ain't visible. Items in
3231  * the system namespace are surely in the path and so we needn't even do
3232  * list_member_oid() for them.
3233  */
3234  namespace = form->cfgnamespace;
3235  if (namespace != PG_CATALOG_NAMESPACE &&
3236  !list_member_oid(activeSearchPath, namespace))
3237  visible = false;
3238  else
3239  {
3240  /*
3241  * If it is in the path, it might still not be visible; it could be
3242  * hidden by another configuration of the same name earlier in the
3243  * path. So we must do a slow check for conflicting configurations.
3244  */
3245  char *name = NameStr(form->cfgname);
3246  ListCell *l;
3247 
3248  visible = false;
3249  foreach(l, activeSearchPath)
3250  {
3251  Oid namespaceId = lfirst_oid(l);
3252 
3253  if (namespaceId == myTempNamespace)
3254  continue; /* do not look in temp namespace */
3255 
3256  if (namespaceId == namespace)
3257  {
3258  /* Found it first in path */
3259  visible = true;
3260  break;
3261  }
3262  if (SearchSysCacheExists2(TSCONFIGNAMENSP,
3264  ObjectIdGetDatum(namespaceId)))
3265  {
3266  /* Found something else first in path */
3267  break;
3268  }
3269  }
3270  }
3271 
3272  ReleaseSysCache(tup);
3273 
3274  return visible;
3275 }
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 2904 of file namespace.c.

2905 {
2906  return TSDictionaryIsVisibleExt(dictId, NULL);
2907 }

References TSDictionaryIsVisibleExt().

Referenced by getObjectDescription(), and regdictionaryout().

◆ TSDictionaryIsVisibleExt()

static bool TSDictionaryIsVisibleExt ( Oid  dictId,
bool is_missing 
)
static

Definition at line 2916 of file namespace.c.

2917 {
2918  HeapTuple tup;
2919  Form_pg_ts_dict form;
2920  Oid namespace;
2921  bool visible;
2922 
2923  tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
2924  if (!HeapTupleIsValid(tup))
2925  {
2926  if (is_missing != NULL)
2927  {
2928  *is_missing = true;
2929  return false;
2930  }
2931  elog(ERROR, "cache lookup failed for text search dictionary %u",
2932  dictId);
2933  }
2934  form = (Form_pg_ts_dict) GETSTRUCT(tup);
2935 
2937 
2938  /*
2939  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2940  * the system namespace are surely in the path and so we needn't even do
2941  * list_member_oid() for them.
2942  */
2943  namespace = form->dictnamespace;
2944  if (namespace != PG_CATALOG_NAMESPACE &&
2945  !list_member_oid(activeSearchPath, namespace))
2946  visible = false;
2947  else
2948  {
2949  /*
2950  * If it is in the path, it might still not be visible; it could be
2951  * hidden by another dictionary of the same name earlier in the path.
2952  * So we must do a slow check for conflicting dictionaries.
2953  */
2954  char *name = NameStr(form->dictname);
2955  ListCell *l;
2956 
2957  visible = false;
2958  foreach(l, activeSearchPath)
2959  {
2960  Oid namespaceId = lfirst_oid(l);
2961 
2962  if (namespaceId == myTempNamespace)
2963  continue; /* do not look in temp namespace */
2964 
2965  if (namespaceId == namespace)
2966  {
2967  /* Found it first in path */
2968  visible = true;
2969  break;
2970  }
2971  if (SearchSysCacheExists2(TSDICTNAMENSP,
2973  ObjectIdGetDatum(namespaceId)))
2974  {
2975  /* Found something else first in path */
2976  break;
2977  }
2978  }
2979  }
2980 
2981  ReleaseSysCache(tup);
2982 
2983  return visible;
2984 }
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 2759 of file namespace.c.

2760 {
2761  return TSParserIsVisibleExt(prsId, NULL);
2762 }

References TSParserIsVisibleExt().

Referenced by getObjectDescription().

◆ TSParserIsVisibleExt()

static bool TSParserIsVisibleExt ( Oid  prsId,
bool is_missing 
)
static

Definition at line 2771 of file namespace.c.