Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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 "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, int *fgc_flags)
 
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, int *fgc_flags)
 
bool FunctionIsVisible (Oid funcid)
 
Oid OpernameGetOprid (List *names, Oid oprleft, Oid oprright)
 
FuncCandidateList OpernameGetCandidates (List *names, char oprkind, bool missing_schema_ok, int *fgc_flags)
 
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 286 of file namespace.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 287 of file namespace.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   SearchPathCacheEntry

Definition at line 280 of file namespace.c.

◆ SH_EQUAL

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

Definition at line 284 of file namespace.c.

◆ SH_HASH_KEY

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

Definition at line 283 of file namespace.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 282 of file namespace.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   SearchPathCacheKey

Definition at line 281 of file namespace.c.

◆ SH_PREFIX

#define SH_PREFIX   nsphash

Definition at line 279 of file namespace.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 285 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:32

◆ SPCACHE_RESET_THRESHOLD

#define SPCACHE_RESET_THRESHOLD   256

Definition at line 296 of file namespace.c.

Typedef Documentation

◆ SearchPathCacheEntry

◆ SearchPathCacheKey

Function Documentation

◆ AccessTempTableNamespace()

static void AccessTempTableNamespace ( bool  force)
static

Definition at line 4432 of file namespace.c.

4433{
4434 /*
4435 * Make note that this temporary namespace has been accessed in this
4436 * transaction.
4437 */
4439
4440 /*
4441 * If the caller attempting to access a temporary schema expects the
4442 * creation of the namespace to be pending and should be enforced, then go
4443 * through the creation.
4444 */
4445 if (!force && OidIsValid(myTempNamespace))
4446 return;
4447
4448 /*
4449 * The temporary tablespace does not exist yet and is wanted, so
4450 * initialize it.
4451 */
4453}
#define OidIsValid(objectId)
Definition: c.h:775
static Oid myTempNamespace
Definition: namespace.c:200
static void InitTempTableNamespace(void)
Definition: namespace.c:4460
int MyXactFlags
Definition: xact.c:136
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition: xact.h:103

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

4784{
4785 /* don't access search_path during bootstrap */
4787
4788 /*
4789 * We mark the path as needing recomputation, but don't do anything until
4790 * it's needed. This avoids trying to do database access during GUC
4791 * initialization, or outside a transaction.
4792 *
4793 * This does not invalidate the search path cache, so if this value had
4794 * been previously set and no syscache invalidations happened,
4795 * recomputation may not be necessary.
4796 */
4797 baseSearchPathValid = false;
4798}
Assert(PointerIsAligned(start, uint64))
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:476
static bool baseSearchPathValid
Definition: namespace.c:157

References Assert(), baseSearchPathValid, and IsBootstrapProcessingMode.

◆ AtEOSubXact_Namespace()

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

Definition at line 4628 of file namespace.c.

4630{
4631
4632 if (myTempNamespaceSubID == mySubid)
4633 {
4634 if (isCommit)
4635 myTempNamespaceSubID = parentSubid;
4636 else
4637 {
4639 /* TEMP namespace creation failed, so reset state */
4642 baseSearchPathValid = false; /* need to rebuild list */
4643 searchPathCacheValid = false;
4644
4645 /*
4646 * Reset the temporary namespace flag in MyProc. We assume that
4647 * this operation is atomic.
4648 *
4649 * Because this subtransaction is aborting, the pg_namespace row
4650 * is not visible to anyone else anyway, but that doesn't matter:
4651 * it's not a problem if objects contained in this namespace are
4652 * removed concurrently.
4653 */
4655 }
4656 }
4657}
#define InvalidSubTransactionId
Definition: c.h:664
static bool searchPathCacheValid
Definition: namespace.c:163
static SubTransactionId myTempNamespaceSubID
Definition: namespace.c:204
static Oid myTempToastNamespace
Definition: namespace.c:202
#define InvalidOid
Definition: postgres_ext.h:37
PGPROC * MyProc
Definition: proc.c:66
Oid tempNamespaceId
Definition: proc.h:227

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

4583{
4584 /*
4585 * If we abort the transaction in which a temp namespace was selected,
4586 * we'll have to do any creation or cleanout work over again. So, just
4587 * forget the namespace entirely until next time. On the other hand, if
4588 * we commit then register an exit callback to clean out the temp tables
4589 * at backend shutdown. (We only want to register the callback once per
4590 * session, so this is a good place to do it.)
4591 */
4593 {
4594 if (isCommit)
4596 else
4597 {
4600 baseSearchPathValid = false; /* need to rebuild list */
4601 searchPathCacheValid = false;
4602
4603 /*
4604 * Reset the temporary namespace flag in MyProc. We assume that
4605 * this operation is atomic.
4606 *
4607 * Because this transaction is aborting, the pg_namespace row is
4608 * not visible to anyone else anyway, but that doesn't matter:
4609 * it's not a problem if objects contained in this namespace are
4610 * removed concurrently.
4611 */
4613 }
4615 }
4616
4617}
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:4694

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

4315{
4316 MemoryContext oldcxt;
4317 SearchPathCacheEntry *entry;
4318
4319 spcache_init();
4320
4321 entry = spcache_insert(searchPath, roleid);
4322
4323 /*
4324 * An OOM may have resulted in a cache entry with missing 'oidlist' or
4325 * 'finalPath', so just compute whatever is missing.
4326 */
4327
4328 if (entry->oidlist == NIL)
4329 {
4331 entry->oidlist = preprocessNamespacePath(searchPath, roleid,
4332 &entry->temp_missing);
4333 MemoryContextSwitchTo(oldcxt);
4334 }
4335
4336 /*
4337 * If a hook is set, we must recompute finalPath from the oidlist each
4338 * time, because the hook may affect the result. This is still much faster
4339 * than recomputing from the string (and doing catalog lookups and ACL
4340 * checks).
4341 */
4342 if (entry->finalPath == NIL || object_access_hook ||
4343 entry->forceRecompute)
4344 {
4345 list_free(entry->finalPath);
4346 entry->finalPath = NIL;
4347
4349 entry->finalPath = finalNamespacePath(entry->oidlist,
4350 &entry->firstNS);
4351 MemoryContextSwitchTo(oldcxt);
4352
4353 /*
4354 * If an object_access_hook is set when finalPath is calculated, the
4355 * result may be affected by the hook. Force recomputation of
4356 * finalPath the next time this cache entry is used, even if the
4357 * object_access_hook is not set at that time.
4358 */
4359 entry->forceRecompute = object_access_hook ? true : false;
4360 }
4361
4362 return entry;
4363}
return true
Definition: isn.c:130
void list_free(List *list)
Definition: list.c:1546
static MemoryContext SearchPathCacheContext
Definition: namespace.c:164
static SearchPathCacheEntry * spcache_insert(const char *searchPath, Oid roleid)
Definition: namespace.c:373
static List * preprocessNamespacePath(const char *searchPath, Oid roleid, bool *temp_missing)
Definition: namespace.c:4177
static void spcache_init(void)
Definition: namespace.c:305
static List * finalNamespacePath(List *oidlist, Oid *firstNS)
Definition: namespace.c:4268
object_access_hook_type object_access_hook
Definition: objectaccess.c:22
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define NIL
Definition: pg_list.h:68

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

Referenced by recomputeNamespacePath().

◆ check_search_path()

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

Definition at line 4727 of file namespace.c.

4728{
4729 Oid roleid = InvalidOid;
4730 const char *searchPath = *newval;
4731 char *rawname;
4732 List *namelist;
4733 bool use_cache = (SearchPathCacheContext != NULL);
4734
4735 /*
4736 * We used to try to check that the named schemas exist, but there are
4737 * many valid use-cases for having search_path settings that include
4738 * schemas that don't exist; and often, we are not inside a transaction
4739 * here and so can't consult the system catalogs anyway. So now, the only
4740 * requirement is syntactic validity of the identifier list.
4741 *
4742 * Checking only the syntactic validity also allows us to use the search
4743 * path cache (if available) to avoid calling SplitIdentifierString() on
4744 * the same string repeatedly.
4745 */
4746 if (use_cache)
4747 {
4748 spcache_init();
4749
4750 roleid = GetUserId();
4751
4752 if (spcache_lookup(searchPath, roleid) != NULL)
4753 return true;
4754 }
4755
4756 /*
4757 * Ensure validity check succeeds before creating cache entry.
4758 */
4759
4760 rawname = pstrdup(searchPath); /* need a modifiable copy */
4761
4762 /* Parse string into list of identifiers */
4763 if (!SplitIdentifierString(rawname, ',', &namelist))
4764 {
4765 /* syntax error in name list */
4766 GUC_check_errdetail("List syntax is invalid.");
4767 pfree(rawname);
4768 list_free(namelist);
4769 return false;
4770 }
4771 pfree(rawname);
4772 list_free(namelist);
4773
4774 /* OK to create empty cache entry */
4775 if (use_cache)
4776 (void) spcache_insert(searchPath, roleid);
4777
4778 return true;
4779}
#define newval
#define GUC_check_errdetail
Definition: guc.h:505
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void pfree(void *pointer)
Definition: mcxt.c:1594
Oid GetUserId(void)
Definition: miscinit.c:469
static SearchPathCacheEntry * spcache_lookup(const char *searchPath, Oid roleid)
Definition: namespace.c:343
Definition: pg_list.h:54
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:2744

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

3530{
3531 /* disallow renaming into or out of temp schemas */
3532 if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
3533 ereport(ERROR,
3534 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3535 errmsg("cannot move objects into or out of temporary schemas")));
3536
3537 /* same for TOAST schema */
3538 if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
3539 ereport(ERROR,
3540 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3541 errmsg("cannot move objects into or out of TOAST schema")));
3542}
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3757

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

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

◆ checkTempNamespaceStatus()

TempNamespaceStatus checkTempNamespaceStatus ( Oid  namespaceId)

Definition at line 3799 of file namespace.c.

3800{
3801 PGPROC *proc;
3802 ProcNumber procNumber;
3803
3805
3806 procNumber = GetTempNamespaceProcNumber(namespaceId);
3807
3808 /* No such namespace, or its name shows it's not temp? */
3809 if (procNumber == INVALID_PROC_NUMBER)
3811
3812 /* Is the backend alive? */
3813 proc = ProcNumberGetProc(procNumber);
3814 if (proc == NULL)
3815 return TEMP_NAMESPACE_IDLE;
3816
3817 /* Is the backend connected to the same database we are looking at? */
3818 if (proc->databaseId != MyDatabaseId)
3819 return TEMP_NAMESPACE_IDLE;
3820
3821 /* Does the backend own the temporary namespace? */
3822 if (proc->tempNamespaceId != namespaceId)
3823 return TEMP_NAMESPACE_IDLE;
3824
3825 /* Yup, so namespace is busy */
3826 return TEMP_NAMESPACE_IN_USE;
3827}
Oid MyDatabaseId
Definition: globals.c:94
ProcNumber GetTempNamespaceProcNumber(Oid namespaceId)
Definition: namespace.c:3836
@ TEMP_NAMESPACE_IN_USE
Definition: namespace.h:67
@ TEMP_NAMESPACE_NOT_TEMP
Definition: namespace.h:65
@ TEMP_NAMESPACE_IDLE
Definition: namespace.h:66
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
Definition: procarray.c:3100
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
int ProcNumber
Definition: procnumber.h:24
Definition: proc.h:179
Oid databaseId
Definition: proc.h:224

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

2441{
2442 int32 dbencoding = GetDatabaseEncoding();
2443 ListCell *l;
2444
2446
2447 foreach(l, activeSearchPath)
2448 {
2449 Oid namespaceId = lfirst_oid(l);
2450 Oid collid;
2451
2452 if (namespaceId == myTempNamespace)
2453 continue; /* do not look in temp namespace */
2454
2455 collid = lookup_collation(collname, namespaceId, dbencoding);
2456 if (OidIsValid(collid))
2457 return collid;
2458 }
2459
2460 /* Not found in path */
2461 return InvalidOid;
2462}
int32_t int32
Definition: c.h:535
Oid collid
int GetDatabaseEncoding(void)
Definition: mbutils.c:1262
static Oid lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
Definition: namespace.c:2389
static List * activeSearchPath
Definition: namespace.c:135
static void recomputeNamespacePath(void)
Definition: namespace.c:4369
#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 2474 of file namespace.c.

2475{
2476 return CollationIsVisibleExt(collid, NULL);
2477}
static bool CollationIsVisibleExt(Oid collid, bool *is_missing)
Definition: namespace.c:2486

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

2487{
2488 HeapTuple colltup;
2489 Form_pg_collation collform;
2490 Oid collnamespace;
2491 bool visible;
2492
2493 colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
2494 if (!HeapTupleIsValid(colltup))
2495 {
2496 if (is_missing != NULL)
2497 {
2498 *is_missing = true;
2499 return false;
2500 }
2501 elog(ERROR, "cache lookup failed for collation %u", collid);
2502 }
2503 collform = (Form_pg_collation) GETSTRUCT(colltup);
2504
2506
2507 /*
2508 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2509 * the system namespace are surely in the path and so we needn't even do
2510 * list_member_oid() for them.
2511 */
2512 collnamespace = collform->collnamespace;
2513 if (collnamespace != PG_CATALOG_NAMESPACE &&
2514 !list_member_oid(activeSearchPath, collnamespace))
2515 visible = false;
2516 else
2517 {
2518 /*
2519 * If it is in the path, it might still not be visible; it could be
2520 * hidden by another collation of the same name earlier in the path,
2521 * or it might not work with the current DB encoding. So we must do a
2522 * slow check to see if this collation would be found by
2523 * CollationGetCollid.
2524 */
2525 char *collname = NameStr(collform->collname);
2526
2527 visible = (CollationGetCollid(collname) == collid);
2528 }
2529
2530 ReleaseSysCache(colltup);
2531
2532 return visible;
2533}
#define NameStr(name)
Definition: c.h:752
#define elog(elevel,...)
Definition: elog.h:226
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
Oid CollationGetCollid(const char *collname)
Definition: namespace.c:2440
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220

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

2545{
2546 Oid conid;
2547 ListCell *l;
2548
2550
2551 foreach(l, activeSearchPath)
2552 {
2553 Oid namespaceId = lfirst_oid(l);
2554
2555 if (namespaceId == myTempNamespace)
2556 continue; /* do not look in temp namespace */
2557
2558 conid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
2559 PointerGetDatum(conname),
2560 ObjectIdGetDatum(namespaceId));
2561 if (OidIsValid(conid))
2562 return conid;
2563 }
2564
2565 /* Not found in path */
2566 return InvalidOid;
2567}
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:111

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

Referenced by ConversionIsVisibleExt().

◆ ConversionIsVisible()

bool ConversionIsVisible ( Oid  conid)

Definition at line 2576 of file namespace.c.

2577{
2578 return ConversionIsVisibleExt(conid, NULL);
2579}
static bool ConversionIsVisibleExt(Oid conid, bool *is_missing)
Definition: namespace.c:2588

References ConversionIsVisibleExt().

Referenced by getObjectDescription().

◆ ConversionIsVisibleExt()

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

Definition at line 2588 of file namespace.c.

2589{
2590 HeapTuple contup;
2591 Form_pg_conversion conform;
2592 Oid connamespace;
2593 bool visible;
2594
2595 contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
2596 if (!HeapTupleIsValid(contup))
2597 {
2598 if (is_missing != NULL)
2599 {
2600 *is_missing = true;
2601 return false;
2602 }
2603 elog(ERROR, "cache lookup failed for conversion %u", conid);
2604 }
2605 conform = (Form_pg_conversion) GETSTRUCT(contup);
2606
2608
2609 /*
2610 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2611 * the system namespace are surely in the path and so we needn't even do
2612 * list_member_oid() for them.
2613 */
2614 connamespace = conform->connamespace;
2615 if (connamespace != PG_CATALOG_NAMESPACE &&
2616 !list_member_oid(activeSearchPath, connamespace))
2617 visible = false;
2618 else
2619 {
2620 /*
2621 * If it is in the path, it might still not be visible; it could be
2622 * hidden by another conversion of the same name earlier in the path.
2623 * So we must do a slow check to see if this conversion would be found
2624 * by ConversionGetConid.
2625 */
2626 char *conname = NameStr(conform->conname);
2627
2628 visible = (ConversionGetConid(conname) == conid);
2629 }
2630
2631 ReleaseSysCache(contup);
2632
2633 return visible;
2634}
Oid ConversionGetConid(const char *conname)
Definition: namespace.c:2544
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 3959 of file namespace.c.

3960{
3961 SearchPathMatcher *result;
3962
3963 result = (SearchPathMatcher *) palloc(sizeof(SearchPathMatcher));
3964 result->schemas = list_copy(path->schemas);
3965 result->addCatalog = path->addCatalog;
3966 result->addTemp = path->addTemp;
3967 result->generation = path->generation;
3968
3969 return result;
3970}
List * list_copy(const List *oldlist)
Definition: list.c:1573
void * palloc(Size size)
Definition: mcxt.c:1365
uint64 generation
Definition: namespace.h:82

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

3374{
3375 char *catalogname;
3376 char *schemaname = NULL;
3377 char *objname = NULL;
3378
3379 switch (list_length(names))
3380 {
3381 case 1:
3382 objname = strVal(linitial(names));
3383 break;
3384 case 2:
3385 schemaname = strVal(linitial(names));
3386 objname = strVal(lsecond(names));
3387 break;
3388 case 3:
3389 catalogname = strVal(linitial(names));
3390 schemaname = strVal(lsecond(names));
3391 objname = strVal(lthird(names));
3392
3393 /*
3394 * We check the catalog name and then ignore it.
3395 */
3396 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
3397 ereport(ERROR,
3398 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3399 errmsg("cross-database references are not implemented: %s",
3400 NameListToString(names))));
3401 break;
3402 default:
3403 ereport(ERROR,
3404 (errcode(ERRCODE_SYNTAX_ERROR),
3405 errmsg("improper qualified name (too many dotted names): %s",
3406 NameListToString(names))));
3407 break;
3408 }
3409
3410 *nspname_p = schemaname;
3411 *objname_p = objname;
3412}
char * get_database_name(Oid dbid)
Definition: lsyscache.c:1259
char * NameListToString(const List *names)
Definition: namespace.c:3664
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 4889 of file namespace.c.

4890{
4891 List *result;
4892
4894
4895 /*
4896 * If the temp namespace should be first, force it to exist. This is so
4897 * that callers can trust the result to reflect the actual default
4898 * creation namespace. It's a bit bogus to do this here, since
4899 * current_schema() is supposedly a stable function without side-effects,
4900 * but the alternatives seem worse.
4901 */
4903 {
4906 }
4907
4908 result = list_copy(activeSearchPath);
4909 if (!includeImplicit)
4910 {
4911 while (result && linitial_oid(result) != activeCreationNamespace)
4912 result = list_delete_first(result);
4913 }
4914
4915 return result;
4916}
List * list_delete_first(List *list)
Definition: list.c:943
static Oid activeCreationNamespace
Definition: namespace.c:138
static bool activeTempCreationPending
Definition: namespace.c:141
static void AccessTempTableNamespace(bool force)
Definition: namespace.c:4432
#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 4929 of file namespace.c.

4930{
4931 int count = 0;
4932 ListCell *l;
4933
4935
4936 foreach(l, activeSearchPath)
4937 {
4938 Oid namespaceId = lfirst_oid(l);
4939
4940 if (namespaceId == myTempNamespace)
4941 continue; /* do not include temp namespace */
4942
4943 if (count < sarray_len)
4944 sarray[count] = namespaceId;
4945 count++;
4946 }
4947
4948 return count;
4949}

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

4269{
4270 List *finalPath = NIL;
4271 ListCell *lc;
4272
4273 foreach(lc, oidlist)
4274 {
4275 Oid namespaceId = lfirst_oid(lc);
4276
4277 if (!list_member_oid(finalPath, namespaceId))
4278 {
4279 if (InvokeNamespaceSearchHook(namespaceId, false))
4280 finalPath = lappend_oid(finalPath, namespaceId);
4281 }
4282 }
4283
4284 /*
4285 * Remember the first member of the explicit list. (Note: this is
4286 * nominally wrong if temp_missing, but we need it anyway to distinguish
4287 * explicit from implicit mention of pg_catalog.)
4288 */
4289 if (finalPath == NIL)
4290 *firstNS = InvalidOid;
4291 else
4292 *firstNS = linitial_oid(finalPath);
4293
4294 /*
4295 * Add any implicitly-searched namespaces to the list. Note these go on
4296 * the front, not the back; also notice that we do not check USAGE
4297 * permissions for these.
4298 */
4299 if (!list_member_oid(finalPath, PG_CATALOG_NAMESPACE))
4300 finalPath = lcons_oid(PG_CATALOG_NAMESPACE, finalPath);
4301
4303 !list_member_oid(finalPath, myTempNamespace))
4304 finalPath = lcons_oid(myTempNamespace, finalPath);
4305
4306 return finalPath;
4307}
List * lcons_oid(Oid datum, List *list)
Definition: list.c:531
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
#define InvokeNamespaceSearchHook(objectId, ereport_on_violation)
Definition: objectaccess.h:208

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

Referenced by cachedNamespacePath().

◆ FindDefaultConversionProc()

Oid FindDefaultConversionProc ( int32  for_encoding,
int32  to_encoding 
)

Definition at line 4150 of file namespace.c.

4151{
4152 Oid proc;
4153 ListCell *l;
4154
4156
4157 foreach(l, activeSearchPath)
4158 {
4159 Oid namespaceId = lfirst_oid(l);
4160
4161 if (namespaceId == myTempNamespace)
4162 continue; /* do not look in temp namespace */
4163
4164 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
4165 if (OidIsValid(proc))
4166 return proc;
4167 }
4168
4169 /* Not found in path */
4170 return InvalidOid;
4171}
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,
int *  fgc_flags 
)

Definition at line 1197 of file namespace.c.

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

References activeSearchPath, _FuncCandidateList::argnumbers, generate_unaccent_rules::args, _FuncCandidateList::args, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, Assert(), CStringGetDatum(), DatumGetArrayTypeP, DeconstructQualifiedName(), elog, ERROR, FGC_ARGCOUNT_MATCH, FGC_ARGNAMES_VALID, FGC_NAME_EXISTS, FGC_NAME_VISIBLE, FGC_SCHEMA_EXISTS, FGC_SCHEMA_GIVEN, 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 1741 of file namespace.c.

1742{
1743 return FunctionIsVisibleExt(funcid, NULL);
1744}
static bool FunctionIsVisibleExt(Oid funcid, bool *is_missing)
Definition: namespace.c:1753

References FunctionIsVisibleExt().

Referenced by format_procedure_extended().

◆ FunctionIsVisibleExt()

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

Definition at line 1753 of file namespace.c.

1754{
1755 HeapTuple proctup;
1756 Form_pg_proc procform;
1757 Oid pronamespace;
1758 bool visible;
1759
1760 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1761 if (!HeapTupleIsValid(proctup))
1762 {
1763 if (is_missing != NULL)
1764 {
1765 *is_missing = true;
1766 return false;
1767 }
1768 elog(ERROR, "cache lookup failed for function %u", funcid);
1769 }
1770 procform = (Form_pg_proc) GETSTRUCT(proctup);
1771
1773
1774 /*
1775 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1776 * the system namespace are surely in the path and so we needn't even do
1777 * list_member_oid() for them.
1778 */
1779 pronamespace = procform->pronamespace;
1780 if (pronamespace != PG_CATALOG_NAMESPACE &&
1781 !list_member_oid(activeSearchPath, pronamespace))
1782 visible = false;
1783 else
1784 {
1785 /*
1786 * If it is in the path, it might still not be visible; it could be
1787 * hidden by another proc of the same name and arguments earlier in
1788 * the path. So we must do a slow check to see if this is the same
1789 * proc that would be found by FuncnameGetCandidates.
1790 */
1791 char *proname = NameStr(procform->proname);
1792 int nargs = procform->pronargs;
1793 FuncCandidateList clist;
1794 int fgc_flags;
1795
1796 visible = false;
1797
1799 nargs, NIL, false, false, false, false,
1800 &fgc_flags);
1801
1802 for (; clist; clist = clist->next)
1803 {
1804 if (memcmp(clist->args, procform->proargtypes.values,
1805 nargs * sizeof(Oid)) == 0)
1806 {
1807 /* Found the expected entry; is it the right proc? */
1808 visible = (clist->oid == funcid);
1809 break;
1810 }
1811 }
1812 }
1813
1814 ReleaseSysCache(proctup);
1815
1816 return visible;
1817}
FuncCandidateList FuncnameGetCandidates(List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool include_out_arguments, bool missing_ok, int *fgc_flags)
Definition: namespace.c:1197
#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 4041 of file namespace.c.

4042{
4043 char *schemaname;
4044 char *collation_name;
4045 int32 dbencoding = GetDatabaseEncoding();
4046 Oid namespaceId;
4047 Oid colloid;
4048 ListCell *l;
4049
4050 /* deconstruct the name list */
4051 DeconstructQualifiedName(collname, &schemaname, &collation_name);
4052
4053 if (schemaname)
4054 {
4055 /* use exact schema given */
4056 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
4057 if (missing_ok && !OidIsValid(namespaceId))
4058 return InvalidOid;
4059
4060 colloid = lookup_collation(collation_name, namespaceId, dbencoding);
4061 if (OidIsValid(colloid))
4062 return colloid;
4063 }
4064 else
4065 {
4066 /* search for it in search path */
4068
4069 foreach(l, activeSearchPath)
4070 {
4071 namespaceId = lfirst_oid(l);
4072
4073 if (namespaceId == myTempNamespace)
4074 continue; /* do not look in temp namespace */
4075
4076 colloid = lookup_collation(collation_name, namespaceId, dbencoding);
4077 if (OidIsValid(colloid))
4078 return colloid;
4079 }
4080 }
4081
4082 /* Not found in path */
4083 if (!missing_ok)
4084 ereport(ERROR,
4085 (errcode(ERRCODE_UNDEFINED_OBJECT),
4086 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
4088 return InvalidOid;
4089}
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1268

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

4096{
4097 char *schemaname;
4098 char *conversion_name;
4099 Oid namespaceId;
4100 Oid conoid = InvalidOid;
4101 ListCell *l;
4102
4103 /* deconstruct the name list */
4104 DeconstructQualifiedName(conname, &schemaname, &conversion_name);
4105
4106 if (schemaname)
4107 {
4108 /* use exact schema given */
4109 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
4110 if (missing_ok && !OidIsValid(namespaceId))
4111 conoid = InvalidOid;
4112 else
4113 conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
4114 PointerGetDatum(conversion_name),
4115 ObjectIdGetDatum(namespaceId));
4116 }
4117 else
4118 {
4119 /* search for it in search path */
4121
4122 foreach(l, activeSearchPath)
4123 {
4124 namespaceId = lfirst_oid(l);
4125
4126 if (namespaceId == myTempNamespace)
4127 continue; /* do not look in temp namespace */
4128
4129 conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
4130 PointerGetDatum(conversion_name),
4131 ObjectIdGetDatum(namespaceId));
4132 if (OidIsValid(conoid))
4133 return conoid;
4134 }
4135 }
4136
4137 /* Not found in path */
4138 if (!OidIsValid(conoid) && !missing_ok)
4139 ereport(ERROR,
4140 (errcode(ERRCODE_UNDEFINED_OBJECT),
4141 errmsg("conversion \"%s\" does not exist",
4142 NameListToString(conname))));
4143 return conoid;
4144}

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

2643{
2644 char *schemaname;
2645 char *stats_name;
2646 Oid namespaceId;
2647 Oid stats_oid = InvalidOid;
2648 ListCell *l;
2649
2650 /* deconstruct the name list */
2651 DeconstructQualifiedName(names, &schemaname, &stats_name);
2652
2653 if (schemaname)
2654 {
2655 /* use exact schema given */
2656 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2657 if (missing_ok && !OidIsValid(namespaceId))
2658 stats_oid = InvalidOid;
2659 else
2660 stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2661 PointerGetDatum(stats_name),
2662 ObjectIdGetDatum(namespaceId));
2663 }
2664 else
2665 {
2666 /* search for it in search path */
2668
2669 foreach(l, activeSearchPath)
2670 {
2671 namespaceId = lfirst_oid(l);
2672
2673 if (namespaceId == myTempNamespace)
2674 continue; /* do not look in temp namespace */
2675 stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2676 PointerGetDatum(stats_name),
2677 ObjectIdGetDatum(namespaceId));
2678 if (OidIsValid(stats_oid))
2679 break;
2680 }
2681 }
2682
2683 if (!OidIsValid(stats_oid) && !missing_ok)
2684 ereport(ERROR,
2685 (errcode(ERRCODE_UNDEFINED_OBJECT),
2686 errmsg("statistics object \"%s\" does not exist",
2687 NameListToString(names))));
2688
2689 return stats_oid;
2690}

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

3223{
3224 char *schemaname;
3225 char *config_name;
3226 Oid namespaceId;
3227 Oid cfgoid = InvalidOid;
3228 ListCell *l;
3229
3230 /* deconstruct the name list */
3231 DeconstructQualifiedName(names, &schemaname, &config_name);
3232
3233 if (schemaname)
3234 {
3235 /* use exact schema given */
3236 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3237 if (missing_ok && !OidIsValid(namespaceId))
3238 cfgoid = InvalidOid;
3239 else
3240 cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
3241 PointerGetDatum(config_name),
3242 ObjectIdGetDatum(namespaceId));
3243 }
3244 else
3245 {
3246 /* search for it in search path */
3248
3249 foreach(l, activeSearchPath)
3250 {
3251 namespaceId = lfirst_oid(l);
3252
3253 if (namespaceId == myTempNamespace)
3254 continue; /* do not look in temp namespace */
3255
3256 cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
3257 PointerGetDatum(config_name),
3258 ObjectIdGetDatum(namespaceId));
3259 if (OidIsValid(cfgoid))
3260 break;
3261 }
3262 }
3263
3264 if (!OidIsValid(cfgoid) && !missing_ok)
3265 ereport(ERROR,
3266 (errcode(ERRCODE_UNDEFINED_OBJECT),
3267 errmsg("text search configuration \"%s\" does not exist",
3268 NameListToString(names))));
3269
3270 return cfgoid;
3271}

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

2932{
2933 char *schemaname;
2934 char *dict_name;
2935 Oid namespaceId;
2936 Oid dictoid = InvalidOid;
2937 ListCell *l;
2938
2939 /* deconstruct the name list */
2940 DeconstructQualifiedName(names, &schemaname, &dict_name);
2941
2942 if (schemaname)
2943 {
2944 /* use exact schema given */
2945 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2946 if (missing_ok && !OidIsValid(namespaceId))
2947 dictoid = InvalidOid;
2948 else
2949 dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2950 PointerGetDatum(dict_name),
2951 ObjectIdGetDatum(namespaceId));
2952 }
2953 else
2954 {
2955 /* search for it in search path */
2957
2958 foreach(l, activeSearchPath)
2959 {
2960 namespaceId = lfirst_oid(l);
2961
2962 if (namespaceId == myTempNamespace)
2963 continue; /* do not look in temp namespace */
2964
2965 dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2966 PointerGetDatum(dict_name),
2967 ObjectIdGetDatum(namespaceId));
2968 if (OidIsValid(dictoid))
2969 break;
2970 }
2971 }
2972
2973 if (!OidIsValid(dictoid) && !missing_ok)
2974 ereport(ERROR,
2975 (errcode(ERRCODE_UNDEFINED_OBJECT),
2976 errmsg("text search dictionary \"%s\" does not exist",
2977 NameListToString(names))));
2978
2979 return dictoid;
2980}

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

2787{
2788 char *schemaname;
2789 char *parser_name;
2790 Oid namespaceId;
2791 Oid prsoid = InvalidOid;
2792 ListCell *l;
2793
2794 /* deconstruct the name list */
2795 DeconstructQualifiedName(names, &schemaname, &parser_name);
2796
2797 if (schemaname)
2798 {
2799 /* use exact schema given */
2800 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2801 if (missing_ok && !OidIsValid(namespaceId))
2802 prsoid = InvalidOid;
2803 else
2804 prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2805 PointerGetDatum(parser_name),
2806 ObjectIdGetDatum(namespaceId));
2807 }
2808 else
2809 {
2810 /* search for it in search path */
2812
2813 foreach(l, activeSearchPath)
2814 {
2815 namespaceId = lfirst_oid(l);
2816
2817 if (namespaceId == myTempNamespace)
2818 continue; /* do not look in temp namespace */
2819
2820 prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2821 PointerGetDatum(parser_name),
2822 ObjectIdGetDatum(namespaceId));
2823 if (OidIsValid(prsoid))
2824 break;
2825 }
2826 }
2827
2828 if (!OidIsValid(prsoid) && !missing_ok)
2829 ereport(ERROR,
2830 (errcode(ERRCODE_UNDEFINED_OBJECT),
2831 errmsg("text search parser \"%s\" does not exist",
2832 NameListToString(names))));
2833
2834 return prsoid;
2835}

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

3078{
3079 char *schemaname;
3080 char *template_name;
3081 Oid namespaceId;
3082 Oid tmploid = InvalidOid;
3083 ListCell *l;
3084
3085 /* deconstruct the name list */
3086 DeconstructQualifiedName(names, &schemaname, &template_name);
3087
3088 if (schemaname)
3089 {
3090 /* use exact schema given */
3091 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3092 if (missing_ok && !OidIsValid(namespaceId))
3093 tmploid = InvalidOid;
3094 else
3095 tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
3096 PointerGetDatum(template_name),
3097 ObjectIdGetDatum(namespaceId));
3098 }
3099 else
3100 {
3101 /* search for it in search path */
3103
3104 foreach(l, activeSearchPath)
3105 {
3106 namespaceId = lfirst_oid(l);
3107
3108 if (namespaceId == myTempNamespace)
3109 continue; /* do not look in temp namespace */
3110
3111 tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
3112 PointerGetDatum(template_name),
3113 ObjectIdGetDatum(namespaceId));
3114 if (OidIsValid(tmploid))
3115 break;
3116 }
3117 }
3118
3119 if (!OidIsValid(tmploid) && !missing_ok)
3120 ereport(ERROR,
3121 (errcode(ERRCODE_UNDEFINED_OBJECT),
3122 errmsg("text search template \"%s\" does not exist",
3123 NameListToString(names))));
3124
3125 return tmploid;
3126}

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

3923{
3924 SearchPathMatcher *result;
3925 List *schemas;
3926 MemoryContext oldcxt;
3927
3929
3930 oldcxt = MemoryContextSwitchTo(context);
3931
3932 result = (SearchPathMatcher *) palloc0(sizeof(SearchPathMatcher));
3933 schemas = list_copy(activeSearchPath);
3934 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
3935 {
3936 if (linitial_oid(schemas) == myTempNamespace)
3937 result->addTemp = true;
3938 else
3939 {
3940 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
3941 result->addCatalog = true;
3942 }
3943 schemas = list_delete_first(schemas);
3944 }
3945 result->schemas = schemas;
3947
3948 MemoryContextSwitchTo(oldcxt);
3949
3950 return result;
3951}
void * palloc0(Size size)
Definition: mcxt.c:1395
static uint64 activePathGeneration
Definition: namespace.c:144

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

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

◆ GetTempNamespaceProcNumber()

ProcNumber GetTempNamespaceProcNumber ( Oid  namespaceId)

Definition at line 3836 of file namespace.c.

3837{
3838 int result;
3839 char *nspname;
3840
3841 /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3842 nspname = get_namespace_name(namespaceId);
3843 if (!nspname)
3844 return INVALID_PROC_NUMBER; /* no such namespace? */
3845 if (strncmp(nspname, "pg_temp_", 8) == 0)
3846 result = atoi(nspname + 8);
3847 else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
3848 result = atoi(nspname + 14);
3849 else
3850 result = INVALID_PROC_NUMBER;
3851 pfree(nspname);
3852 return result;
3853}
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3533

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

3876{
3877 /* Return namespace OIDs, or 0 if session has not created temp namespace */
3878 *tempNamespaceId = myTempNamespace;
3879 *tempToastNamespaceId = myTempToastNamespace;
3880}

References myTempNamespace, and myTempToastNamespace.

Referenced by InitializeParallelDSM().

◆ GetTempToastNamespace()

Oid GetTempToastNamespace ( void  )

Definition at line 3861 of file namespace.c.

3862{
3864 return myTempToastNamespace;
3865}

References Assert(), myTempToastNamespace, and OidIsValid.

Referenced by create_toast_table().

◆ InitializeSearchPath()

void InitializeSearchPath ( void  )

Definition at line 4806 of file namespace.c.

4807{
4809 {
4810 /*
4811 * In bootstrap mode, the search path must be 'pg_catalog' so that
4812 * tables are created in the proper namespace; ignore the GUC setting.
4813 */
4814 MemoryContext oldcxt;
4815
4817 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
4818 MemoryContextSwitchTo(oldcxt);
4819 baseCreationNamespace = PG_CATALOG_NAMESPACE;
4821 baseSearchPathValid = true;
4826 activePathGeneration++; /* pro forma */
4827 }
4828 else
4829 {
4830 /*
4831 * In normal mode, arrange for a callback on any syscache invalidation
4832 * that will affect the search_path cache.
4833 */
4834
4835 /* namespace name or ACLs may have changed */
4836 CacheRegisterSyscacheCallback(NAMESPACEOID,
4838 (Datum) 0);
4839
4840 /* role name may affect the meaning of "$user" */
4843 (Datum) 0);
4844
4845 /* role membership may affect ACLs */
4846 CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
4848 (Datum) 0);
4849
4850 /* database owner may affect ACLs */
4853 (Datum) 0);
4854
4855 /* Force search path to be recomputed on next use */
4856 baseSearchPathValid = false;
4857 searchPathCacheValid = false;
4858 }
4859}
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1812
MemoryContext TopMemoryContext
Definition: mcxt.c:166
static bool baseTempCreationPending
Definition: namespace.c:152
static Oid baseCreationNamespace
Definition: namespace.c:150
static Oid namespaceUser
Definition: namespace.c:154
static void InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: namespace.c:4866
static List * baseSearchPath
Definition: namespace.c:148
#define list_make1_oid(x1)
Definition: pg_list.h:242

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

Referenced by InitPostgres().

◆ InitTempTableNamespace()

static void InitTempTableNamespace ( void  )
static

Definition at line 4460 of file namespace.c.

4461{
4462 char namespaceName[NAMEDATALEN];
4463 Oid namespaceId;
4464 Oid toastspaceId;
4465
4467
4468 /*
4469 * First, do permission check to see if we are authorized to make temp
4470 * tables. We use a nonstandard error message here since "databasename:
4471 * permission denied" might be a tad cryptic.
4472 *
4473 * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
4474 * that's necessary since current user ID could change during the session.
4475 * But there's no need to make the namespace in the first place until a
4476 * temp table creation request is made by someone with appropriate rights.
4477 */
4478 if (object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
4480 ereport(ERROR,
4481 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4482 errmsg("permission denied to create temporary tables in database \"%s\"",
4484
4485 /*
4486 * Do not allow a Hot Standby session to make temp tables. Aside from
4487 * problems with modifying the system catalogs, there is a naming
4488 * conflict: pg_temp_N belongs to the session with proc number N on the
4489 * primary, not to a hot standby session with the same proc number. We
4490 * should not be able to get here anyway due to XactReadOnly checks, but
4491 * let's just make real sure. Note that this also backstops various
4492 * operations that allow XactReadOnly transactions to modify temp tables;
4493 * they'd need RecoveryInProgress checks if not for this.
4494 */
4495 if (RecoveryInProgress())
4496 ereport(ERROR,
4497 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
4498 errmsg("cannot create temporary tables during recovery")));
4499
4500 /* Parallel workers can't create temporary tables, either. */
4501 if (IsParallelWorker())
4502 ereport(ERROR,
4503 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
4504 errmsg("cannot create temporary tables during a parallel operation")));
4505
4506 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyProcNumber);
4507
4508 namespaceId = get_namespace_oid(namespaceName, true);
4509 if (!OidIsValid(namespaceId))
4510 {
4511 /*
4512 * First use of this temp namespace in this database; create it. The
4513 * temp namespaces are always owned by the superuser. We leave their
4514 * permissions at default --- i.e., no access except to superuser ---
4515 * to ensure that unprivileged users can't peek at other backends'
4516 * temp tables. This works because the places that access the temp
4517 * namespace for my own backend skip permissions checks on it.
4518 */
4519 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4520 true);
4521 /* Advance command counter to make namespace visible */
4523 }
4524 else
4525 {
4526 /*
4527 * If the namespace already exists, clean it out (in case the former
4528 * owner crashed without doing so).
4529 */
4530 RemoveTempRelations(namespaceId);
4531 }
4532
4533 /*
4534 * If the corresponding toast-table namespace doesn't exist yet, create
4535 * it. (We assume there is no need to clean it out if it does exist, since
4536 * dropping a parent table should make its toast table go away.)
4537 */
4538 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
4539 MyProcNumber);
4540
4541 toastspaceId = get_namespace_oid(namespaceName, true);
4542 if (!OidIsValid(toastspaceId))
4543 {
4544 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4545 true);
4546 /* Advance command counter to make namespace visible */
4548 }
4549
4550 /*
4551 * Okay, we've prepared the temp namespace ... but it's not committed yet,
4552 * so all our work could be undone by transaction rollback. Set flag for
4553 * AtEOXact_Namespace to know what to do.
4554 */
4555 myTempNamespace = namespaceId;
4556 myTempToastNamespace = toastspaceId;
4557
4558 /*
4559 * Mark MyProc as owning this namespace which other processes can use to
4560 * decide if a temporary namespace is in use or not. We assume that
4561 * assignment of namespaceId is an atomic operation. Even if it is not,
4562 * the temporary relation which resulted in the creation of this temporary
4563 * namespace is still locked until the current transaction commits, and
4564 * its pg_namespace row is not visible yet. However it does not matter:
4565 * this flag makes the namespace as being in use, so no objects created on
4566 * it would be removed concurrently.
4567 */
4568 MyProc->tempNamespaceId = namespaceId;
4569
4570 /* It should not be done already. */
4573
4574 baseSearchPathValid = false; /* need to rebuild list */
4575 searchPathCacheValid = false;
4576}
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3834
ProcNumber MyProcNumber
Definition: globals.c:90
#define IsParallelWorker()
Definition: parallel.h:60
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3605
static void RemoveTempRelations(Oid tempNamespaceId)
Definition: namespace.c:4668
#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:239
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:791
void CommandCounterIncrement(void)
Definition: xact.c:1100
bool RecoveryInProgress(void)
Definition: xlog.c:6383

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

4867{
4868 /*
4869 * Force search path to be recomputed on next use, also invalidating the
4870 * search path cache (because namespace names, ACLs, or role names may
4871 * have changed).
4872 */
4873 baseSearchPathValid = false;
4874 searchPathCacheValid = false;
4875}

References baseSearchPathValid, and searchPathCacheValid.

Referenced by InitializeSearchPath().

◆ isAnyTempNamespace()

bool isAnyTempNamespace ( Oid  namespaceId)

Definition at line 3757 of file namespace.c.

3758{
3759 bool result;
3760 char *nspname;
3761
3762 /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3763 nspname = get_namespace_name(namespaceId);
3764 if (!nspname)
3765 return false; /* no such namespace? */
3766 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
3767 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
3768 pfree(nspname);
3769 return result;
3770}

References get_namespace_name(), and pfree().

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

◆ isOtherTempNamespace()

bool isOtherTempNamespace ( Oid  namespaceId)

Definition at line 3780 of file namespace.c.

3781{
3782 /* If it's my own temp namespace, say "false" */
3783 if (isTempOrTempToastNamespace(namespaceId))
3784 return false;
3785 /* Else, if it's any temp namespace, say "true" */
3786 return isAnyTempNamespace(namespaceId);
3787}
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3743

References isAnyTempNamespace(), and isTempOrTempToastNamespace().

Referenced by pg_is_other_temp_schema().

◆ isTempNamespace()

bool isTempNamespace ( Oid  namespaceId)

◆ isTempOrTempToastNamespace()

bool isTempOrTempToastNamespace ( Oid  namespaceId)

Definition at line 3743 of file namespace.c.

3744{
3746 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
3747 return true;
3748 return false;
3749}

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

3732{
3734 return true;
3735 return false;
3736}

References myTempToastNamespace, and OidIsValid.

Referenced by IsToastNamespace().

◆ lookup_collation()

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

Definition at line 2389 of file namespace.c.

2390{
2391 Oid collid;
2392 HeapTuple colltup;
2393 Form_pg_collation collform;
2394
2395 /* Check for encoding-specific entry (exact match) */
2396 collid = GetSysCacheOid3(COLLNAMEENCNSP, Anum_pg_collation_oid,
2397 PointerGetDatum(collname),
2399 ObjectIdGetDatum(collnamespace));
2400 if (OidIsValid(collid))
2401 return collid;
2402
2403 /*
2404 * Check for any-encoding entry. This takes a bit more work: while libc
2405 * collations with collencoding = -1 do work with all encodings, ICU
2406 * collations only work with certain encodings, so we have to check that
2407 * aspect before deciding it's a match.
2408 */
2409 colltup = SearchSysCache3(COLLNAMEENCNSP,
2410 PointerGetDatum(collname),
2411 Int32GetDatum(-1),
2412 ObjectIdGetDatum(collnamespace));
2413 if (!HeapTupleIsValid(colltup))
2414 return InvalidOid;
2415 collform = (Form_pg_collation) GETSTRUCT(colltup);
2416 if (collform->collprovider == COLLPROVIDER_ICU)
2417 {
2419 collid = collform->oid;
2420 else
2422 }
2423 else
2424 {
2425 collid = collform->oid;
2426 }
2427 ReleaseSysCache(colltup);
2428 return collid;
2429}
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:222
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:240
#define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3)
Definition: syscache.h:113

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

Referenced by CollationGetCollid(), and get_collation_oid().

◆ LookupCreationNamespace()

Oid LookupCreationNamespace ( const char *  nspname)

Definition at line 3498 of file namespace.c.

3499{
3500 Oid namespaceId;
3501 AclResult aclresult;
3502
3503 /* check for pg_temp alias */
3504 if (strcmp(nspname, "pg_temp") == 0)
3505 {
3506 /* Initialize temp namespace */
3508 return myTempNamespace;
3509 }
3510
3511 namespaceId = get_namespace_oid(nspname, false);
3512
3513 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
3514 if (aclresult != ACLCHECK_OK)
3515 aclcheck_error(aclresult, OBJECT_SCHEMA,
3516 nspname);
3517
3518 return namespaceId;
3519}
AclResult
Definition: acl.h:182
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2652
@ OBJECT_SCHEMA
Definition: parsenodes.h:2360
#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 3455 of file namespace.c.

3456{
3457 Oid namespaceId;
3458 AclResult aclresult;
3459
3460 /* check for pg_temp alias */
3461 if (strcmp(nspname, "pg_temp") == 0)
3462 {
3464 return myTempNamespace;
3465
3466 /*
3467 * Since this is used only for looking up existing objects, there is
3468 * no point in trying to initialize the temp namespace here; and doing
3469 * so might create problems for some callers --- just fall through.
3470 */
3471 }
3472
3473 namespaceId = get_namespace_oid(nspname, missing_ok);
3474 if (missing_ok && !OidIsValid(namespaceId))
3475 return InvalidOid;
3476
3477 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_USAGE);
3478 if (aclresult != ACLCHECK_OK)
3479 aclcheck_error(aclresult, OBJECT_SCHEMA,
3480 nspname);
3481 /* Schema search hook for this lookup */
3482 InvokeNamespaceSearchHook(namespaceId, true);
3483
3484 return namespaceId;
3485}
#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(), schema_to_xmlschema_internal(), and stats_lookup_relid().

◆ LookupNamespaceNoError()

Oid LookupNamespaceNoError ( const char *  nspname)

Definition at line 3425 of file namespace.c.

3426{
3427 /* check for pg_temp alias */
3428 if (strcmp(nspname, "pg_temp") == 0)
3429 {
3431 {
3433 return myTempNamespace;
3434 }
3435
3436 /*
3437 * Since this is used only for looking up existing objects, there is
3438 * no point in trying to initialize the temp namespace here; and doing
3439 * so might create problems for some callers. Just report "not found".
3440 */
3441 return InvalidOid;
3442 }
3443
3444 return get_namespace_oid(nspname, true);
3445}

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

3625{
3626 RangeVar *rel = makeRangeVar(NULL, NULL, -1);
3627
3628 switch (list_length(names))
3629 {
3630 case 1:
3631 rel->relname = strVal(linitial(names));
3632 break;
3633 case 2:
3634 rel->schemaname = strVal(linitial(names));
3635 rel->relname = strVal(lsecond(names));
3636 break;
3637 case 3:
3638 rel->catalogname = strVal(linitial(names));
3639 rel->schemaname = strVal(lsecond(names));
3640 rel->relname = strVal(lthird(names));
3641 break;
3642 default:
3643 ereport(ERROR,
3644 (errcode(ERRCODE_SYNTAX_ERROR),
3645 errmsg("improper relation name (too many dotted names): %s",
3646 NameListToString(names))));
3647 break;
3648 }
3649
3650 return rel;
3651}
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:473
char * relname
Definition: primnodes.h:83
char * catalogname
Definition: primnodes.h:77
char * schemaname
Definition: primnodes.h:80

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,
int *  fgc_flags 
)
static

Definition at line 1616 of file namespace.c.

1619{
1620 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
1621 int numposargs = nargs - list_length(argnames);
1622 int pronallargs;
1623 Oid *p_argtypes;
1624 char **p_argnames;
1625 char *p_argmodes;
1626 bool arggiven[FUNC_MAX_ARGS];
1627 bool arg_filled_twice = false;
1628 bool isnull;
1629 int ap; /* call args position */
1630 int pp; /* proargs position */
1631 ListCell *lc;
1632
1633 Assert(argnames != NIL);
1634 Assert(numposargs >= 0);
1635 Assert(nargs <= pronargs);
1636
1637 /* Ignore this function if its proargnames is null */
1638 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
1639 &isnull);
1640 if (isnull)
1641 return false;
1642
1643 /* OK, let's extract the argument names and types */
1644 pronallargs = get_func_arg_info(proctup,
1645 &p_argtypes, &p_argnames, &p_argmodes);
1646 Assert(p_argnames != NULL);
1647
1648 Assert(include_out_arguments ? (pronargs == pronallargs) : (pronargs <= pronallargs));
1649
1650 /* initialize state for matching */
1651 *argnumbers = (int *) palloc(pronargs * sizeof(int));
1652 memset(arggiven, false, pronargs * sizeof(bool));
1653
1654 /* there are numposargs positional args before the named args */
1655 for (ap = 0; ap < numposargs; ap++)
1656 {
1657 (*argnumbers)[ap] = ap;
1658 arggiven[ap] = true;
1659 }
1660
1661 /* now examine the named args */
1662 foreach(lc, argnames)
1663 {
1664 char *argname = (char *) lfirst(lc);
1665 bool found;
1666 int i;
1667
1668 pp = 0;
1669 found = false;
1670 for (i = 0; i < pronallargs; i++)
1671 {
1672 /* consider only input params, except with include_out_arguments */
1673 if (!include_out_arguments &&
1674 p_argmodes &&
1675 (p_argmodes[i] != FUNC_PARAM_IN &&
1676 p_argmodes[i] != FUNC_PARAM_INOUT &&
1677 p_argmodes[i] != FUNC_PARAM_VARIADIC))
1678 continue;
1679 if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
1680 {
1681 /* note if argname matches a positional argument */
1682 if (arggiven[pp])
1683 arg_filled_twice = true;
1684 arggiven[pp] = true;
1685 (*argnumbers)[ap] = pp;
1686 found = true;
1687 break;
1688 }
1689 /* increase pp only for considered parameters */
1690 pp++;
1691 }
1692 /* if name isn't in proargnames, fail */
1693 if (!found)
1694 return false;
1695 ap++;
1696 }
1697
1698 Assert(ap == nargs); /* processed all actual parameters */
1699
1700 /* If we get here, the function did match all the supplied argnames */
1701 *fgc_flags |= FGC_ARGNAMES_MATCH;
1702
1703 /* ... however, some of them might have been placed wrong */
1704 if (arg_filled_twice)
1705 return false; /* some argname matched a positional argument */
1706
1707 /* If we get here, the call doesn't have invalid mixed notation */
1708 *fgc_flags |= FGC_ARGNAMES_NONDUP;
1709
1710 /* Check for default arguments */
1711 if (nargs < pronargs)
1712 {
1713 int first_arg_with_default = pronargs - procform->pronargdefaults;
1714
1715 for (pp = numposargs; pp < pronargs; pp++)
1716 {
1717 if (arggiven[pp])
1718 continue;
1719 /* fail if arg not given and no default available */
1720 if (pp < first_arg_with_default)
1721 return false;
1722 (*argnumbers)[ap++] = pp;
1723 }
1724 }
1725
1726 Assert(ap == pronargs); /* processed all function parameters */
1727
1728 /* If we get here, the call supplies all the required arguments */
1729 *fgc_flags |= FGC_ARGNAMES_ALL;
1730
1731 return true;
1732}
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1379
#define FGC_ARGNAMES_ALL
Definition: namespace.h:55
#define FGC_ARGNAMES_MATCH
Definition: namespace.h:53
#define FGC_ARGNAMES_NONDUP
Definition: namespace.h:54
@ FUNC_PARAM_IN
Definition: parsenodes.h:3576
@ FUNC_PARAM_INOUT
Definition: parsenodes.h:3578
@ FUNC_PARAM_VARIADIC
Definition: parsenodes.h:3579
#define FUNC_MAX_ARGS
#define lfirst(lc)
Definition: pg_list.h:172

References Assert(), FGC_ARGNAMES_ALL, FGC_ARGNAMES_MATCH, FGC_ARGNAMES_NONDUP, 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 3698 of file namespace.c.

3699{
3701 ListCell *l;
3702
3703 initStringInfo(&string);
3704
3705 foreach(l, names)
3706 {
3707 if (l != list_head(names))
3708 appendStringInfoChar(&string, '.');
3710 }
3711
3712 return string.data;
3713}
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:13030
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97

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

◆ NameListToString()

char * NameListToString ( const List names)

Definition at line 3664 of file namespace.c.

3665{
3667 ListCell *l;
3668
3669 initStringInfo(&string);
3670
3671 foreach(l, names)
3672 {
3673 Node *name = (Node *) lfirst(l);
3674
3675 if (l != list_head(names))
3676 appendStringInfoChar(&string, '.');
3677
3678 if (IsA(name, String))
3680 else if (IsA(name, A_Star))
3681 appendStringInfoChar(&string, '*');
3682 else
3683 elog(ERROR, "unexpected node type in name list: %d",
3684 (int) nodeTag(name));
3685 }
3686
3687 return string.data;
3688}
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define nodeTag(nodeptr)
Definition: nodes.h:139
Definition: nodes.h:135
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 2221 of file namespace.c.

2222{
2223 return OpclassIsVisibleExt(opcid, NULL);
2224}
static bool OpclassIsVisibleExt(Oid opcid, bool *is_missing)
Definition: namespace.c:2233

References OpclassIsVisibleExt().

Referenced by get_opclass_name(), and getObjectDescription().

◆ OpclassIsVisibleExt()

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

Definition at line 2233 of file namespace.c.

2234{
2235 HeapTuple opctup;
2236 Form_pg_opclass opcform;
2237 Oid opcnamespace;
2238 bool visible;
2239
2240 opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
2241 if (!HeapTupleIsValid(opctup))
2242 {
2243 if (is_missing != NULL)
2244 {
2245 *is_missing = true;
2246 return false;
2247 }
2248 elog(ERROR, "cache lookup failed for opclass %u", opcid);
2249 }
2250 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
2251
2253
2254 /*
2255 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2256 * the system namespace are surely in the path and so we needn't even do
2257 * list_member_oid() for them.
2258 */
2259 opcnamespace = opcform->opcnamespace;
2260 if (opcnamespace != PG_CATALOG_NAMESPACE &&
2261 !list_member_oid(activeSearchPath, opcnamespace))
2262 visible = false;
2263 else
2264 {
2265 /*
2266 * If it is in the path, it might still not be visible; it could be
2267 * hidden by another opclass of the same name earlier in the path. So
2268 * we must do a slow check to see if this opclass would be found by
2269 * OpclassnameGetOpcid.
2270 */
2271 char *opcname = NameStr(opcform->opcname);
2272
2273 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
2274 }
2275
2276 ReleaseSysCache(opctup);
2277
2278 return visible;
2279}
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:2188
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 2188 of file namespace.c.

2189{
2190 Oid opcid;
2191 ListCell *l;
2192
2194
2195 foreach(l, activeSearchPath)
2196 {
2197 Oid namespaceId = lfirst_oid(l);
2198
2199 if (namespaceId == myTempNamespace)
2200 continue; /* do not look in temp namespace */
2201
2202 opcid = GetSysCacheOid3(CLAAMNAMENSP, Anum_pg_opclass_oid,
2203 ObjectIdGetDatum(amid),
2204 PointerGetDatum(opcname),
2205 ObjectIdGetDatum(namespaceId));
2206 if (OidIsValid(opcid))
2207 return opcid;
2208 }
2209
2210 /* Not found in path */
2211 return InvalidOid;
2212}

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

2117{
2118 return OperatorIsVisibleExt(oprid, NULL);
2119}
static bool OperatorIsVisibleExt(Oid oprid, bool *is_missing)
Definition: namespace.c:2128
Oid oprid(Operator op)
Definition: parse_oper.c:239

References OperatorIsVisibleExt(), and oprid().

Referenced by format_operator_extended().

◆ OperatorIsVisibleExt()

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

Definition at line 2128 of file namespace.c.

2129{
2130 HeapTuple oprtup;
2131 Form_pg_operator oprform;
2132 Oid oprnamespace;
2133 bool visible;
2134
2135 oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
2136 if (!HeapTupleIsValid(oprtup))
2137 {
2138 if (is_missing != NULL)
2139 {
2140 *is_missing = true;
2141 return false;
2142 }
2143 elog(ERROR, "cache lookup failed for operator %u", oprid);
2144 }
2145 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
2146
2148
2149 /*
2150 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2151 * the system namespace are surely in the path and so we needn't even do
2152 * list_member_oid() for them.
2153 */
2154 oprnamespace = oprform->oprnamespace;
2155 if (oprnamespace != PG_CATALOG_NAMESPACE &&
2156 !list_member_oid(activeSearchPath, oprnamespace))
2157 visible = false;
2158 else
2159 {
2160 /*
2161 * If it is in the path, it might still not be visible; it could be
2162 * hidden by another operator of the same name and arguments earlier
2163 * in the path. So we must do a slow check to see if this is the same
2164 * operator that would be found by OpernameGetOprid.
2165 */
2166 char *oprname = NameStr(oprform->oprname);
2167
2168 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
2169 oprform->oprleft, oprform->oprright)
2170 == oprid);
2171 }
2172
2173 ReleaseSysCache(oprtup);
2174
2175 return visible;
2176}
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1832
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,
int *  fgc_flags 
)

Definition at line 1945 of file namespace.c.

1947{
1948 FuncCandidateList resultList = NULL;
1949 char *resultSpace = NULL;
1950 int nextResult = 0;
1951 char *schemaname;
1952 char *opername;
1953 Oid namespaceId;
1954 CatCList *catlist;
1955 int i;
1956
1957 /* initialize output fgc_flags to empty */
1958 *fgc_flags = 0;
1959
1960 /* deconstruct the name list */
1961 DeconstructQualifiedName(names, &schemaname, &opername);
1962
1963 if (schemaname)
1964 {
1965 /* use exact schema given */
1966 *fgc_flags |= FGC_SCHEMA_GIVEN; /* report that a schema is given */
1967 namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
1968 if (!OidIsValid(namespaceId))
1969 return NULL;
1970 *fgc_flags |= FGC_SCHEMA_EXISTS; /* report that the schema exists */
1971 }
1972 else
1973 {
1974 /* flag to indicate we need namespace search */
1975 namespaceId = InvalidOid;
1977 }
1978
1979 /* Search syscache by name only */
1980 catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
1981
1982 /*
1983 * In typical scenarios, most if not all of the operators found by the
1984 * catcache search will end up getting returned; and there can be quite a
1985 * few, for common operator names such as '=' or '+'. To reduce the time
1986 * spent in palloc, we allocate the result space as an array large enough
1987 * to hold all the operators. The original coding of this routine did a
1988 * separate palloc for each operator, but profiling revealed that the
1989 * pallocs used an unreasonably large fraction of parsing time.
1990 */
1991#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
1992 2 * sizeof(Oid))
1993
1994 if (catlist->n_members > 0)
1995 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1996
1997 for (i = 0; i < catlist->n_members; i++)
1998 {
1999 HeapTuple opertup = &catlist->members[i]->tuple;
2000 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
2001 int pathpos = 0;
2002 FuncCandidateList newResult;
2003
2004 /* Ignore operators of wrong kind, if specific kind requested */
2005 if (oprkind && operform->oprkind != oprkind)
2006 continue;
2007
2008 *fgc_flags |= FGC_NAME_EXISTS; /* the name is present in pg_operator */
2009
2010 if (OidIsValid(namespaceId))
2011 {
2012 /* Consider only opers in specified namespace */
2013 if (operform->oprnamespace != namespaceId)
2014 continue;
2015 /* No need to check args, they must all be different */
2016 }
2017 else
2018 {
2019 /*
2020 * Consider only opers that are in the search path and are not in
2021 * the temp namespace.
2022 */
2023 ListCell *nsp;
2024
2025 foreach(nsp, activeSearchPath)
2026 {
2027 if (operform->oprnamespace == lfirst_oid(nsp) &&
2028 operform->oprnamespace != myTempNamespace)
2029 break;
2030 pathpos++;
2031 }
2032 if (nsp == NULL)
2033 continue; /* oper is not in search path */
2034
2035 /*
2036 * Okay, it's in the search path, but does it have the same
2037 * arguments as something we already accepted? If so, keep only
2038 * the one that appears earlier in the search path.
2039 *
2040 * If we have an ordered list from SearchSysCacheList (the normal
2041 * case), then any conflicting oper must immediately adjoin this
2042 * one in the list, so we only need to look at the newest result
2043 * item. If we have an unordered list, we have to scan the whole
2044 * result list.
2045 */
2046 if (resultList)
2047 {
2048 FuncCandidateList prevResult;
2049
2050 if (catlist->ordered)
2051 {
2052 if (operform->oprleft == resultList->args[0] &&
2053 operform->oprright == resultList->args[1])
2054 prevResult = resultList;
2055 else
2056 prevResult = NULL;
2057 }
2058 else
2059 {
2060 for (prevResult = resultList;
2061 prevResult;
2062 prevResult = prevResult->next)
2063 {
2064 if (operform->oprleft == prevResult->args[0] &&
2065 operform->oprright == prevResult->args[1])
2066 break;
2067 }
2068 }
2069 if (prevResult)
2070 {
2071 /* We have a match with a previous result */
2072 Assert(pathpos != prevResult->pathpos);
2073 if (pathpos > prevResult->pathpos)
2074 continue; /* keep previous result */
2075 /* replace previous result */
2076 prevResult->pathpos = pathpos;
2077 prevResult->oid = operform->oid;
2078 continue; /* args are same, of course */
2079 }
2080 }
2081 }
2082
2083 *fgc_flags |= FGC_NAME_VISIBLE; /* operator is in the right schema */
2084
2085 /*
2086 * Okay to add it to result list
2087 */
2088 newResult = (FuncCandidateList) (resultSpace + nextResult);
2089 nextResult += SPACE_PER_OP;
2090
2091 newResult->pathpos = pathpos;
2092 newResult->oid = operform->oid;
2093 newResult->nominalnargs = 2;
2094 newResult->nargs = 2;
2095 newResult->nvargs = 0;
2096 newResult->ndargs = 0;
2097 newResult->argnumbers = NULL;
2098 newResult->args[0] = operform->oprleft;
2099 newResult->args[1] = operform->oprright;
2100 newResult->next = resultList;
2101 resultList = newResult;
2102 }
2103
2104 ReleaseSysCacheList(catlist);
2105
2106 return resultList;
2107}
#define SPACE_PER_OP

References activeSearchPath, _FuncCandidateList::argnumbers, _FuncCandidateList::args, Assert(), CStringGetDatum(), DeconstructQualifiedName(), FGC_NAME_EXISTS, FGC_NAME_VISIBLE, FGC_SCHEMA_EXISTS, FGC_SCHEMA_GIVEN, 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 1832 of file namespace.c.

1833{
1834 char *schemaname;
1835 char *opername;
1836 CatCList *catlist;
1837 ListCell *l;
1838
1839 /* deconstruct the name list */
1840 DeconstructQualifiedName(names, &schemaname, &opername);
1841
1842 if (schemaname)
1843 {
1844 /* search only in exact schema given */
1845 Oid namespaceId;
1846
1847 namespaceId = LookupExplicitNamespace(schemaname, true);
1848 if (OidIsValid(namespaceId))
1849 {
1850 HeapTuple opertup;
1851
1852 opertup = SearchSysCache4(OPERNAMENSP,
1853 CStringGetDatum(opername),
1854 ObjectIdGetDatum(oprleft),
1855 ObjectIdGetDatum(oprright),
1856 ObjectIdGetDatum(namespaceId));
1857 if (HeapTupleIsValid(opertup))
1858 {
1859 Form_pg_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
1860 Oid result = operclass->oid;
1861
1862 ReleaseSysCache(opertup);
1863 return result;
1864 }
1865 }
1866
1867 return InvalidOid;
1868 }
1869
1870 /* Search syscache by name and argument types */
1871 catlist = SearchSysCacheList3(OPERNAMENSP,
1872 CStringGetDatum(opername),
1873 ObjectIdGetDatum(oprleft),
1874 ObjectIdGetDatum(oprright));
1875
1876 if (catlist->n_members == 0)
1877 {
1878 /* no hope, fall out early */
1879 ReleaseSysCacheList(catlist);
1880 return InvalidOid;
1881 }
1882
1883 /*
1884 * We have to find the list member that is first in the search path, if
1885 * there's more than one. This doubly-nested loop looks ugly, but in
1886 * practice there should usually be few catlist members.
1887 */
1889
1890 foreach(l, activeSearchPath)
1891 {
1892 Oid namespaceId = lfirst_oid(l);
1893 int i;
1894
1895 if (namespaceId == myTempNamespace)
1896 continue; /* do not look in temp namespace */
1897
1898 for (i = 0; i < catlist->n_members; i++)
1899 {
1900 HeapTuple opertup = &catlist->members[i]->tuple;
1901 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1902
1903 if (operform->oprnamespace == namespaceId)
1904 {
1905 Oid result = operform->oid;
1906
1907 ReleaseSysCacheList(catlist);
1908 return result;
1909 }
1910 }
1911 }
1912
1913 ReleaseSysCacheList(catlist);
1914 return InvalidOid;
1915}
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:250
#define SearchSysCacheList3(cacheId, key1, key2, key3)
Definition: syscache.h:131

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

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

◆ OpfamilyIsVisible()

bool OpfamilyIsVisible ( Oid  opfid)

Definition at line 2323 of file namespace.c.

2324{
2325 return OpfamilyIsVisibleExt(opfid, NULL);
2326}
static bool OpfamilyIsVisibleExt(Oid opfid, bool *is_missing)
Definition: namespace.c:2335

References OpfamilyIsVisibleExt().

Referenced by getOpFamilyDescription().

◆ OpfamilyIsVisibleExt()

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

Definition at line 2335 of file namespace.c.

2336{
2337 HeapTuple opftup;
2338 Form_pg_opfamily opfform;
2339 Oid opfnamespace;
2340 bool visible;
2341
2342 opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
2343 if (!HeapTupleIsValid(opftup))
2344 {
2345 if (is_missing != NULL)
2346 {
2347 *is_missing = true;
2348 return false;
2349 }
2350 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
2351 }
2352 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
2353
2355
2356 /*
2357 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2358 * the system namespace are surely in the path and so we needn't even do
2359 * list_member_oid() for them.
2360 */
2361 opfnamespace = opfform->opfnamespace;
2362 if (opfnamespace != PG_CATALOG_NAMESPACE &&
2363 !list_member_oid(activeSearchPath, opfnamespace))
2364 visible = false;
2365 else
2366 {
2367 /*
2368 * If it is in the path, it might still not be visible; it could be
2369 * hidden by another opfamily of the same name earlier in the path. So
2370 * we must do a slow check to see if this opfamily would be found by
2371 * OpfamilynameGetOpfid.
2372 */
2373 char *opfname = NameStr(opfform->opfname);
2374
2375 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
2376 }
2377
2378 ReleaseSysCache(opftup);
2379
2380 return visible;
2381}
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
Definition: namespace.c:2290
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 2290 of file namespace.c.

2291{
2292 Oid opfid;
2293 ListCell *l;
2294
2296
2297 foreach(l, activeSearchPath)
2298 {
2299 Oid namespaceId = lfirst_oid(l);
2300
2301 if (namespaceId == myTempNamespace)
2302 continue; /* do not look in temp namespace */
2303
2304 opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP, Anum_pg_opfamily_oid,
2305 ObjectIdGetDatum(amid),
2306 PointerGetDatum(opfname),
2307 ObjectIdGetDatum(namespaceId));
2308 if (OidIsValid(opfid))
2309 return opfid;
2310 }
2311
2312 /* Not found in path */
2313 return InvalidOid;
2314}

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

5049{
5050 Oid oid = PG_GETARG_OID(0);
5051 bool result;
5052 bool is_missing = false;
5053
5054 result = CollationIsVisibleExt(oid, &is_missing);
5055
5056 if (is_missing)
5058 PG_RETURN_BOOL(result);
5059}
#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 5062 of file namespace.c.

5063{
5064 Oid oid = PG_GETARG_OID(0);
5065 bool result;
5066 bool is_missing = false;
5067
5068 result = ConversionIsVisibleExt(oid, &is_missing);
5069
5070 if (is_missing)
5072 PG_RETURN_BOOL(result);
5073}

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

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

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

5153{
5154 Oid oid = PG_GETARG_OID(0);
5155
5157}
bool isOtherTempNamespace(Oid namespaceId)
Definition: namespace.c:3780

References isOtherTempNamespace(), PG_GETARG_OID, and PG_RETURN_BOOL.

◆ pg_my_temp_schema()

Datum pg_my_temp_schema ( PG_FUNCTION_ARGS  )

Definition at line 5146 of file namespace.c.

5147{
5149}
#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 5020 of file namespace.c.

5021{
5022 Oid oid = PG_GETARG_OID(0);
5023 bool result;
5024 bool is_missing = false;
5025
5026 result = OpclassIsVisibleExt(oid, &is_missing);
5027
5028 if (is_missing)
5030 PG_RETURN_BOOL(result);
5031}

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

5007{
5008 Oid oid = PG_GETARG_OID(0);
5009 bool result;
5010 bool is_missing = false;
5011
5012 result = OperatorIsVisibleExt(oid, &is_missing);
5013
5014 if (is_missing)
5016 PG_RETURN_BOOL(result);
5017}

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

5035{
5036 Oid oid = PG_GETARG_OID(0);
5037 bool result;
5038 bool is_missing = false;
5039
5040 result = OpfamilyIsVisibleExt(oid, &is_missing);
5041
5042 if (is_missing)
5044 PG_RETURN_BOOL(result);
5045}

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

5077{
5078 Oid oid = PG_GETARG_OID(0);
5079 bool result;
5080 bool is_missing = false;
5081
5082 result = StatisticsObjIsVisibleExt(oid, &is_missing);
5083
5084 if (is_missing)
5086 PG_RETURN_BOOL(result);
5087}
static bool StatisticsObjIsVisibleExt(Oid stxid, bool *is_missing)
Definition: namespace.c:2711

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

4965{
4966 Oid oid = PG_GETARG_OID(0);
4967 bool result;
4968 bool is_missing = false;
4969
4970 result = RelationIsVisibleExt(oid, &is_missing);
4971
4972 if (is_missing)
4974 PG_RETURN_BOOL(result);
4975}
static bool RelationIsVisibleExt(Oid relid, bool *is_missing)
Definition: namespace.c:924

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

5133{
5134 Oid oid = PG_GETARG_OID(0);
5135 bool result;
5136 bool is_missing = false;
5137
5138 result = TSConfigIsVisibleExt(oid, &is_missing);
5139
5140 if (is_missing)
5142 PG_RETURN_BOOL(result);
5143}
static bool TSConfigIsVisibleExt(Oid cfgid, bool *is_missing)
Definition: namespace.c:3292

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

5105{
5106 Oid oid = PG_GETARG_OID(0);
5107 bool result;
5108 bool is_missing = false;
5109
5110 result = TSDictionaryIsVisibleExt(oid, &is_missing);
5111
5112 if (is_missing)
5114 PG_RETURN_BOOL(result);
5115}
static bool TSDictionaryIsVisibleExt(Oid dictId, bool *is_missing)
Definition: namespace.c:3001

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

5091{
5092 Oid oid = PG_GETARG_OID(0);
5093 bool result;
5094 bool is_missing = false;
5095
5096 result = TSParserIsVisibleExt(oid, &is_missing);
5097
5098 if (is_missing)
5100 PG_RETURN_BOOL(result);
5101}
static bool TSParserIsVisibleExt(Oid prsId, bool *is_missing)
Definition: namespace.c:2856

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

5119{
5120 Oid oid = PG_GETARG_OID(0);
5121 bool result;
5122 bool is_missing = false;
5123
5124 result = TSTemplateIsVisibleExt(oid, &is_missing);
5125
5126 if (is_missing)
5128 PG_RETURN_BOOL(result);
5129}
static bool TSTemplateIsVisibleExt(Oid tmplId, bool *is_missing)
Definition: namespace.c:3147

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

4979{
4980 Oid oid = PG_GETARG_OID(0);
4981 bool result;
4982 bool is_missing = false;
4983
4984 result = TypeIsVisibleExt(oid, &is_missing);
4985
4986 if (is_missing)
4988 PG_RETURN_BOOL(result);
4989}
static bool TypeIsVisibleExt(Oid typid, bool *is_missing)
Definition: namespace.c:1051

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

4179{
4180 char *rawname;
4181 List *namelist;
4182 List *oidlist;
4183 ListCell *l;
4184
4185 /* Need a modifiable copy */
4186 rawname = pstrdup(searchPath);
4187
4188 /* Parse string into list of identifiers */
4189 if (!SplitIdentifierString(rawname, ',', &namelist))
4190 {
4191 /* syntax error in name list */
4192 /* this should not happen if GUC checked check_search_path */
4193 elog(ERROR, "invalid list syntax");
4194 }
4195
4196 /*
4197 * Convert the list of names to a list of OIDs. If any names are not
4198 * recognizable or we don't have read access, just leave them out of the
4199 * list. (We can't raise an error, since the search_path setting has
4200 * already been accepted.) Don't make duplicate entries, either.
4201 */
4202 oidlist = NIL;
4203 *temp_missing = false;
4204 foreach(l, namelist)
4205 {
4206 char *curname = (char *) lfirst(l);
4207 Oid namespaceId;
4208
4209 if (strcmp(curname, "$user") == 0)
4210 {
4211 /* $user --- substitute namespace matching user name, if any */
4212 HeapTuple tuple;
4213
4214 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4215 if (HeapTupleIsValid(tuple))
4216 {
4217 char *rname;
4218
4219 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
4220 namespaceId = get_namespace_oid(rname, true);
4221 ReleaseSysCache(tuple);
4222 if (OidIsValid(namespaceId) &&
4223 object_aclcheck(NamespaceRelationId, namespaceId, roleid,
4225 oidlist = lappend_oid(oidlist, namespaceId);
4226 }
4227 }
4228 else if (strcmp(curname, "pg_temp") == 0)
4229 {
4230 /* pg_temp --- substitute temp namespace, if any */
4232 oidlist = lappend_oid(oidlist, myTempNamespace);
4233 else
4234 {
4235 /* If it ought to be the creation namespace, set flag */
4236 if (oidlist == NIL)
4237 *temp_missing = true;
4238 }
4239 }
4240 else
4241 {
4242 /* normal namespace reference */
4243 namespaceId = get_namespace_oid(curname, true);
4244 if (OidIsValid(namespaceId) &&
4245 object_aclcheck(NamespaceRelationId, namespaceId, roleid,
4247 oidlist = lappend_oid(oidlist, namespaceId);
4248 }
4249 }
4250
4251 pfree(rawname);
4252 list_free(namelist);
4253
4254 return oidlist;
4255}
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 3557 of file namespace.c.

3558{
3559 char *schemaname;
3560 Oid namespaceId;
3561
3562 /* deconstruct the name list */
3563 DeconstructQualifiedName(names, &schemaname, objname_p);
3564
3565 if (schemaname)
3566 {
3567 /* check for pg_temp alias */
3568 if (strcmp(schemaname, "pg_temp") == 0)
3569 {
3570 /* Initialize temp namespace */
3572 return myTempNamespace;
3573 }
3574 /* use exact schema given */
3575 namespaceId = get_namespace_oid(schemaname, false);
3576 /* we do not check for USAGE rights here! */
3577 }
3578 else
3579 {
3580 /* use the default creation namespace */
3583 {
3584 /* Need to initialize temp namespace */
3586 return myTempNamespace;
3587 }
3588 namespaceId = activeCreationNamespace;
3589 if (!OidIsValid(namespaceId))
3590 ereport(ERROR,
3591 (errcode(ERRCODE_UNDEFINED_SCHEMA),
3592 errmsg("no schema has been selected to create in")));
3593 }
3594
3595 return namespaceId;
3596}

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

846{
847 switch (newRelation->relpersistence)
848 {
849 case RELPERSISTENCE_TEMP:
851 {
854 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
855 errmsg("cannot create relations in temporary schemas of other sessions")));
856 else
858 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
859 errmsg("cannot create temporary relation in non-temporary schema")));
860 }
861 break;
862 case RELPERSISTENCE_PERMANENT:
864 newRelation->relpersistence = RELPERSISTENCE_TEMP;
865 else if (isAnyTempNamespace(nspid))
867 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
868 errmsg("cannot create relations in temporary schemas of other sessions")));
869 break;
870 default:
873 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
874 errmsg("only temporary relations may be created in temporary schemas")));
875 }
876}
int nspid
char relpersistence
Definition: primnodes.h:89

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

741{
742 uint64 inval_count;
743 Oid relid;
744 Oid oldrelid = InvalidOid;
745 Oid nspid;
746 Oid oldnspid = InvalidOid;
747 bool retry = false;
748
749 /*
750 * We check the catalog name and then ignore it.
751 */
752 if (relation->catalogname)
753 {
754 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
756 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
757 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
758 relation->catalogname, relation->schemaname,
759 relation->relname)));
760 }
761
762 /*
763 * As in RangeVarGetRelidExtended(), we guard against concurrent DDL
764 * operations by tracking whether any invalidation messages are processed
765 * while we're doing the name lookups and acquiring locks. See comments
766 * in that function for a more detailed explanation of this logic.
767 */
768 for (;;)
769 {
770 AclResult aclresult;
771
772 inval_count = SharedInvalidMessageCounter;
773
774 /* Look up creation namespace and check for existing relation. */
777 if (existing_relation_id != NULL)
778 relid = get_relname_relid(relation->relname, nspid);
779 else
780 relid = InvalidOid;
781
782 /*
783 * In bootstrap processing mode, we don't bother with permissions or
784 * locking. Permissions might not be working yet, and locking is
785 * unnecessary.
786 */
788 break;
789
790 /* Check namespace permissions. */
791 aclresult = object_aclcheck(NamespaceRelationId, nspid, GetUserId(), ACL_CREATE);
792 if (aclresult != ACLCHECK_OK)
793 aclcheck_error(aclresult, OBJECT_SCHEMA,
795
796 if (retry)
797 {
798 /* If nothing changed, we're done. */
799 if (relid == oldrelid && nspid == oldnspid)
800 break;
801 /* If creation namespace has changed, give up old lock. */
802 if (nspid != oldnspid)
803 UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
805 /* If name points to something different, give up old lock. */
806 if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
807 UnlockRelationOid(oldrelid, lockmode);
808 }
809
810 /* Lock namespace. */
811 if (nspid != oldnspid)
812 LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
813
814 /* Lock relation, if required if and we have permission. */
815 if (lockmode != NoLock && OidIsValid(relid))
816 {
817 if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
819 relation->relname);
820 if (relid != oldrelid)
821 LockRelationOid(relid, lockmode);
822 }
823
824 /* If no invalidation message were processed, we're done! */
825 if (inval_count == SharedInvalidMessageCounter)
826 break;
827
828 /* Something may have changed, so recheck our work. */
829 retry = true;
830 oldrelid = relid;
831 oldnspid = nspid;
832 }
833
835 if (existing_relation_id != NULL)
836 *existing_relation_id = relid;
837 return nspid;
838}
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4088
uint64_t uint64
Definition: c.h:540
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:229
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1008
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1068
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2170
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:2052
void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
Definition: namespace.c:845
Oid RangeVarGetCreationNamespace(const RangeVar *newRelation)
Definition: namespace.c:653
ObjectType get_relkind_objtype(char relkind)
uint64 SharedInvalidMessageCounter
Definition: sinval.c:24

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

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

◆ RangeVarGetCreationNamespace()

Oid RangeVarGetCreationNamespace ( const RangeVar newRelation)

Definition at line 653 of file namespace.c.

654{
655 Oid namespaceId;
656
657 /*
658 * We check the catalog name and then ignore it.
659 */
660 if (newRelation->catalogname)
661 {
662 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
664 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
665 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
666 newRelation->catalogname, newRelation->schemaname,
667 newRelation->relname)));
668 }
669
670 if (newRelation->schemaname)
671 {
672 /* check for pg_temp alias */
673 if (strcmp(newRelation->schemaname, "pg_temp") == 0)
674 {
675 /* Initialize temp namespace */
677 return myTempNamespace;
678 }
679 /* use exact schema given */
680 namespaceId = get_namespace_oid(newRelation->schemaname, false);
681 /* we do not check for USAGE rights here! */
682 }
683 else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
684 {
685 /* Initialize temp namespace */
687 return myTempNamespace;
688 }
689 else
690 {
691 /* use the default creation namespace */
694 {
695 /* Need to initialize temp namespace */
697 return myTempNamespace;
698 }
699 namespaceId = activeCreationNamespace;
700 if (!OidIsValid(namespaceId))
702 (errcode(ERRCODE_UNDEFINED_SCHEMA),
703 errmsg("no schema has been selected to create in")));
704 }
705
706 /* Note: callers will check for CREATE rights when appropriate */
707
708 return namespaceId;
709}

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

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

4370{
4371 Oid roleid = GetUserId();
4372 bool pathChanged;
4373 const SearchPathCacheEntry *entry;
4374
4375 /* Do nothing if path is already valid. */
4376 if (baseSearchPathValid && namespaceUser == roleid)
4377 return;
4378
4380
4381 if (baseCreationNamespace == entry->firstNS &&
4384 {
4385 pathChanged = false;
4386 }
4387 else
4388 {
4389 MemoryContext oldcxt;
4390 List *newpath;
4391
4392 pathChanged = true;
4393
4394 /* Must save OID list in permanent storage. */
4396 newpath = list_copy(entry->finalPath);
4397 MemoryContextSwitchTo(oldcxt);
4398
4399 /* Now safe to assign to state variables. */
4401 baseSearchPath = newpath;
4404 }
4405
4406 /* Mark the path valid. */
4407 baseSearchPathValid = true;
4408 namespaceUser = roleid;
4409
4410 /* And make it active. */
4414
4415 /*
4416 * Bump the generation only if something actually changed. (Notice that
4417 * what we compared to was the old state of the base path variables.)
4418 */
4419 if (pathChanged)
4421}
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
static const SearchPathCacheEntry * cachedNamespacePath(const char *searchPath, Oid roleid)
Definition: namespace.c:4314
char * namespace_search_path
Definition: namespace.c:210

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

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

References RelationIsVisibleExt().

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

◆ RelationIsVisibleExt()

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

Definition at line 924 of file namespace.c.

925{
926 HeapTuple reltup;
927 Form_pg_class relform;
928 Oid relnamespace;
929 bool visible;
930
931 reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
932 if (!HeapTupleIsValid(reltup))
933 {
934 if (is_missing != NULL)
935 {
936 *is_missing = true;
937 return false;
938 }
939 elog(ERROR, "cache lookup failed for relation %u", relid);
940 }
941 relform = (Form_pg_class) GETSTRUCT(reltup);
942
944
945 /*
946 * Quick check: if it ain't in the path at all, it ain't visible. Items in
947 * the system namespace are surely in the path and so we needn't even do
948 * list_member_oid() for them.
949 */
950 relnamespace = relform->relnamespace;
951 if (relnamespace != PG_CATALOG_NAMESPACE &&
952 !list_member_oid(activeSearchPath, relnamespace))
953 visible = false;
954 else
955 {
956 /*
957 * If it is in the path, it might still not be visible; it could be
958 * hidden by another relation of the same name earlier in the path. So
959 * we must do a slow check for conflicting relations.
960 */
961 char *relname = NameStr(relform->relname);
962 ListCell *l;
963
964 visible = false;
965 foreach(l, activeSearchPath)
966 {
967 Oid namespaceId = lfirst_oid(l);
968
969 if (namespaceId == relnamespace)
970 {
971 /* Found it first in path */
972 visible = true;
973 break;
974 }
975 if (OidIsValid(get_relname_relid(relname, namespaceId)))
976 {
977 /* Found something else first in path */
978 break;
979 }
980 }
981 }
982
983 ReleaseSysCache(reltup);
984
985 return visible;
986}
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:156

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

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

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

4669{
4670 ObjectAddress object;
4671
4672 /*
4673 * We want to get rid of everything in the target namespace, but not the
4674 * namespace itself (deleting it only to recreate it later would be a
4675 * waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
4676 * deletion, and we want to not drop any extensions that might happen to
4677 * own temp objects.
4678 */
4679 object.classId = NamespaceRelationId;
4680 object.objectId = tempNamespaceId;
4681 object.objectSubId = 0;
4682
4688}
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:2398

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

4695{
4696 if (OidIsValid(myTempNamespace)) /* should always be true */
4697 {
4698 /* Need to ensure we have a usable transaction. */
4702
4704
4707 }
4708}
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:271
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:680
void PopActiveSnapshot(void)
Definition: snapmgr.c:773
void StartTransactionCommand(void)
Definition: xact.c:3071
void CommitTransactionCommand(void)
Definition: xact.c:3169
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4874

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

Referenced by AtEOXact_Namespace().

◆ ResetTempTableNamespace()

void ResetTempTableNamespace ( void  )

Definition at line 4714 of file namespace.c.

References myTempNamespace, OidIsValid, and RemoveTempRelations().

Referenced by DiscardAll(), and DiscardCommand().

◆ SearchPathMatchesCurrentEnvironment()

bool SearchPathMatchesCurrentEnvironment ( SearchPathMatcher path)

Definition at line 3981 of file namespace.c.

3982{
3983 ListCell *lc,
3984 *lcp;
3985
3987
3988 /* Quick out if already known equal to active path. */
3989 if (path->generation == activePathGeneration)
3990 return true;
3991
3992 /* We scan down the activeSearchPath to see if it matches the input. */
3994
3995 /* If path->addTemp, first item should be my temp namespace. */
3996 if (path->addTemp)
3997 {
3998 if (lc && lfirst_oid(lc) == myTempNamespace)
3999 lc = lnext(activeSearchPath, lc);
4000 else
4001 return false;
4002 }
4003 /* If path->addCatalog, next item should be pg_catalog. */
4004 if (path->addCatalog)
4005 {
4006 if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
4007 lc = lnext(activeSearchPath, lc);
4008 else
4009 return false;
4010 }
4011 /* We should now be looking at the activeCreationNamespace. */
4012 if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
4013 return false;
4014 /* The remainder of activeSearchPath should match path->schemas. */
4015 foreach(lcp, path->schemas)
4016 {
4017 if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
4018 lc = lnext(activeSearchPath, lc);
4019 else
4020 return false;
4021 }
4022 if (lc)
4023 return false;
4024
4025 /*
4026 * Update path->generation so that future tests will return quickly, so
4027 * long as the active search path doesn't change.
4028 */
4030
4031 return true;
4032}
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 3891 of file namespace.c.

3892{
3893 /* Worker should not have created its own namespaces ... */
3897
3898 /* Assign same namespace OIDs that leader has */
3899 myTempNamespace = tempNamespaceId;
3900 myTempToastNamespace = tempToastNamespaceId;
3901
3902 /*
3903 * It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
3904 * Even if the namespace is new so far as the leader is concerned, it's
3905 * not new to the worker, and we certainly wouldn't want the worker trying
3906 * to destroy it.
3907 */
3908
3909 baseSearchPathValid = false; /* may need to rebuild list */
3910 searchPathCacheValid = false;
3911}

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

Referenced by ParallelWorkerMain().

◆ spcache_init()

static void spcache_init ( void  )
static

Definition at line 305 of file namespace.c.

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

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

Referenced by cachedNamespacePath(), and check_search_path().

◆ spcache_insert()

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

Definition at line 373 of file namespace.c.

374{
377 strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
378 {
380 }
381 else
382 {
384 SearchPathCacheKey cachekey = {
385 .searchPath = searchPath,
386 .roleid = roleid
387 };
388
389 /*
390 * searchPath is not saved in SearchPathCacheContext. First perform a
391 * lookup, and copy searchPath only if we need to create a new entry.
392 */
393 entry = nsphash_lookup(SearchPathCache, cachekey);
394
395 if (!entry)
396 {
397 bool found;
398
400 entry = nsphash_insert(SearchPathCache, cachekey, &found);
401 Assert(!found);
402
403 entry->oidlist = NIL;
404 entry->finalPath = NIL;
405 entry->firstNS = InvalidOid;
406 entry->temp_missing = false;
407 entry->forceRecompute = false;
408 /* do not touch entry->status, used by simplehash */
409 }
410
412 return entry;
413 }
414}
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1746
SearchPathCacheKey key
Definition: namespace.c:174
const char * searchPath
Definition: namespace.c:168

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

344{
347 strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
348 {
350 }
351 else
352 {
354 SearchPathCacheKey cachekey = {
355 .searchPath = searchPath,
356 .roleid = roleid
357 };
358
359 entry = nsphash_lookup(SearchPathCache, cachekey);
360 if (entry)
362 return entry;
363 }
364}

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

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

References a, and b.

◆ spcachekey_hash()

static uint32 spcachekey_hash ( SearchPathCacheKey  key)
inlinestatic

Definition at line 253 of file namespace.c.

254{
256 int sp_len;
257
258 fasthash_init(&hs, 0);
259
260 hs.accum = key.roleid;
261 fasthash_combine(&hs);
262
263 /*
264 * Combine search path into the hash and save the length for tweaking the
265 * final mix.
266 */
267 sp_len = fasthash_accum_cstring(&hs, key.searchPath);
268
269 return fasthash_final32(&hs, sp_len);
270}
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 2699 of file namespace.c.

2700{
2701 return StatisticsObjIsVisibleExt(stxid, NULL);
2702}

References StatisticsObjIsVisibleExt().

Referenced by getObjectDescription().

◆ StatisticsObjIsVisibleExt()

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

Definition at line 2711 of file namespace.c.

2712{
2713 HeapTuple stxtup;
2714 Form_pg_statistic_ext stxform;
2715 Oid stxnamespace;
2716 bool visible;
2717
2718 stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stxid));
2719 if (!HeapTupleIsValid(stxtup))
2720 {
2721 if (is_missing != NULL)
2722 {
2723 *is_missing = true;
2724 return false;
2725 }
2726 elog(ERROR, "cache lookup failed for statistics object %u", stxid);
2727 }
2728 stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
2729
2731
2732 /*
2733 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2734 * the system namespace are surely in the path and so we needn't even do
2735 * list_member_oid() for them.
2736 */
2737 stxnamespace = stxform->stxnamespace;
2738 if (stxnamespace != PG_CATALOG_NAMESPACE &&
2739 !list_member_oid(activeSearchPath, stxnamespace))
2740 visible = false;
2741 else
2742 {
2743 /*
2744 * If it is in the path, it might still not be visible; it could be
2745 * hidden by another statistics object of the same name earlier in the
2746 * path. So we must do a slow check for conflicting objects.
2747 */
2748 char *stxname = NameStr(stxform->stxname);
2749 ListCell *l;
2750
2751 visible = false;
2752 foreach(l, activeSearchPath)
2753 {
2754 Oid namespaceId = lfirst_oid(l);
2755
2756 if (namespaceId == myTempNamespace)
2757 continue; /* do not look in temp namespace */
2758
2759 if (namespaceId == stxnamespace)
2760 {
2761 /* Found it first in path */
2762 visible = true;
2763 break;
2764 }
2765 if (SearchSysCacheExists2(STATEXTNAMENSP,
2766 PointerGetDatum(stxname),
2767 ObjectIdGetDatum(namespaceId)))
2768 {
2769 /* Found something else first in path */
2770 break;
2771 }
2772 }
2773 }
2774
2775 ReleaseSysCache(stxtup);
2776
2777 return visible;
2778}
FormData_pg_statistic_ext * Form_pg_statistic_ext
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:102

References activeSearchPath, elog, ERROR, GETSTRUCT(), HeapTupleIsValid, lfirst_oid, list_member_oid(), myTempNamespace, 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 3280 of file namespace.c.

3281{
3282 return TSConfigIsVisibleExt(cfgid, NULL);
3283}

References TSConfigIsVisibleExt().

Referenced by getObjectDescription(), and regconfigout().

◆ TSConfigIsVisibleExt()

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

Definition at line 3292 of file namespace.c.

3293{
3294 HeapTuple tup;
3295 Form_pg_ts_config form;
3296 Oid namespace;
3297 bool visible;
3298
3299 tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
3300 if (!HeapTupleIsValid(tup))
3301 {
3302 if (is_missing != NULL)
3303 {
3304 *is_missing = true;
3305 return false;
3306 }
3307 elog(ERROR, "cache lookup failed for text search configuration %u",
3308 cfgid);
3309 }
3310 form = (Form_pg_ts_config) GETSTRUCT(tup);
3311
3313
3314 /*
3315 * Quick check: if it ain't in the path at all, it ain't visible. Items in
3316 * the system namespace are surely in the path and so we needn't even do
3317 * list_member_oid() for them.
3318 */
3319 namespace = form->cfgnamespace;
3320 if (namespace != PG_CATALOG_NAMESPACE &&
3321 !list_member_oid(activeSearchPath, namespace))
3322 visible = false;
3323 else
3324 {
3325 /*
3326 * If it is in the path, it might still not be visible; it could be
3327 * hidden by another configuration of the same name earlier in the
3328 * path. So we must do a slow check for conflicting configurations.
3329 */
3330 char *name = NameStr(form->cfgname);
3331 ListCell *l;
3332
3333 visible = false;
3334 foreach(l, activeSearchPath)
3335 {
3336 Oid namespaceId = lfirst_oid(l);
3337
3338 if (namespaceId == myTempNamespace)
3339 continue; /* do not look in temp namespace */
3340
3341 if (namespaceId == namespace)
3342 {
3343 /* Found it first in path */
3344 visible = true;
3345 break;
3346 }
3347 if (SearchSysCacheExists2(TSCONFIGNAMENSP,
3349 ObjectIdGetDatum(namespaceId)))
3350 {
3351 /* Found something else first in path */
3352 break;
3353 }
3354 }
3355 }
3356
3357 ReleaseSysCache(tup);
3358
3359 return visible;
3360}
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 2989 of file namespace.c.

2990{
2991 return TSDictionaryIsVisibleExt(dictId, NULL);
2992}

References TSDictionaryIsVisibleExt().

Referenced by getObjectDescription(), and regdictionaryout().

◆ TSDictionaryIsVisibleExt()

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

Definition at line 3001 of file namespace.c.

3002{
3003 HeapTuple tup;
3004 Form_pg_ts_dict form;
3005 Oid namespace;
3006 bool visible;
3007
3008 tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
3009 if (!HeapTupleIsValid(tup))
3010 {
3011 if (is_missing != NULL)
3012 {
3013 *is_missing = true;
3014 return false;
3015 }
3016 elog(ERROR, "cache lookup failed for text search dictionary %u",
3017 dictId);
3018 }
3019 form = (Form_pg_ts_dict) GETSTRUCT(tup);
3020
3022
3023 /*
3024 * Quick check: if it ain't in the path at all, it ain't visible. Items in
3025 * the system namespace are surely in the path and so we needn't even do
3026 * list_member_oid() for them.
3027 */
3028 namespace = form->dictnamespace;
3029 if (namespace != PG_CATALOG_NAMESPACE &&
3030 !list_member_oid(activeSearchPath, namespace))
3031 visible = false;
3032 else
3033 {
3034 /*
3035 * If it is in the path, it might still not be visible; it could be
3036 * hidden by another dictionary of the same name earlier in the path.
3037 * So we must do a slow check for conflicting dictionaries.
3038 */
3039 char *name = NameStr(form->dictname);
3040 ListCell *l;
3041
3042 visible = false;
3043 foreach(l, activeSearchPath)
3044 {
3045 Oid namespaceId = lfirst_oid(l);
3046
3047 if (namespaceId == myTempNamespace)
3048 continue; /* do not look in temp namespace */
3049
3050 if (namespaceId == namespace)
3051 {
3052 /* Found it first in path */
3053 visible = true;
3054 break;
3055 }
3056 if (SearchSysCacheExists2(TSDICTNAMENSP,
3058 ObjectIdGetDatum(namespaceId)))
3059 {
3060 /* Found something else first in path */
3061 break;
3062 }
3063 }
3064 }
3065
3066 ReleaseSysCache(tup);
3067
3068 return visible;
3069}
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 2844 of file namespace.c.

2845{
2846 return TSParserIsVisibleExt(prsId, NULL);
2847}

References TSParserIsVisibleExt().

Referenced by getObjectDescription().

◆ TSParserIsVisibleExt()

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

Definition at line 2856 of file namespace.c.

2857{
2858 HeapTuple tup;
2859 Form_pg_ts_parser form;
2860 Oid namespace;
2861 bool visible;
2862
2863 tup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
2864 if (!HeapTupleIsValid(tup))
2865 {
2866 if (is_missing != NULL)
2867 {
2868 *is_missing = true;
2869 return false;
2870 }
2871 elog(ERROR, "cache lookup failed for text search parser %u", prsId);
2872 }
2873 form = (Form_pg_ts_parser) GETSTRUCT(tup);
2874
2876
2877 /*
2878 * Quick check: if it ain't in the path at all, it ain't visible. Items in
2879 * the system namespace are surely in the path and so we needn't even do
2880 * list_member_oid() for them.
2881 */
2882 namespace = form->prsnamespace;
2883 if (namespace != PG_CATALOG_NAMESPACE &&
2884 !list_member_oid(activeSearchPath, namespace))
2885 visible = false;
2886 else
2887 {
2888 /*
2889 * If it is in the path, it might still not be visible; it could be
2890 * hidden by another parser of the same name earlier in the path. So
2891 * we must do a slow check for conflicting parsers.
2892 */
2893 char *name = NameStr(form->prsname);
2894 ListCell *l;
2895
2896 visible = false;
2897 foreach(l, activeSearchPath)
2898 {
2899 Oid namespaceId = lfirst_oid(l);
2900
2901 if (namespaceId == myTempNamespace)
2902 continue; /* do not look in temp namespace */
2903
2904 if (namespaceId == namespace)
2905 {
2906 /* Found it first in path */
2907 visible = true;
2908 break;
2909 }
2910 if (SearchSysCacheExists2(TSPARSERNAMENSP,
2912 ObjectIdGetDatum(namespaceId)))
2913 {
2914 /* Found something else first in path */
2915 break;
2916 }
2917 }
2918 }
2919
2920 ReleaseSysCache(tup);
2921
2922 return visible;
2923}
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55

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

Referenced by pg_ts_parser_is_visible(), and TSParserIsVisible().

◆ TSTemplateIsVisible()

bool TSTemplateIsVisible ( Oid  tmplId)

Definition at line 3135 of file namespace.c.

3136{
3137 return TSTemplateIsVisibleExt(tmplId, NULL);
3138}

References TSTemplateIsVisibleExt().

Referenced by getObjectDescription().

◆ TSTemplateIsVisibleExt()

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

Definition at line 3147 of file namespace.c.

3148{
3149 HeapTuple tup;
3151 Oid namespace;
3152 bool visible;
3153
3154 tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
3155 if (!HeapTupleIsValid(tup))
3156 {
3157 if (is_missing != NULL)
3158 {
3159 *is_missing = true;
3160 return false;
3161 }
3162 elog(ERROR, "cache lookup failed for text search template %u", tmplId);
3163 }
3164 form = (Form_pg_ts_template) GETSTRUCT(tup);
3165
3167
3168 /*
3169 * Quick check: if it ain't in the path at all, it ain't visible. Items in
3170 * the system namespace are surely in the path and so we needn't even do
3171 * list_member_oid() for them.
3172 */
3173 namespace = form->tmplnamespace;
3174 if (namespace != PG_CATALOG_NAMESPACE &&
3175 !list_member_oid(activeSearchPath, namespace))
3176 visible = false;
3177 else
3178 {
3179 /*
3180 * If it is in the path, it might still not be visible; it could be
3181 * hidden by another template of the same name earlier in the path. So
3182 * we must do a slow check for conflicting templates.
3183 */
3184 char *name = NameStr(form->tmplname);
3185 ListCell *l;
3186
3187 visible = false;
3188 foreach(l, activeSearchPath)
3189 {
3190 Oid namespaceId = lfirst_oid(l);
3191
3192 if (namespaceId == myTempNamespace)
3193 continue; /* do not look in temp namespace */
3194
3195 if (namespaceId == namespace)
3196 {
3197 /* Found it first in path */
3198 visible = true;
3199 break;
3200 }
3201 if (SearchSysCacheExists2(TSTEMPLATENAMENSP,
3203 ObjectIdGetDatum(namespaceId)))
3204 {
3205 /* Found something else first in path */
3206 break;
3207 }
3208 }
3209 }
3210
3211 ReleaseSysCache(tup);
3212
3213 return visible;
3214}
FormData_pg_ts_template * Form_pg_ts_template

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

Referenced by pg_ts_template_is_visible(), and TSTemplateIsVisible().

◆ TypeIsVisible()

bool TypeIsVisible ( Oid  typid)

Definition at line 1039 of file namespace.c.

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

References TypeIsVisibleExt().

Referenced by format_type_extended().

◆ TypeIsVisibleExt()

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

Definition at line 1051 of file namespace.c.

1052{
1053 HeapTuple typtup;
1054 Form_pg_type typform;
1055 Oid typnamespace;
1056 bool visible;
1057
1058 typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1059 if (!HeapTupleIsValid(typtup))
1060 {
1061 if (is_missing != NULL)
1062 {
1063 *is_missing = true;
1064 return false;
1065 }
1066 elog(ERROR, "cache lookup failed for type %u", typid);
1067 }
1068 typform = (Form_pg_type) GETSTRUCT(typtup);
1069
1071
1072 /*
1073 * Quick check: if it ain't in the path at all, it ain't visible. Items in
1074 * the system namespace are surely in the path and so we needn't even do
1075 * list_member_oid() for them.
1076 */
1077 typnamespace = typform->typnamespace;
1078 if (typnamespace != PG_CATALOG_NAMESPACE &&
1079 !list_member_oid(activeSearchPath, typnamespace))
1080 visible = false;
1081 else
1082 {
1083 /*
1084 * If it is in the path, it might still not be visible; it could be
1085 * hidden by another type of the same name earlier in the path. So we
1086 * must do a slow check for conflicting types.
1087 */
1088 char *typname = NameStr(typform->typname);
1089 ListCell *l;
1090
1091 visible = false;
1092 foreach(l, activeSearchPath)
1093 {
1094 Oid namespaceId = lfirst_oid(l);
1095
1096 if (namespaceId == typnamespace)
1097 {
1098 /* Found it first in path */
1099 visible = true;
1100 break;
1101 }
1102 if (SearchSysCacheExists2(TYPENAMENSP,
1104 ObjectIdGetDatum(namespaceId)))
1105 {
1106 /* Found something else first in path */
1107 break;
1108 }
1109 }
1110 }
1111
1112 ReleaseSysCache(typtup);
1113
1114 return visible;
1115}
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41

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

Referenced by pg_type_is_visible(), and TypeIsVisible().

◆ TypenameGetTypid()

Oid TypenameGetTypid ( const char *  typname)

Definition at line 994 of file namespace.c.

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

References TypenameGetTypidExtended(), and typname.

◆ TypenameGetTypidExtended()

Oid TypenameGetTypidExtended ( const char *  typname,
bool  temp_ok 
)

Definition at line 1007 of file namespace.c.

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

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

Referenced by LookupTypeNameExtended(), and TypenameGetTypid().

Variable Documentation

◆ activeCreationNamespace

◆ activePathGeneration

uint64 activePathGeneration = 1
static

◆ activeSearchPath

◆ activeTempCreationPending

bool activeTempCreationPending = false
static

◆ baseCreationNamespace

Oid baseCreationNamespace = InvalidOid
static

Definition at line 150 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ baseSearchPath

List* baseSearchPath = NIL
static

Definition at line 148 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ baseSearchPathValid

◆ baseTempCreationPending

bool baseTempCreationPending = false
static

Definition at line 152 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ LastSearchPathCacheEntry

SearchPathCacheEntry* LastSearchPathCacheEntry = NULL
static

Definition at line 299 of file namespace.c.

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

◆ myTempNamespace

◆ myTempNamespaceSubID

◆ myTempToastNamespace

◆ namespace_search_path

char* namespace_search_path = NULL

Definition at line 210 of file namespace.c.

Referenced by CreateSchemaCommand(), and recomputeNamespacePath().

◆ namespaceUser

Oid namespaceUser = InvalidOid
static

Definition at line 154 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

◆ SearchPathCache

nsphash_hash* SearchPathCache = NULL
static

Definition at line 298 of file namespace.c.

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

◆ SearchPathCacheContext

MemoryContext SearchPathCacheContext = NULL
static

Definition at line 164 of file namespace.c.

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

◆ searchPathCacheValid