Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Functions | Variables

namespace.c File Reference

#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_conversion_fn.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_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_func.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/sinval.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/guc.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
Include dependency graph for namespace.c:

Go to the source code of this file.

Data Structures

struct  OverrideStackEntry

Defines

#define SPACE_PER_OP   MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))

Functions

static void recomputeNamespacePath (void)
static void InitTempTableNamespace (void)
static void RemoveTempRelations (Oid tempNamespaceId)
static void RemoveTempRelationsCallback (int code, Datum arg)
static void NamespaceCallback (Datum arg, int cacheid, uint32 hashvalue)
static bool MatchNamedCall (HeapTuple proctup, int nargs, List *argnames, int **argnumbers)
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_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)
Oid RangeVarGetRelidExtended (const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, 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)
bool TypeIsVisible (Oid typid)
FuncCandidateList FuncnameGetCandidates (List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults)
bool FunctionIsVisible (Oid funcid)
Oid OpernameGetOprid (List *names, Oid oprleft, Oid oprright)
FuncCandidateList OpernameGetCandidates (List *names, char oprkind)
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)
Oid CollationGetCollid (const char *collname)
bool CollationIsVisible (Oid collid)
Oid ConversionGetConid (const char *conname)
bool ConversionIsVisible (Oid conid)
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 (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 classid, Oid objid)
Oid QualifiedNameGetCreationNamespace (List *names, char **objname_p)
Oid get_namespace_oid (const char *nspname, bool missing_ok)
RangeVarmakeRangeVarFromNameList (List *names)
char * NameListToString (List *names)
char * NameListToQuotedString (List *names)
bool isTempNamespace (Oid namespaceId)
bool isTempToastNamespace (Oid namespaceId)
bool isTempOrToastNamespace (Oid namespaceId)
bool isAnyTempNamespace (Oid namespaceId)
bool isOtherTempNamespace (Oid namespaceId)
int GetTempNamespaceBackendId (Oid namespaceId)
Oid GetTempToastNamespace (void)
OverrideSearchPathGetOverrideSearchPath (MemoryContext context)
OverrideSearchPathCopyOverrideSearchPath (OverrideSearchPath *path)
bool OverrideSearchPathMatchesCurrent (OverrideSearchPath *path)
void PushOverrideSearchPath (OverrideSearchPath *newpath)
void PopOverrideSearchPath (void)
Oid get_collation_oid (List *name, bool missing_ok)
Oid get_conversion_oid (List *name, bool missing_ok)
Oid FindDefaultConversionProc (int32 for_encoding, int32 to_encoding)
void AtEOXact_Namespace (bool isCommit)
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)

Variables

static ListactiveSearchPath = NIL
static Oid activeCreationNamespace = InvalidOid
static bool activeTempCreationPending = false
static ListbaseSearchPath = NIL
static Oid baseCreationNamespace = InvalidOid
static bool baseTempCreationPending = false
static Oid namespaceUser = InvalidOid
static bool baseSearchPathValid = true
static ListoverrideStack = NIL
static Oid myTempNamespace = InvalidOid
static Oid myTempToastNamespace = InvalidOid
static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId
char * namespace_search_path = NULL

Define Documentation

#define SPACE_PER_OP   MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))

Referenced by OpernameGetCandidates().


Function Documentation

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

Definition at line 3871 of file namespace.c.

References baseSearchPathValid.

{
    /*
     * We mark the path as needing recomputation, but don't do anything until
     * it's needed.  This avoids trying to do database access during GUC
     * initialization, or outside a transaction.
     */
    baseSearchPathValid = false;
}

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

Definition at line 3725 of file namespace.c.

References activeCreationNamespace, activeTempCreationPending, baseCreationNamespace, baseSearchPathValid, baseTempCreationPending, OverrideStackEntry::creationNamespace, elog, GetCurrentTransactionNestLevel(), linitial, list_delete_first(), list_free(), myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, OverrideStackEntry::nestLevel, pfree(), OverrideStackEntry::searchPath, and WARNING.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

{
    OverrideStackEntry *entry;

    if (myTempNamespaceSubID == mySubid)
    {
        if (isCommit)
            myTempNamespaceSubID = parentSubid;
        else
        {
            myTempNamespaceSubID = InvalidSubTransactionId;
            /* TEMP namespace creation failed, so reset state */
            myTempNamespace = InvalidOid;
            myTempToastNamespace = InvalidOid;
            baseSearchPathValid = false;        /* need to rebuild list */
        }
    }

    /*
     * Clean up if someone failed to do PopOverrideSearchPath
     */
    while (overrideStack)
    {
        entry = (OverrideStackEntry *) linitial(overrideStack);
        if (entry->nestLevel < GetCurrentTransactionNestLevel())
            break;
        if (isCommit)
            elog(WARNING, "leaked override search path");
        overrideStack = list_delete_first(overrideStack);
        list_free(entry->searchPath);
        pfree(entry);
    }

    /* Activate the next level down. */
    if (overrideStack)
    {
        entry = (OverrideStackEntry *) linitial(overrideStack);
        activeSearchPath = entry->searchPath;
        activeCreationNamespace = entry->creationNamespace;
        activeTempCreationPending = false;      /* XXX is this OK? */
    }
    else
    {
        /* If not baseSearchPathValid, this is useless but harmless */
        activeSearchPath = baseSearchPath;
        activeCreationNamespace = baseCreationNamespace;
        activeTempCreationPending = baseTempCreationPending;
    }
}

void AtEOXact_Namespace ( bool  isCommit  ) 

Definition at line 3670 of file namespace.c.

References activeCreationNamespace, activeTempCreationPending, baseCreationNamespace, baseSearchPathValid, baseTempCreationPending, elog, InvalidSubTransactionId, linitial, list_delete_first(), list_free(), myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, on_shmem_exit(), pfree(), RemoveTempRelationsCallback(), OverrideStackEntry::searchPath, and WARNING.

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

{
    /*
     * If we abort the transaction in which a temp namespace was selected,
     * we'll have to do any creation or cleanout work over again.  So, just
     * forget the namespace entirely until next time.  On the other hand, if
     * we commit then register an exit callback to clean out the temp tables
     * at backend shutdown.  (We only want to register the callback once per
     * session, so this is a good place to do it.)
     */
    if (myTempNamespaceSubID != InvalidSubTransactionId)
    {
        if (isCommit)
            on_shmem_exit(RemoveTempRelationsCallback, 0);
        else
        {
            myTempNamespace = InvalidOid;
            myTempToastNamespace = InvalidOid;
            baseSearchPathValid = false;        /* need to rebuild list */
        }
        myTempNamespaceSubID = InvalidSubTransactionId;
    }

    /*
     * Clean up if someone failed to do PopOverrideSearchPath
     */
    if (overrideStack)
    {
        if (isCommit)
            elog(WARNING, "leaked override search path");
        while (overrideStack)
        {
            OverrideStackEntry *entry;

            entry = (OverrideStackEntry *) linitial(overrideStack);
            overrideStack = list_delete_first(overrideStack);
            list_free(entry->searchPath);
            pfree(entry);
        }
        /* If not baseSearchPathValid, this is useless but harmless */
        activeSearchPath = baseSearchPath;
        activeCreationNamespace = baseCreationNamespace;
        activeTempCreationPending = baseTempCreationPending;
    }
}

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

Definition at line 3837 of file namespace.c.

References GUC_check_errdetail, list_free(), pfree(), pstrdup(), and SplitIdentifierString().

{
    char       *rawname;
    List       *namelist;

    /* Need a modifiable copy of string */
    rawname = pstrdup(*newval);

    /* Parse string into list of identifiers */
    if (!SplitIdentifierString(rawname, ',', &namelist))
    {
        /* syntax error in name list */
        GUC_check_errdetail("List syntax is invalid.");
        pfree(rawname);
        list_free(namelist);
        return false;
    }

    /*
     * We used to try to check that the named schemas exist, but there are
     * many valid use-cases for having search_path settings that include
     * schemas that don't exist; and often, we are not inside a transaction
     * here and so can't consult the system catalogs anyway.  So now, the only
     * requirement is syntactic validity of the identifier list.
     */

    pfree(rawname);
    list_free(namelist);

    return true;
}

void CheckSetNamespace ( Oid  oldNspOid,
Oid  nspOid,
Oid  classid,
Oid  objid 
)

Definition at line 2758 of file namespace.c.

References ereport, errcode(), errmsg(), ERROR, get_namespace_name(), getObjectDescriptionOids(), isAnyTempNamespace(), PG_TOAST_NAMESPACE, ProcedureRelationId, and RelationRelationId.

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

{
    if (oldNspOid == nspOid)
        ereport(ERROR,
                (classid == RelationRelationId ?
                 errcode(ERRCODE_DUPLICATE_TABLE) :
                 classid == ProcedureRelationId ?
                 errcode(ERRCODE_DUPLICATE_FUNCTION) :
                 errcode(ERRCODE_DUPLICATE_OBJECT),
                 errmsg("%s is already in schema \"%s\"",
                        getObjectDescriptionOids(classid, objid),
                        get_namespace_name(nspOid))));

    /* disallow renaming into or out of temp schemas */
    if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
            errmsg("cannot move objects into or out of temporary schemas")));

    /* same for TOAST schema */
    if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("cannot move objects into or out of TOAST schema")));
}

Oid CollationGetCollid ( const char *  collname  ) 

Definition at line 1918 of file namespace.c.

References COLLNAMEENCNSP, GetDatabaseEncoding(), GetSysCacheOid3, Int32GetDatum, lfirst_oid, myTempNamespace, ObjectIdGetDatum, OidIsValid, PointerGetDatum, and recomputeNamespacePath().

Referenced by CollationIsVisible().

{
    int32       dbencoding = GetDatabaseEncoding();
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);
        Oid         collid;

        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */

        /* Check for database-encoding-specific entry */
        collid = GetSysCacheOid3(COLLNAMEENCNSP,
                                 PointerGetDatum(collname),
                                 Int32GetDatum(dbencoding),
                                 ObjectIdGetDatum(namespaceId));
        if (OidIsValid(collid))
            return collid;

        /* Check for any-encoding entry */
        collid = GetSysCacheOid3(COLLNAMEENCNSP,
                                 PointerGetDatum(collname),
                                 Int32GetDatum(-1),
                                 ObjectIdGetDatum(namespaceId));
        if (OidIsValid(collid))
            return collid;
    }

    /* Not found in path */
    return InvalidOid;
}

bool CollationIsVisible ( Oid  collid  ) 

Definition at line 1961 of file namespace.c.

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

Referenced by generate_collation_name(), and pg_collation_is_visible().

{
    HeapTuple   colltup;
    Form_pg_collation collform;
    Oid         collnamespace;
    bool        visible;

    colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
    if (!HeapTupleIsValid(colltup))
        elog(ERROR, "cache lookup failed for collation %u", collid);
    collform = (Form_pg_collation) GETSTRUCT(colltup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    collnamespace = collform->collnamespace;
    if (collnamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, collnamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another conversion of the same name earlier in the path.
         * So we must do a slow check to see if this conversion would be found
         * by CollationGetCollid.
         */
        char       *collname = NameStr(collform->collname);

        visible = (CollationGetCollid(collname) == collid);
    }

    ReleaseSysCache(colltup);

    return visible;
}

Oid ConversionGetConid ( const char *  conname  ) 

Definition at line 2011 of file namespace.c.

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

Referenced by ConversionIsVisible().

{
    Oid         conid;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */

        conid = GetSysCacheOid2(CONNAMENSP,
                                PointerGetDatum(conname),
                                ObjectIdGetDatum(namespaceId));
        if (OidIsValid(conid))
            return conid;
    }

    /* Not found in path */
    return InvalidOid;
}

bool ConversionIsVisible ( Oid  conid  ) 

Definition at line 2043 of file namespace.c.

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

Referenced by pg_conversion_is_visible().

{
    HeapTuple   contup;
    Form_pg_conversion conform;
    Oid         connamespace;
    bool        visible;

    contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
    if (!HeapTupleIsValid(contup))
        elog(ERROR, "cache lookup failed for conversion %u", conid);
    conform = (Form_pg_conversion) GETSTRUCT(contup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    connamespace = conform->connamespace;
    if (connamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, connamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another conversion of the same name earlier in the path.
         * So we must do a slow check to see if this conversion would be found
         * by ConversionGetConid.
         */
        char       *conname = NameStr(conform->conname);

        visible = (ConversionGetConid(conname) == conid);
    }

    ReleaseSysCache(contup);

    return visible;
}

OverrideSearchPath* CopyOverrideSearchPath ( OverrideSearchPath path  ) 

Definition at line 3113 of file namespace.c.

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

Referenced by CopyCachedPlan().

{
    OverrideSearchPath *result;

    result = (OverrideSearchPath *) palloc(sizeof(OverrideSearchPath));
    result->schemas = list_copy(path->schemas);
    result->addCatalog = path->addCatalog;
    result->addTemp = path->addTemp;

    return result;
}

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

Definition at line 2599 of file namespace.c.

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

Referenced by FuncnameGetCandidates(), get_collation_oid(), get_conversion_oid(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), GetIndexOpClass(), LookupTypeName(), make_oper_cache_key(), OpClassCacheLookup(), OpernameGetCandidates(), OpernameGetOprid(), OpFamilyCacheLookup(), and QualifiedNameGetCreationNamespace().

{
    char       *catalogname;
    char       *schemaname = NULL;
    char       *objname = NULL;

    switch (list_length(names))
    {
        case 1:
            objname = strVal(linitial(names));
            break;
        case 2:
            schemaname = strVal(linitial(names));
            objname = strVal(lsecond(names));
            break;
        case 3:
            catalogname = strVal(linitial(names));
            schemaname = strVal(lsecond(names));
            objname = strVal(lthird(names));

            /*
             * We check the catalog name and then ignore it.
             */
            if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                  errmsg("cross-database references are not implemented: %s",
                         NameListToString(names))));
            break;
        default:
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                errmsg("improper qualified name (too many dotted names): %s",
                       NameListToString(names))));
            break;
    }

    *nspname_p = schemaname;
    *objname_p = objname;
}

List* fetch_search_path ( bool  includeImplicit  ) 

Definition at line 3945 of file namespace.c.

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

Referenced by AfterTriggerSetState(), CreateExtension(), current_schema(), and current_schemas().

{
    List       *result;

    recomputeNamespacePath();

    /*
     * If the temp namespace should be first, force it to exist.  This is so
     * that callers can trust the result to reflect the actual default
     * creation namespace.  It's a bit bogus to do this here, since
     * current_schema() is supposedly a stable function without side-effects,
     * but the alternatives seem worse.
     */
    if (activeTempCreationPending)
    {
        InitTempTableNamespace();
        recomputeNamespacePath();
    }

    result = list_copy(activeSearchPath);
    if (!includeImplicit)
    {
        while (result && linitial_oid(result) != activeCreationNamespace)
            result = list_delete_first(result);
    }

    return result;
}

int fetch_search_path_array ( Oid sarray,
int  sarray_len 
)

Definition at line 3985 of file namespace.c.

References lfirst_oid, myTempNamespace, and recomputeNamespacePath().

Referenced by make_oper_cache_key().

{
    int         count = 0;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        if (namespaceId == myTempNamespace)
            continue;           /* do not include temp namespace */

        if (count < sarray_len)
            sarray[count] = namespaceId;
        count++;
    }

    return count;
}

Oid FindDefaultConversionProc ( int32  for_encoding,
int32  to_encoding 
)

Definition at line 3390 of file namespace.c.

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

Referenced by pg_do_encoding_conversion(), and PrepareClientEncoding().

{
    Oid         proc;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */

        proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
        if (OidIsValid(proc))
            return proc;
    }

    /* Not found in path */
    return InvalidOid;
}

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

Definition at line 910 of file namespace.c.

References _FuncCandidateList::argnumbers, _FuncCandidateList::args, Assert, CStringGetDatum, DeconstructQualifiedName(), GETSTRUCT, HeapTupleGetOid, i, lfirst_oid, LookupExplicitNamespace(), MatchNamedCall(), Max, catclist::members, memcmp(), myTempNamespace, catclist::n_members, _FuncCandidateList::nargs, _FuncCandidateList::ndargs, _FuncCandidateList::next, NIL, NULL, _FuncCandidateList::nvargs, _FuncCandidateList::oid, OidIsValid, catclist::ordered, palloc(), _FuncCandidateList::pathpos, pfree(), PROCNAMEARGSNSP, recomputeNamespacePath(), ReleaseSysCacheList, SearchSysCacheList1, and catctup::tuple.

Referenced by func_get_detail(), FunctionIsVisible(), LookupFuncName(), regprocedurein(), regprocin(), and regprocout().

{
    FuncCandidateList resultList = NULL;
    bool        any_special = false;
    char       *schemaname;
    char       *funcname;
    Oid         namespaceId;
    CatCList   *catlist;
    int         i;

    /* check for caller error */
    Assert(nargs >= 0 || !(expand_variadic | expand_defaults));

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &funcname);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, false);
    }
    else
    {
        /* flag to indicate we need namespace search */
        namespaceId = InvalidOid;
        recomputeNamespacePath();
    }

    /* Search syscache by name only */
    catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname));

    for (i = 0; i < catlist->n_members; i++)
    {
        HeapTuple   proctup = &catlist->members[i]->tuple;
        Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
        int         pronargs = procform->pronargs;
        int         effective_nargs;
        int         pathpos = 0;
        bool        variadic;
        bool        use_defaults;
        Oid         va_elem_type;
        int        *argnumbers = NULL;
        FuncCandidateList newResult;

        if (OidIsValid(namespaceId))
        {
            /* Consider only procs in specified namespace */
            if (procform->pronamespace != namespaceId)
                continue;
        }
        else
        {
            /*
             * Consider only procs that are in the search path and are not in
             * the temp namespace.
             */
            ListCell   *nsp;

            foreach(nsp, activeSearchPath)
            {
                if (procform->pronamespace == lfirst_oid(nsp) &&
                    procform->pronamespace != myTempNamespace)
                    break;
                pathpos++;
            }
            if (nsp == NULL)
                continue;       /* proc is not in search path */
        }

        if (argnames != NIL)
        {
            /*
             * Call uses named or mixed notation
             *
             * Named or mixed notation can match a variadic function only if
             * expand_variadic is off; otherwise there is no way to match the
             * presumed-nameless parameters expanded from the variadic array.
             */
            if (OidIsValid(procform->provariadic) && expand_variadic)
                continue;
            va_elem_type = InvalidOid;
            variadic = false;

            /*
             * Check argument count.
             */
            Assert(nargs >= 0); /* -1 not supported with argnames */

            if (pronargs > nargs && expand_defaults)
            {
                /* Ignore if not enough default expressions */
                if (nargs + procform->pronargdefaults < pronargs)
                    continue;
                use_defaults = true;
            }
            else
                use_defaults = false;

            /* Ignore if it doesn't match requested argument count */
            if (pronargs != nargs && !use_defaults)
                continue;

            /* Check for argument name match, generate positional mapping */
            if (!MatchNamedCall(proctup, nargs, argnames,
                                &argnumbers))
                continue;

            /* Named argument matching is always "special" */
            any_special = true;
        }
        else
        {
            /*
             * Call uses positional notation
             *
             * Check if function is variadic, and get variadic element type if
             * so.  If expand_variadic is false, we should just ignore
             * variadic-ness.
             */
            if (pronargs <= nargs && expand_variadic)
            {
                va_elem_type = procform->provariadic;
                variadic = OidIsValid(va_elem_type);
                any_special |= variadic;
            }
            else
            {
                va_elem_type = InvalidOid;
                variadic = false;
            }

            /*
             * Check if function can match by using parameter defaults.
             */
            if (pronargs > nargs && expand_defaults)
            {
                /* Ignore if not enough default expressions */
                if (nargs + procform->pronargdefaults < pronargs)
                    continue;
                use_defaults = true;
                any_special = true;
            }
            else
                use_defaults = false;

            /* Ignore if it doesn't match requested argument count */
            if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
                continue;
        }

        /*
         * We must compute the effective argument list so that we can easily
         * compare it to earlier results.  We waste a palloc cycle if it gets
         * masked by an earlier result, but really that's a pretty infrequent
         * case so it's not worth worrying about.
         */
        effective_nargs = Max(pronargs, nargs);
        newResult = (FuncCandidateList)
            palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
                   + effective_nargs * sizeof(Oid));
        newResult->pathpos = pathpos;
        newResult->oid = HeapTupleGetOid(proctup);
        newResult->nargs = effective_nargs;
        newResult->argnumbers = argnumbers;
        if (argnumbers)
        {
            /* Re-order the argument types into call's logical order */
            Oid        *proargtypes = procform->proargtypes.values;
            int         i;

            for (i = 0; i < pronargs; i++)
                newResult->args[i] = proargtypes[argnumbers[i]];
        }
        else
        {
            /* Simple positional case, just copy proargtypes as-is */
            memcpy(newResult->args, procform->proargtypes.values,
                   pronargs * sizeof(Oid));
        }
        if (variadic)
        {
            int         i;

            newResult->nvargs = effective_nargs - pronargs + 1;
            /* Expand variadic argument into N copies of element type */
            for (i = pronargs - 1; i < effective_nargs; i++)
                newResult->args[i] = va_elem_type;
        }
        else
            newResult->nvargs = 0;
        newResult->ndargs = use_defaults ? pronargs - nargs : 0;

        /*
         * Does it have the same arguments as something we already accepted?
         * If so, decide what to do to avoid returning duplicate argument
         * lists.  We can skip this check for the single-namespace case if no
         * special (named, variadic or defaults) match has been made, since
         * then the unique index on pg_proc guarantees all the matches have
         * different argument lists.
         */
        if (resultList != NULL &&
            (any_special || !OidIsValid(namespaceId)))
        {
            /*
             * If we have an ordered list from SearchSysCacheList (the normal
             * case), then any conflicting proc must immediately adjoin this
             * one in the list, so we only need to look at the newest result
             * item.  If we have an unordered list, we have to scan the whole
             * result list.  Also, if either the current candidate or any
             * previous candidate is a special match, we can't assume that
             * conflicts are adjacent.
             *
             * We ignore defaulted arguments in deciding what is a match.
             */
            FuncCandidateList prevResult;

            if (catlist->ordered && !any_special)
            {
                /* ndargs must be 0 if !any_special */
                if (effective_nargs == resultList->nargs &&
                    memcmp(newResult->args,
                           resultList->args,
                           effective_nargs * sizeof(Oid)) == 0)
                    prevResult = resultList;
                else
                    prevResult = NULL;
            }
            else
            {
                int         cmp_nargs = newResult->nargs - newResult->ndargs;

                for (prevResult = resultList;
                     prevResult;
                     prevResult = prevResult->next)
                {
                    if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
                        memcmp(newResult->args,
                               prevResult->args,
                               cmp_nargs * sizeof(Oid)) == 0)
                        break;
                }
            }

            if (prevResult)
            {
                /*
                 * We have a match with a previous result.  Decide which one
                 * to keep, or mark it ambiguous if we can't decide.  The
                 * logic here is preference > 0 means prefer the old result,
                 * preference < 0 means prefer the new, preference = 0 means
                 * ambiguous.
                 */
                int         preference;

                if (pathpos != prevResult->pathpos)
                {
                    /*
                     * Prefer the one that's earlier in the search path.
                     */
                    preference = pathpos - prevResult->pathpos;
                }
                else if (variadic && prevResult->nvargs == 0)
                {
                    /*
                     * With variadic functions we could have, for example,
                     * both foo(numeric) and foo(variadic numeric[]) in the
                     * same namespace; if so we prefer the non-variadic match
                     * on efficiency grounds.
                     */
                    preference = 1;
                }
                else if (!variadic && prevResult->nvargs > 0)
                {
                    preference = -1;
                }
                else
                {
                    /*----------
                     * We can't decide.  This can happen with, for example,
                     * both foo(numeric, variadic numeric[]) and
                     * foo(variadic numeric[]) in the same namespace, or
                     * both foo(int) and foo (int, int default something)
                     * in the same namespace, or both foo(a int, b text)
                     * and foo(b text, a int) in the same namespace.
                     *----------
                     */
                    preference = 0;
                }

                if (preference > 0)
                {
                    /* keep previous result */
                    pfree(newResult);
                    continue;
                }
                else if (preference < 0)
                {
                    /* remove previous result from the list */
                    if (prevResult == resultList)
                        resultList = prevResult->next;
                    else
                    {
                        FuncCandidateList prevPrevResult;

                        for (prevPrevResult = resultList;
                             prevPrevResult;
                             prevPrevResult = prevPrevResult->next)
                        {
                            if (prevResult == prevPrevResult->next)
                            {
                                prevPrevResult->next = prevResult->next;
                                break;
                            }
                        }
                        Assert(prevPrevResult); /* assert we found it */
                    }
                    pfree(prevResult);
                    /* fall through to add newResult to list */
                }
                else
                {
                    /* mark old result as ambiguous, discard new */
                    prevResult->oid = InvalidOid;
                    pfree(newResult);
                    continue;
                }
            }
        }

        /*
         * Okay to add it to result list
         */
        newResult->next = resultList;
        resultList = newResult;
    }

    ReleaseSysCacheList(catlist);

    return resultList;
}

bool FunctionIsVisible ( Oid  funcid  ) 

Definition at line 1378 of file namespace.c.

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

Referenced by format_procedure_internal(), and pg_function_is_visible().

{
    HeapTuple   proctup;
    Form_pg_proc procform;
    Oid         pronamespace;
    bool        visible;

    proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    if (!HeapTupleIsValid(proctup))
        elog(ERROR, "cache lookup failed for function %u", funcid);
    procform = (Form_pg_proc) GETSTRUCT(proctup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    pronamespace = procform->pronamespace;
    if (pronamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, pronamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another proc of the same name and arguments earlier in
         * the path.  So we must do a slow check to see if this is the same
         * proc that would be found by FuncnameGetCandidates.
         */
        char       *proname = NameStr(procform->proname);
        int         nargs = procform->pronargs;
        FuncCandidateList clist;

        visible = false;

        clist = FuncnameGetCandidates(list_make1(makeString(proname)),
                                      nargs, NIL, false, false);

        for (; clist; clist = clist->next)
        {
            if (memcmp(clist->args, procform->proargtypes.values,
                       nargs * sizeof(Oid)) == 0)
            {
                /* Found the expected entry; is it the right proc? */
                visible = (clist->oid == funcid);
                break;
            }
        }
    }

    ReleaseSysCache(proctup);

    return visible;
}

Oid get_collation_oid ( List name,
bool  missing_ok 
)

Definition at line 3262 of file namespace.c.

References COLLNAMEENCNSP, DeconstructQualifiedName(), ereport, errcode(), errmsg(), ERROR, GetDatabaseEncoding(), GetDatabaseEncodingName(), GetSysCacheOid3, Int32GetDatum, lfirst_oid, LookupExplicitNamespace(), myTempNamespace, NameListToString(), ObjectIdGetDatum, OidIsValid, PointerGetDatum, and recomputeNamespacePath().

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

{
    char       *schemaname;
    char       *collation_name;
    int32       dbencoding = GetDatabaseEncoding();
    Oid         namespaceId;
    Oid         colloid;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(name, &schemaname, &collation_name);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
        if (missing_ok && !OidIsValid(namespaceId))
            return InvalidOid;

        /* first try for encoding-specific entry, then any-encoding */
        colloid = GetSysCacheOid3(COLLNAMEENCNSP,
                                  PointerGetDatum(collation_name),
                                  Int32GetDatum(dbencoding),
                                  ObjectIdGetDatum(namespaceId));
        if (OidIsValid(colloid))
            return colloid;
        colloid = GetSysCacheOid3(COLLNAMEENCNSP,
                                  PointerGetDatum(collation_name),
                                  Int32GetDatum(-1),
                                  ObjectIdGetDatum(namespaceId));
        if (OidIsValid(colloid))
            return colloid;
    }
    else
    {
        /* search for it in search path */
        recomputeNamespacePath();

        foreach(l, activeSearchPath)
        {
            namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            colloid = GetSysCacheOid3(COLLNAMEENCNSP,
                                      PointerGetDatum(collation_name),
                                      Int32GetDatum(dbencoding),
                                      ObjectIdGetDatum(namespaceId));
            if (OidIsValid(colloid))
                return colloid;
            colloid = GetSysCacheOid3(COLLNAMEENCNSP,
                                      PointerGetDatum(collation_name),
                                      Int32GetDatum(-1),
                                      ObjectIdGetDatum(namespaceId));
            if (OidIsValid(colloid))
                return colloid;
        }
    }

    /* Not found in path */
    if (!missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
                        NameListToString(name), GetDatabaseEncodingName())));
    return InvalidOid;
}

Oid get_conversion_oid ( List name,
bool  missing_ok 
)

Definition at line 3335 of file namespace.c.

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

Referenced by get_object_address().

{
    char       *schemaname;
    char       *conversion_name;
    Oid         namespaceId;
    Oid         conoid = InvalidOid;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(name, &schemaname, &conversion_name);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
        if (missing_ok && !OidIsValid(namespaceId))
            conoid = InvalidOid;
        else
            conoid = GetSysCacheOid2(CONNAMENSP,
                                     PointerGetDatum(conversion_name),
                                     ObjectIdGetDatum(namespaceId));
    }
    else
    {
        /* search for it in search path */
        recomputeNamespacePath();

        foreach(l, activeSearchPath)
        {
            namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            conoid = GetSysCacheOid2(CONNAMENSP,
                                     PointerGetDatum(conversion_name),
                                     ObjectIdGetDatum(namespaceId));
            if (OidIsValid(conoid))
                return conoid;
        }
    }

    /* Not found in path */
    if (!OidIsValid(conoid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("conversion \"%s\" does not exist",
                        NameListToString(name))));
    return conoid;
}

Oid get_namespace_oid ( const char *  nspname,
bool  missing_ok 
)
Oid get_ts_config_oid ( List names,
bool  missing_ok 
)

Definition at line 2469 of file namespace.c.

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

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

{
    char       *schemaname;
    char       *config_name;
    Oid         namespaceId;
    Oid         cfgoid = InvalidOid;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &config_name);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
        if (missing_ok && !OidIsValid(namespaceId))
            cfgoid = InvalidOid;
        else
            cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP,
                                     PointerGetDatum(config_name),
                                     ObjectIdGetDatum(namespaceId));
    }
    else
    {
        /* search for it in search path */
        recomputeNamespacePath();

        foreach(l, activeSearchPath)
        {
            namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP,
                                     PointerGetDatum(config_name),
                                     ObjectIdGetDatum(namespaceId));
            if (OidIsValid(cfgoid))
                break;
        }
    }

    if (!OidIsValid(cfgoid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("text search configuration \"%s\" does not exist",
                        NameListToString(names))));

    return cfgoid;
}

Oid get_ts_dict_oid ( List names,
bool  missing_ok 
)

Definition at line 2216 of file namespace.c.

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

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

{
    char       *schemaname;
    char       *dict_name;
    Oid         namespaceId;
    Oid         dictoid = InvalidOid;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &dict_name);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
        if (missing_ok && !OidIsValid(namespaceId))
            dictoid = InvalidOid;
        else
            dictoid = GetSysCacheOid2(TSDICTNAMENSP,
                                      PointerGetDatum(dict_name),
                                      ObjectIdGetDatum(namespaceId));
    }
    else
    {
        /* search for it in search path */
        recomputeNamespacePath();

        foreach(l, activeSearchPath)
        {
            namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            dictoid = GetSysCacheOid2(TSDICTNAMENSP,
                                      PointerGetDatum(dict_name),
                                      ObjectIdGetDatum(namespaceId));
            if (OidIsValid(dictoid))
                break;
        }
    }

    if (!OidIsValid(dictoid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("text search dictionary \"%s\" does not exist",
                        NameListToString(names))));

    return dictoid;
}

Oid get_ts_parser_oid ( List names,
bool  missing_ok 
)

Definition at line 2090 of file namespace.c.

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

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

{
    char       *schemaname;
    char       *parser_name;
    Oid         namespaceId;
    Oid         prsoid = InvalidOid;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &parser_name);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
        if (missing_ok && !OidIsValid(namespaceId))
            prsoid = InvalidOid;
        else
            prsoid = GetSysCacheOid2(TSPARSERNAMENSP,
                                     PointerGetDatum(parser_name),
                                     ObjectIdGetDatum(namespaceId));
    }
    else
    {
        /* search for it in search path */
        recomputeNamespacePath();

        foreach(l, activeSearchPath)
        {
            namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            prsoid = GetSysCacheOid2(TSPARSERNAMENSP,
                                     PointerGetDatum(parser_name),
                                     ObjectIdGetDatum(namespaceId));
            if (OidIsValid(prsoid))
                break;
        }
    }

    if (!OidIsValid(prsoid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("text search parser \"%s\" does not exist",
                        NameListToString(names))));

    return prsoid;
}

Oid get_ts_template_oid ( List names,
bool  missing_ok 
)

Definition at line 2343 of file namespace.c.

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

Referenced by DefineTSDictionary(), and get_object_address().

{
    char       *schemaname;
    char       *template_name;
    Oid         namespaceId;
    Oid         tmploid = InvalidOid;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &template_name);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
        if (missing_ok && !OidIsValid(namespaceId))
            tmploid = InvalidOid;
        else
            tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP,
                                      PointerGetDatum(template_name),
                                      ObjectIdGetDatum(namespaceId));
    }
    else
    {
        /* search for it in search path */
        recomputeNamespacePath();

        foreach(l, activeSearchPath)
        {
            namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP,
                                      PointerGetDatum(template_name),
                                      ObjectIdGetDatum(namespaceId));
            if (OidIsValid(tmploid))
                break;
        }
    }

    if (!OidIsValid(tmploid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("text search template \"%s\" does not exist",
                        NameListToString(names))));

    return tmploid;
}

OverrideSearchPath* GetOverrideSearchPath ( MemoryContext  context  ) 
int GetTempNamespaceBackendId ( Oid  namespaceId  ) 

Definition at line 3036 of file namespace.c.

References get_namespace_name(), and pfree().

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

{
    int         result;
    char       *nspname;

    /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
    nspname = get_namespace_name(namespaceId);
    if (!nspname)
        return InvalidBackendId;    /* no such namespace? */
    if (strncmp(nspname, "pg_temp_", 8) == 0)
        result = atoi(nspname + 8);
    else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
        result = atoi(nspname + 14);
    else
        result = InvalidBackendId;
    pfree(nspname);
    return result;
}

Oid GetTempToastNamespace ( void   ) 

Definition at line 3061 of file namespace.c.

References Assert, myTempToastNamespace, and OidIsValid.

Referenced by create_toast_table().

void InitializeSearchPath ( void   ) 

Definition at line 3887 of file namespace.c.

References activeCreationNamespace, activeTempCreationPending, baseCreationNamespace, baseSearchPathValid, baseTempCreationPending, CacheRegisterSyscacheCallback(), GetUserId(), IsBootstrapProcessingMode, list_make1_oid, MemoryContextSwitchTo(), NamespaceCallback(), NAMESPACEOID, namespaceUser, PG_CATALOG_NAMESPACE, and TopMemoryContext.

Referenced by InitPostgres().

{
    if (IsBootstrapProcessingMode())
    {
        /*
         * In bootstrap mode, the search path must be 'pg_catalog' so that
         * tables are created in the proper namespace; ignore the GUC setting.
         */
        MemoryContext oldcxt;

        oldcxt = MemoryContextSwitchTo(TopMemoryContext);
        baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
        MemoryContextSwitchTo(oldcxt);
        baseCreationNamespace = PG_CATALOG_NAMESPACE;
        baseTempCreationPending = false;
        baseSearchPathValid = true;
        namespaceUser = GetUserId();
        activeSearchPath = baseSearchPath;
        activeCreationNamespace = baseCreationNamespace;
        activeTempCreationPending = baseTempCreationPending;
    }
    else
    {
        /*
         * In normal mode, arrange for a callback on any syscache invalidation
         * of pg_namespace rows.
         */
        CacheRegisterSyscacheCallback(NAMESPACEOID,
                                      NamespaceCallback,
                                      (Datum) 0);
        /* Force search path to be recomputed on next use */
        baseSearchPathValid = false;
    }
}

static void InitTempTableNamespace ( void   )  [static]

Definition at line 3567 of file namespace.c.

References ACL_CREATE_TEMP, ACLCHECK_OK, Assert, AssertState, baseSearchPathValid, BOOTSTRAP_SUPERUSERID, CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, get_database_name(), get_namespace_oid(), GetCurrentSubTransactionId(), GetUserId(), InvalidSubTransactionId, MyBackendId, MyDatabaseId, myTempNamespace, myTempNamespaceSubID, myTempToastNamespace, NamespaceCreate(), OidIsValid, pg_database_aclcheck(), RecoveryInProgress(), RemoveTempRelations(), and snprintf().

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

{
    char        namespaceName[NAMEDATALEN];
    Oid         namespaceId;
    Oid         toastspaceId;

    Assert(!OidIsValid(myTempNamespace));

    /*
     * First, do permission check to see if we are authorized to make temp
     * tables.  We use a nonstandard error message here since "databasename:
     * permission denied" might be a tad cryptic.
     *
     * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
     * that's necessary since current user ID could change during the session.
     * But there's no need to make the namespace in the first place until a
     * temp table creation request is made by someone with appropriate rights.
     */
    if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
                             ACL_CREATE_TEMP) != ACLCHECK_OK)
        ereport(ERROR,
                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                 errmsg("permission denied to create temporary tables in database \"%s\"",
                        get_database_name(MyDatabaseId))));

    /*
     * Do not allow a Hot Standby slave session to make temp tables.  Aside
     * from problems with modifying the system catalogs, there is a naming
     * conflict: pg_temp_N belongs to the session with BackendId N on the
     * master, not to a slave session with the same BackendId.  We should not
     * be able to get here anyway due to XactReadOnly checks, but let's just
     * make real sure.  Note that this also backstops various operations that
     * allow XactReadOnly transactions to modify temp tables; they'd need
     * RecoveryInProgress checks if not for this.
     */
    if (RecoveryInProgress())
        ereport(ERROR,
                (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
                 errmsg("cannot create temporary tables during recovery")));

    snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);

    namespaceId = get_namespace_oid(namespaceName, true);
    if (!OidIsValid(namespaceId))
    {
        /*
         * First use of this temp namespace in this database; create it. The
         * temp namespaces are always owned by the superuser.  We leave their
         * permissions at default --- i.e., no access except to superuser ---
         * to ensure that unprivileged users can't peek at other backends'
         * temp tables.  This works because the places that access the temp
         * namespace for my own backend skip permissions checks on it.
         */
        namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
                                      true);
        /* Advance command counter to make namespace visible */
        CommandCounterIncrement();
    }
    else
    {
        /*
         * If the namespace already exists, clean it out (in case the former
         * owner crashed without doing so).
         */
        RemoveTempRelations(namespaceId);
    }

    /*
     * If the corresponding toast-table namespace doesn't exist yet, create
     * it. (We assume there is no need to clean it out if it does exist, since
     * dropping a parent table should make its toast table go away.)
     */
    snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
             MyBackendId);

    toastspaceId = get_namespace_oid(namespaceName, true);
    if (!OidIsValid(toastspaceId))
    {
        toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
                                       true);
        /* Advance command counter to make namespace visible */
        CommandCounterIncrement();
    }

    /*
     * Okay, we've prepared the temp namespace ... but it's not committed yet,
     * so all our work could be undone by transaction rollback.  Set flag for
     * AtEOXact_Namespace to know what to do.
     */
    myTempNamespace = namespaceId;
    myTempToastNamespace = toastspaceId;

    /* It should not be done already. */
    AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
    myTempNamespaceSubID = GetCurrentSubTransactionId();

    baseSearchPathValid = false;    /* need to rebuild list */
}

bool isAnyTempNamespace ( Oid  namespaceId  ) 

Definition at line 2997 of file namespace.c.

References get_namespace_name(), and pfree().

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

{
    bool        result;
    char       *nspname;

    /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
    nspname = get_namespace_name(namespaceId);
    if (!nspname)
        return false;           /* no such namespace? */
    result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
        (strncmp(nspname, "pg_toast_temp_", 14) == 0);
    pfree(nspname);
    return result;
}

bool isOtherTempNamespace ( Oid  namespaceId  ) 

Definition at line 3020 of file namespace.c.

References isAnyTempNamespace(), and isTempOrToastNamespace().

Referenced by pg_is_other_temp_schema().

{
    /* If it's my own temp namespace, say "false" */
    if (isTempOrToastNamespace(namespaceId))
        return false;
    /* Else, if it's any temp namespace, say "true" */
    return isAnyTempNamespace(namespaceId);
}

bool isTempNamespace ( Oid  namespaceId  ) 

Definition at line 2959 of file namespace.c.

References myTempNamespace, and OidIsValid.

Referenced by ExecCheckXactReadOnly(), pg_namespace_aclmask(), and ReindexDatabase().

{
    if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
        return true;
    return false;
}

bool isTempOrToastNamespace ( Oid  namespaceId  ) 
bool isTempToastNamespace ( Oid  namespaceId  ) 

Definition at line 2971 of file namespace.c.

References myTempToastNamespace, and OidIsValid.

Referenced by IsToastNamespace().

{
    if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
        return true;
    return false;
}

Oid LookupCreationNamespace ( const char *  nspname  ) 

Definition at line 2726 of file namespace.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_OK, get_namespace_oid(), GetUserId(), InitTempTableNamespace(), myTempNamespace, OidIsValid, and pg_namespace_aclcheck().

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

{
    Oid         namespaceId;
    AclResult   aclresult;

    /* check for pg_temp alias */
    if (strcmp(nspname, "pg_temp") == 0)
    {
        /* Initialize temp namespace if first time through */
        if (!OidIsValid(myTempNamespace))
            InitTempTableNamespace();
        return myTempNamespace;
    }

    namespaceId = get_namespace_oid(nspname, false);

    aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                       nspname);

    return namespaceId;
}

Oid LookupExplicitNamespace ( const char *  nspname,
bool  missing_ok 
)

Definition at line 2683 of file namespace.c.

References ACL_KIND_NAMESPACE, ACL_USAGE, aclcheck_error(), ACLCHECK_OK, get_namespace_oid(), GetUserId(), InvokeNamespaceSearchHook, myTempNamespace, OidIsValid, and pg_namespace_aclcheck().

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

{
    Oid         namespaceId;
    AclResult   aclresult;

    /* check for pg_temp alias */
    if (strcmp(nspname, "pg_temp") == 0)
    {
        if (OidIsValid(myTempNamespace))
            return myTempNamespace;

        /*
         * Since this is used only for looking up existing objects, there is
         * no point in trying to initialize the temp namespace here; and doing
         * so might create problems for some callers --- just fall through.
         */
    }

    namespaceId = get_namespace_oid(nspname, missing_ok);
    if (missing_ok && !OidIsValid(namespaceId))
        return InvalidOid;
    
    aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                       nspname);
    /* Schema search hook for this lookup */
    InvokeNamespaceSearchHook(namespaceId, true);

    return namespaceId;
}

Oid LookupNamespaceNoError ( const char *  nspname  ) 

Definition at line 2653 of file namespace.c.

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

Referenced by refnameRangeTblEntry().

{
    /* check for pg_temp alias */
    if (strcmp(nspname, "pg_temp") == 0)
    {
        if (OidIsValid(myTempNamespace))
        {
            InvokeNamespaceSearchHook(myTempNamespace, true);
            return myTempNamespace;
        }

        /*
         * Since this is used only for looking up existing objects, there is
         * no point in trying to initialize the temp namespace here; and doing
         * so might create problems for some callers. Just report "not found".
         */
        return InvalidOid;
    }

    return get_namespace_oid(nspname, true);
}

RangeVar* makeRangeVarFromNameList ( List names  ) 
static bool MatchNamedCall ( HeapTuple  proctup,
int  nargs,
List argnames,
int **  argnumbers 
) [static]

Definition at line 1270 of file namespace.c.

References Anum_pg_proc_proargnames, Assert, FUNC_PARAM_IN, FUNC_PARAM_INOUT, FUNC_PARAM_VARIADIC, get_func_arg_info(), GETSTRUCT, i, lfirst, list_length(), NIL, NULL, palloc(), PROCOID, and SysCacheGetAttr().

Referenced by FuncnameGetCandidates().

{
    Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
    int         pronargs = procform->pronargs;
    int         numposargs = nargs - list_length(argnames);
    int         pronallargs;
    Oid        *p_argtypes;
    char      **p_argnames;
    char       *p_argmodes;
    bool        arggiven[FUNC_MAX_ARGS];
    bool        isnull;
    int         ap;             /* call args position */
    int         pp;             /* proargs position */
    ListCell   *lc;

    Assert(argnames != NIL);
    Assert(numposargs >= 0);
    Assert(nargs <= pronargs);

    /* Ignore this function if its proargnames is null */
    (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
                           &isnull);
    if (isnull)
        return false;

    /* OK, let's extract the argument names and types */
    pronallargs = get_func_arg_info(proctup,
                                    &p_argtypes, &p_argnames, &p_argmodes);
    Assert(p_argnames != NULL);

    /* initialize state for matching */
    *argnumbers = (int *) palloc(pronargs * sizeof(int));
    memset(arggiven, false, pronargs * sizeof(bool));

    /* there are numposargs positional args before the named args */
    for (ap = 0; ap < numposargs; ap++)
    {
        (*argnumbers)[ap] = ap;
        arggiven[ap] = true;
    }

    /* now examine the named args */
    foreach(lc, argnames)
    {
        char       *argname = (char *) lfirst(lc);
        bool        found;
        int         i;

        pp = 0;
        found = false;
        for (i = 0; i < pronallargs; i++)
        {
            /* consider only input parameters */
            if (p_argmodes &&
                (p_argmodes[i] != FUNC_PARAM_IN &&
                 p_argmodes[i] != FUNC_PARAM_INOUT &&
                 p_argmodes[i] != FUNC_PARAM_VARIADIC))
                continue;
            if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
            {
                /* fail if argname matches a positional argument */
                if (arggiven[pp])
                    return false;
                arggiven[pp] = true;
                (*argnumbers)[ap] = pp;
                found = true;
                break;
            }
            /* increase pp only for input parameters */
            pp++;
        }
        /* if name isn't in proargnames, fail */
        if (!found)
            return false;
        ap++;
    }

    Assert(ap == nargs);        /* processed all actual parameters */

    /* Check for default arguments */
    if (nargs < pronargs)
    {
        int         first_arg_with_default = pronargs - procform->pronargdefaults;

        for (pp = numposargs; pp < pronargs; pp++)
        {
            if (arggiven[pp])
                continue;
            /* fail if arg not given and no default available */
            if (pp < first_arg_with_default)
                return false;
            (*argnumbers)[ap++] = pp;
        }
    }

    Assert(ap == pronargs);     /* processed all function parameters */

    return true;
}

char* NameListToQuotedString ( List names  ) 

Definition at line 2938 of file namespace.c.

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

{
    StringInfoData string;
    ListCell   *l;

    initStringInfo(&string);

    foreach(l, names)
    {
        if (l != list_head(names))
            appendStringInfoChar(&string, '.');
        appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
    }

    return string.data;
}

char* NameListToString ( List names  ) 

Definition at line 2904 of file namespace.c.

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

Referenced by AggregateCreate(), AlterFunction(), AlterTSConfiguration(), AlterTSDictionary(), check_object_ownership(), CreateConversionCommand(), CreateEventTrigger(), CreateProceduralLanguage(), CreateTrigger(), DeconstructQualifiedName(), defGetString(), DefineOperator(), DefineType(), does_not_exist_skipping(), dropOperators(), dropProcedures(), ExpandColumnRefStar(), findRangeSubOpclass(), findTypeAnalyzeFunction(), findTypeInputFunction(), findTypeOutputFunction(), findTypeTypmodinFunction(), findTypeTypmodoutFunction(), func_signature_string(), get_collation_oid(), get_conversion_oid(), get_object_address_attribute(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), GetIndexOpClass(), lookup_fdw_handler_func(), LookupAggNameTypeNames(), LookupTypeName(), makeRangeVarFromNameList(), op_signature_string(), OpClassCacheLookup(), OperatorCreate(), OpFamilyCacheLookup(), ParseFuncOrColumn(), plpgsql_post_column_ref(), RemoveObjects(), storeOperators(), storeProcedures(), and transformColumnRef().

{
    StringInfoData string;
    ListCell   *l;

    initStringInfo(&string);

    foreach(l, names)
    {
        Node       *name = (Node *) lfirst(l);

        if (l != list_head(names))
            appendStringInfoChar(&string, '.');

        if (IsA(name, String))
            appendStringInfoString(&string, strVal(name));
        else if (IsA(name, A_Star))
            appendStringInfoString(&string, "*");
        else
            elog(ERROR, "unexpected node type in name list: %d",
                 (int) nodeTag(name));
    }

    return string.data;
}

static void NamespaceCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
) [static]

Definition at line 3927 of file namespace.c.

References baseSearchPathValid.

Referenced by InitializeSearchPath().

{
    /* Force search path to be recomputed on next use */
    baseSearchPathValid = false;
}

bool OpclassIsVisible ( Oid  opcid  ) 

Definition at line 1788 of file namespace.c.

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

Referenced by get_opclass_name(), getObjectDescription(), and pg_opclass_is_visible().

{
    HeapTuple   opctup;
    Form_pg_opclass opcform;
    Oid         opcnamespace;
    bool        visible;

    opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
    if (!HeapTupleIsValid(opctup))
        elog(ERROR, "cache lookup failed for opclass %u", opcid);
    opcform = (Form_pg_opclass) GETSTRUCT(opctup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    opcnamespace = opcform->opcnamespace;
    if (opcnamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, opcnamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another opclass of the same name earlier in the path. So
         * we must do a slow check to see if this opclass would be found by
         * OpclassnameGetOpcid.
         */
        char       *opcname = NameStr(opcform->opcname);

        visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
    }

    ReleaseSysCache(opctup);

    return visible;
}

Oid OpclassnameGetOpcid ( Oid  amid,
const char *  opcname 
)

Definition at line 1755 of file namespace.c.

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

Referenced by GetIndexOpClass(), OpClassCacheLookup(), and OpclassIsVisible().

{
    Oid         opcid;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */

        opcid = GetSysCacheOid3(CLAAMNAMENSP,
                                ObjectIdGetDatum(amid),
                                PointerGetDatum(opcname),
                                ObjectIdGetDatum(namespaceId));
        if (OidIsValid(opcid))
            return opcid;
    }

    /* Not found in path */
    return InvalidOid;
}

bool OperatorIsVisible ( Oid  oprid  ) 

Definition at line 1702 of file namespace.c.

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

Referenced by format_operator_internal(), and pg_operator_is_visible().

{
    HeapTuple   oprtup;
    Form_pg_operator oprform;
    Oid         oprnamespace;
    bool        visible;

    oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
    if (!HeapTupleIsValid(oprtup))
        elog(ERROR, "cache lookup failed for operator %u", oprid);
    oprform = (Form_pg_operator) GETSTRUCT(oprtup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    oprnamespace = oprform->oprnamespace;
    if (oprnamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, oprnamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another operator of the same name and arguments earlier
         * in the path.  So we must do a slow check to see if this is the same
         * operator that would be found by OpernameGetOprId.
         */
        char       *oprname = NameStr(oprform->oprname);

        visible = (OpernameGetOprid(list_make1(makeString(oprname)),
                                    oprform->oprleft, oprform->oprright)
                   == oprid);
    }

    ReleaseSysCache(oprtup);

    return visible;
}

FuncCandidateList OpernameGetCandidates ( List names,
char  oprkind 
)

Definition at line 1545 of file namespace.c.

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

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

{
    FuncCandidateList resultList = NULL;
    char       *resultSpace = NULL;
    int         nextResult = 0;
    char       *schemaname;
    char       *opername;
    Oid         namespaceId;
    CatCList   *catlist;
    int         i;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &opername);

    if (schemaname)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname, false);
    }
    else
    {
        /* flag to indicate we need namespace search */
        namespaceId = InvalidOid;
        recomputeNamespacePath();
    }

    /* Search syscache by name only */
    catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));

    /*
     * In typical scenarios, most if not all of the operators found by the
     * catcache search will end up getting returned; and there can be quite a
     * few, for common operator names such as '=' or '+'.  To reduce the time
     * spent in palloc, we allocate the result space as an array large enough
     * to hold all the operators.  The original coding of this routine did a
     * separate palloc for each operator, but profiling revealed that the
     * pallocs used an unreasonably large fraction of parsing time.
     */
#define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))

    if (catlist->n_members > 0)
        resultSpace = palloc(catlist->n_members * SPACE_PER_OP);

    for (i = 0; i < catlist->n_members; i++)
    {
        HeapTuple   opertup = &catlist->members[i]->tuple;
        Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
        int         pathpos = 0;
        FuncCandidateList newResult;

        /* Ignore operators of wrong kind, if specific kind requested */
        if (oprkind && operform->oprkind != oprkind)
            continue;

        if (OidIsValid(namespaceId))
        {
            /* Consider only opers in specified namespace */
            if (operform->oprnamespace != namespaceId)
                continue;
            /* No need to check args, they must all be different */
        }
        else
        {
            /*
             * Consider only opers that are in the search path and are not in
             * the temp namespace.
             */
            ListCell   *nsp;

            foreach(nsp, activeSearchPath)
            {
                if (operform->oprnamespace == lfirst_oid(nsp) &&
                    operform->oprnamespace != myTempNamespace)
                    break;
                pathpos++;
            }
            if (nsp == NULL)
                continue;       /* oper is not in search path */

            /*
             * Okay, it's in the search path, but does it have the same
             * arguments as something we already accepted?  If so, keep only
             * the one that appears earlier in the search path.
             *
             * If we have an ordered list from SearchSysCacheList (the normal
             * case), then any conflicting oper must immediately adjoin this
             * one in the list, so we only need to look at the newest result
             * item.  If we have an unordered list, we have to scan the whole
             * result list.
             */
            if (resultList)
            {
                FuncCandidateList prevResult;

                if (catlist->ordered)
                {
                    if (operform->oprleft == resultList->args[0] &&
                        operform->oprright == resultList->args[1])
                        prevResult = resultList;
                    else
                        prevResult = NULL;
                }
                else
                {
                    for (prevResult = resultList;
                         prevResult;
                         prevResult = prevResult->next)
                    {
                        if (operform->oprleft == prevResult->args[0] &&
                            operform->oprright == prevResult->args[1])
                            break;
                    }
                }
                if (prevResult)
                {
                    /* We have a match with a previous result */
                    Assert(pathpos != prevResult->pathpos);
                    if (pathpos > prevResult->pathpos)
                        continue;       /* keep previous result */
                    /* replace previous result */
                    prevResult->pathpos = pathpos;
                    prevResult->oid = HeapTupleGetOid(opertup);
                    continue;   /* args are same, of course */
                }
            }
        }

        /*
         * Okay to add it to result list
         */
        newResult = (FuncCandidateList) (resultSpace + nextResult);
        nextResult += SPACE_PER_OP;

        newResult->pathpos = pathpos;
        newResult->oid = HeapTupleGetOid(opertup);
        newResult->nargs = 2;
        newResult->nvargs = 0;
        newResult->ndargs = 0;
        newResult->argnumbers = NULL;
        newResult->args[0] = operform->oprleft;
        newResult->args[1] = operform->oprright;
        newResult->next = resultList;
        resultList = newResult;
    }

    ReleaseSysCacheList(catlist);

    return resultList;
}

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

Definition at line 1448 of file namespace.c.

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

Referenced by binary_oper_exact(), left_oper(), LookupOperName(), OperatorIsVisible(), regoperatorin(), and right_oper().

{
    char       *schemaname;
    char       *opername;
    CatCList   *catlist;
    ListCell   *l;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, &opername);

    if (schemaname)
    {
        /* search only in exact schema given */
        Oid         namespaceId;
        HeapTuple   opertup;

        namespaceId = LookupExplicitNamespace(schemaname, false);
        opertup = SearchSysCache4(OPERNAMENSP,
                                  CStringGetDatum(opername),
                                  ObjectIdGetDatum(oprleft),
                                  ObjectIdGetDatum(oprright),
                                  ObjectIdGetDatum(namespaceId));
        if (HeapTupleIsValid(opertup))
        {
            Oid         result = HeapTupleGetOid(opertup);

            ReleaseSysCache(opertup);
            return result;
        }
        return InvalidOid;
    }

    /* Search syscache by name and argument types */
    catlist = SearchSysCacheList3(OPERNAMENSP,
                                  CStringGetDatum(opername),
                                  ObjectIdGetDatum(oprleft),
                                  ObjectIdGetDatum(oprright));

    if (catlist->n_members == 0)
    {
        /* no hope, fall out early */
        ReleaseSysCacheList(catlist);
        return InvalidOid;
    }

    /*
     * We have to find the list member that is first in the search path, if
     * there's more than one.  This doubly-nested loop looks ugly, but in
     * practice there should usually be few catlist members.
     */
    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);
        int         i;

        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */

        for (i = 0; i < catlist->n_members; i++)
        {
            HeapTuple   opertup = &catlist->members[i]->tuple;
            Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);

            if (operform->oprnamespace == namespaceId)
            {
                Oid         result = HeapTupleGetOid(opertup);

                ReleaseSysCacheList(catlist);
                return result;
            }
        }
    }

    ReleaseSysCacheList(catlist);
    return InvalidOid;
}

bool OpfamilyIsVisible ( Oid  opfid  ) 

Definition at line 1871 of file namespace.c.

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

Referenced by getOpFamilyDescription(), and pg_opfamily_is_visible().

{
    HeapTuple   opftup;
    Form_pg_opfamily opfform;
    Oid         opfnamespace;
    bool        visible;

    opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
    if (!HeapTupleIsValid(opftup))
        elog(ERROR, "cache lookup failed for opfamily %u", opfid);
    opfform = (Form_pg_opfamily) GETSTRUCT(opftup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    opfnamespace = opfform->opfnamespace;
    if (opfnamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, opfnamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another opfamily of the same name earlier in the path. So
         * we must do a slow check to see if this opfamily would be found by
         * OpfamilynameGetOpfid.
         */
        char       *opfname = NameStr(opfform->opfname);

        visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
    }

    ReleaseSysCache(opftup);

    return visible;
}

Oid OpfamilynameGetOpfid ( Oid  amid,
const char *  opfname 
)

Definition at line 1838 of file namespace.c.

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

Referenced by OpFamilyCacheLookup(), and OpfamilyIsVisible().

{
    Oid         opfid;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */

        opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP,
                                ObjectIdGetDatum(amid),
                                PointerGetDatum(opfname),
                                ObjectIdGetDatum(namespaceId));
        if (OidIsValid(opfid))
            return opfid;
    }

    /* Not found in path */
    return InvalidOid;
}

bool OverrideSearchPathMatchesCurrent ( OverrideSearchPath path  ) 

Definition at line 3129 of file namespace.c.

References OverrideSearchPath::addCatalog, OverrideSearchPath::addTemp, cur, CurrentMemoryContext, equal(), GetOverrideSearchPath(), list_free(), pfree(), and OverrideSearchPath::schemas.

Referenced by RevalidateCachedQuery().

{
    /* Easiest way to do this is GetOverrideSearchPath() and compare */
    bool        result;
    OverrideSearchPath *cur;

    cur = GetOverrideSearchPath(CurrentMemoryContext);
    if (path->addCatalog == cur->addCatalog &&
        path->addTemp == cur->addTemp &&
        equal(path->schemas, cur->schemas))
        result = true;
    else
        result = false;
    list_free(cur->schemas);
    pfree(cur);
    return result;
}

Datum pg_collation_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_conversion_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_function_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_is_other_temp_schema ( PG_FUNCTION_ARGS   ) 

Definition at line 4160 of file namespace.c.

References isOtherTempNamespace(), PG_GETARG_OID, and PG_RETURN_BOOL.

Datum pg_my_temp_schema ( PG_FUNCTION_ARGS   ) 

Definition at line 4154 of file namespace.c.

References myTempNamespace, and PG_RETURN_OID.

Datum pg_opclass_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_operator_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_opfamily_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_table_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_ts_config_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_ts_dict_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_ts_parser_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_ts_template_is_visible ( PG_FUNCTION_ARGS   ) 
Datum pg_type_is_visible ( PG_FUNCTION_ARGS   ) 
void PopOverrideSearchPath ( void   ) 

Definition at line 3224 of file namespace.c.

References activeCreationNamespace, activeTempCreationPending, baseCreationNamespace, baseTempCreationPending, OverrideStackEntry::creationNamespace, elog, ERROR, GetCurrentTransactionNestLevel(), linitial, list_delete_first(), list_free(), OverrideStackEntry::nestLevel, NIL, pfree(), and OverrideStackEntry::searchPath.

Referenced by CreateSchemaCommand().

{
    OverrideStackEntry *entry;

    /* Sanity checks. */
    if (overrideStack == NIL)
        elog(ERROR, "bogus PopOverrideSearchPath call");
    entry = (OverrideStackEntry *) linitial(overrideStack);
    if (entry->nestLevel != GetCurrentTransactionNestLevel())
        elog(ERROR, "bogus PopOverrideSearchPath call");

    /* Pop the stack and free storage. */
    overrideStack = list_delete_first(overrideStack);
    list_free(entry->searchPath);
    pfree(entry);

    /* Activate the next level down. */
    if (overrideStack)
    {
        entry = (OverrideStackEntry *) linitial(overrideStack);
        activeSearchPath = entry->searchPath;
        activeCreationNamespace = entry->creationNamespace;
        activeTempCreationPending = false;      /* XXX is this OK? */
    }
    else
    {
        /* If not baseSearchPathValid, this is useless but harmless */
        activeSearchPath = baseSearchPath;
        activeCreationNamespace = baseCreationNamespace;
        activeTempCreationPending = baseTempCreationPending;
    }
}

void PushOverrideSearchPath ( OverrideSearchPath newpath  ) 

Definition at line 3165 of file namespace.c.

References activeCreationNamespace, activeTempCreationPending, OverrideSearchPath::addCatalog, OverrideSearchPath::addTemp, OverrideStackEntry::creationNamespace, GetCurrentTransactionNestLevel(), lcons(), lcons_oid(), linitial_oid, list_copy(), MemoryContextSwitchTo(), myTempNamespace, OverrideStackEntry::nestLevel, NIL, OidIsValid, palloc(), PG_CATALOG_NAMESPACE, OverrideSearchPath::schemas, OverrideStackEntry::searchPath, and TopMemoryContext.

Referenced by CreateSchemaCommand().

{
    OverrideStackEntry *entry;
    List       *oidlist;
    Oid         firstNS;
    MemoryContext oldcxt;

    /*
     * Copy the list for safekeeping, and insert implicitly-searched
     * namespaces as needed.  This code should track recomputeNamespacePath.
     */
    oldcxt = MemoryContextSwitchTo(TopMemoryContext);

    oidlist = list_copy(newpath->schemas);

    /*
     * Remember the first member of the explicit list.
     */
    if (oidlist == NIL)
        firstNS = InvalidOid;
    else
        firstNS = linitial_oid(oidlist);

    /*
     * Add any implicitly-searched namespaces to the list.  Note these go on
     * the front, not the back; also notice that we do not check USAGE
     * permissions for these.
     */
    if (newpath->addCatalog)
        oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);

    if (newpath->addTemp && OidIsValid(myTempNamespace))
        oidlist = lcons_oid(myTempNamespace, oidlist);

    /*
     * Build the new stack entry, then insert it at the head of the list.
     */
    entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
    entry->searchPath = oidlist;
    entry->creationNamespace = firstNS;
    entry->nestLevel = GetCurrentTransactionNestLevel();

    overrideStack = lcons(entry, overrideStack);

    /* And make it active. */
    activeSearchPath = entry->searchPath;
    activeCreationNamespace = entry->creationNamespace;
    activeTempCreationPending = false;  /* XXX is this OK? */

    MemoryContextSwitchTo(oldcxt);
}

Oid QualifiedNameGetCreationNamespace ( List names,
char **  objname_p 
)

Definition at line 2797 of file namespace.c.

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

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

{
    char       *schemaname;
    Oid         namespaceId;

    /* deconstruct the name list */
    DeconstructQualifiedName(names, &schemaname, objname_p);

    if (schemaname)
    {
        /* check for pg_temp alias */
        if (strcmp(schemaname, "pg_temp") == 0)
        {
            /* Initialize temp namespace if first time through */
            if (!OidIsValid(myTempNamespace))
                InitTempTableNamespace();
            return myTempNamespace;
        }
        /* use exact schema given */
        namespaceId = get_namespace_oid(schemaname, false);
        /* we do not check for USAGE rights here! */
    }
    else
    {
        /* use the default creation namespace */
        recomputeNamespacePath();
        if (activeTempCreationPending)
        {
            /* Need to initialize temp namespace */
            InitTempTableNamespace();
            return myTempNamespace;
        }
        namespaceId = activeCreationNamespace;
        if (!OidIsValid(namespaceId))
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_SCHEMA),
                     errmsg("no schema has been selected to create in")));
    }

    return namespaceId;
}

void RangeVarAdjustRelationPersistence ( RangeVar newRelation,
Oid  nspid 
)

Definition at line 626 of file namespace.c.

References ereport, errcode(), errmsg(), ERROR, isAnyTempNamespace(), isTempOrToastNamespace(), RangeVar::relpersistence, RELPERSISTENCE_PERMANENT, and RELPERSISTENCE_TEMP.

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

{
    switch (newRelation->relpersistence)
    {
        case RELPERSISTENCE_TEMP:
            if (!isTempOrToastNamespace(nspid))
            {
                if (isAnyTempNamespace(nspid))
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                             errmsg("cannot create relations in temporary schemas of other sessions")));
                else
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                             errmsg("cannot create temporary relation in non-temporary schema")));
            }
            break;
        case RELPERSISTENCE_PERMANENT:
            if (isTempOrToastNamespace(nspid))
                newRelation->relpersistence = RELPERSISTENCE_TEMP;
            else if (isAnyTempNamespace(nspid))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                         errmsg("cannot create relations in temporary schemas of other sessions")));
            break;
        default:
            if (isAnyTempNamespace(nspid))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                         errmsg("only temporary relations may be created in temporary schemas")));
    }
}

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

Definition at line 519 of file namespace.c.

References AccessShareLock, ACL_CREATE, ACL_KIND_CLASS, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, Assert, RangeVar::catalogname, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_namespace_name(), get_relname_relid(), GetUserId(), IsBootstrapProcessingMode, LockDatabaseObject(), LockRelationOid(), MyDatabaseId, NamespaceRelationId, NoLock, NULL, OidIsValid, pg_class_ownercheck(), pg_namespace_aclcheck(), RangeVarAdjustRelationPersistence(), RangeVarGetCreationNamespace(), RangeVar::relname, RangeVar::schemaname, SharedInvalidMessageCounter, UnlockDatabaseObject(), and UnlockRelationOid().

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

{
    uint64      inval_count;
    Oid         relid;
    Oid         oldrelid = InvalidOid;
    Oid         nspid;
    Oid         oldnspid = InvalidOid;
    bool        retry = false;

    /*
     * We check the catalog name and then ignore it.
     */
    if (relation->catalogname)
    {
        if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
                            relation->catalogname, relation->schemaname,
                            relation->relname)));
    }

    /*
     * As in RangeVarGetRelidExtended(), we guard against concurrent DDL
     * operations by tracking whether any invalidation messages are processed
     * while we're doing the name lookups and acquiring locks.  See comments
     * in that function for a more detailed explanation of this logic.
     */
    for (;;)
    {
        AclResult   aclresult;

        inval_count = SharedInvalidMessageCounter;

        /* Look up creation namespace and check for existing relation. */
        nspid = RangeVarGetCreationNamespace(relation);
        Assert(OidIsValid(nspid));
        if (existing_relation_id != NULL)
            relid = get_relname_relid(relation->relname, nspid);
        else
            relid = InvalidOid;

        /*
         * In bootstrap processing mode, we don't bother with permissions or
         * locking.  Permissions might not be working yet, and locking is
         * unnecessary.
         */
        if (IsBootstrapProcessingMode())
            break;

        /* Check namespace permissions. */
        aclresult = pg_namespace_aclcheck(nspid, GetUserId(), ACL_CREATE);
        if (aclresult != ACLCHECK_OK)
            aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                           get_namespace_name(nspid));

        if (retry)
        {
            /* If nothing changed, we're done. */
            if (relid == oldrelid && nspid == oldnspid)
                break;
            /* If creation namespace has changed, give up old lock. */
            if (nspid != oldnspid)
                UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
                                     AccessShareLock);
            /* If name points to something different, give up old lock. */
            if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
                UnlockRelationOid(oldrelid, lockmode);
        }

        /* Lock namespace. */
        if (nspid != oldnspid)
            LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);

        /* Lock relation, if required if and we have permission. */
        if (lockmode != NoLock && OidIsValid(relid))
        {
            if (!pg_class_ownercheck(relid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
                               relation->relname);
            if (relid != oldrelid)
                LockRelationOid(relid, lockmode);
        }

        /* If no invalidation message were processed, we're done! */
        if (inval_count == SharedInvalidMessageCounter)
            break;

        /* Something may have changed, so recheck our work. */
        retry = true;
        oldrelid = relid;
        oldnspid = nspid;
    }

    RangeVarAdjustRelationPersistence(relation, nspid);
    if (existing_relation_id != NULL)
        *existing_relation_id = relid;
    return nspid;
}

Oid RangeVarGetCreationNamespace ( const RangeVar newRelation  ) 

Definition at line 432 of file namespace.c.

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

Referenced by RangeVarGetAndCheckCreationNamespace(), and transformColumnDefinition().

{
    Oid         namespaceId;

    /*
     * We check the catalog name and then ignore it.
     */
    if (newRelation->catalogname)
    {
        if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
                            newRelation->catalogname, newRelation->schemaname,
                            newRelation->relname)));
    }

    if (newRelation->schemaname)
    {
        /* check for pg_temp alias */
        if (strcmp(newRelation->schemaname, "pg_temp") == 0)
        {
            /* Initialize temp namespace if first time through */
            if (!OidIsValid(myTempNamespace))
                InitTempTableNamespace();
            return myTempNamespace;
        }
        /* use exact schema given */
        namespaceId = get_namespace_oid(newRelation->schemaname, false);
        /* we do not check for USAGE rights here! */
    }
    else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
    {
        /* Initialize temp namespace if first time through */
        if (!OidIsValid(myTempNamespace))
            InitTempTableNamespace();
        return myTempNamespace;
    }
    else
    {
        /* use the default creation namespace */
        recomputeNamespacePath();
        if (activeTempCreationPending)
        {
            /* Need to initialize temp namespace */
            InitTempTableNamespace();
            return myTempNamespace;
        }
        namespaceId = activeCreationNamespace;
        if (!OidIsValid(namespaceId))
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_SCHEMA),
                     errmsg("no schema has been selected to create in")));
    }

    /* Note: callers will check for CREATE rights when appropriate */

    return namespaceId;
}

Oid RangeVarGetRelidExtended ( const RangeVar relation,
LOCKMODE  lockmode,
bool  missing_ok,
bool  nowait,
RangeVarGetRelidCallback  callback,
void *  callback_arg 
)

Definition at line 230 of file namespace.c.

References AcceptInvalidationMessages(), callback(), RangeVar::catalogname, ConditionalLockRelationOid(), ereport, errcode(), errmsg(), ERROR, get_database_name(), get_relname_relid(), LockRelationOid(), LookupExplicitNamespace(), MyDatabaseId, myTempNamespace, NoLock, OidIsValid, RangeVar::relname, RelnameGetRelid(), RangeVar::relpersistence, RELPERSISTENCE_TEMP, RangeVar::schemaname, SharedInvalidMessageCounter, and UnlockRelationOid().

Referenced by AlterTableLookupRelation(), AlterTableNamespace(), cluster(), ExecRefreshMatView(), LockTableCommand(), ReindexIndex(), ReindexTable(), RemoveRelations(), renameatt(), RenameConstraint(), RenameRelation(), RenameRewriteRule(), and renametrig().

{
    uint64      inval_count;
    Oid         relId;
    Oid         oldRelId = InvalidOid;
    bool        retry = false;

    /*
     * We check the catalog name and then ignore it.
     */
    if (relation->catalogname)
    {
        if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
                            relation->catalogname, relation->schemaname,
                            relation->relname)));
    }

    /*
     * DDL operations can change the results of a name lookup.  Since all such
     * operations will generate invalidation messages, we keep track of
     * whether any such messages show up while we're performing the operation,
     * and retry until either (1) no more invalidation messages show up or (2)
     * the answer doesn't change.
     *
     * But if lockmode = NoLock, then we assume that either the caller is OK
     * with the answer changing under them, or that they already hold some
     * appropriate lock, and therefore return the first answer we get without
     * checking for invalidation messages.  Also, if the requested lock is
     * already held, no LockRelationOid will not AcceptInvalidationMessages,
     * so we may fail to notice a change.  We could protect against that case
     * by calling AcceptInvalidationMessages() before beginning this loop, but
     * that would add a significant amount overhead, so for now we don't.
     */
    for (;;)
    {
        /*
         * Remember this value, so that, after looking up the relation name
         * and locking its OID, we can check whether any invalidation messages
         * have been processed that might require a do-over.
         */
        inval_count = SharedInvalidMessageCounter;

        /*
         * Some non-default relpersistence value may have been specified.  The
         * parser never generates such a RangeVar in simple DML, but it can
         * happen in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY
         * KEY)".  Such a command will generate an added CREATE INDEX
         * operation, which must be careful to find the temp table, even when
         * pg_temp is not first in the search path.
         */
        if (relation->relpersistence == RELPERSISTENCE_TEMP)
        {
            if (!OidIsValid(myTempNamespace))
                relId = InvalidOid;     /* this probably can't happen? */
            else
            {
                if (relation->schemaname)
                {
                    Oid         namespaceId;

                    namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
                    /*
                     *  For missing_ok, allow a non-existant schema name to
                     *  return InvalidOid.
                     */
                    if (namespaceId != myTempNamespace)
                        ereport(ERROR,
                                (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                                 errmsg("temporary tables cannot specify a schema name")));
                }

                relId = get_relname_relid(relation->relname, myTempNamespace);
            }
        }
        else if (relation->schemaname)
        {
            Oid         namespaceId;

            /* use exact schema given */
            namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
            if (missing_ok && !OidIsValid(namespaceId))
                relId = InvalidOid;
            else
                relId = get_relname_relid(relation->relname, namespaceId);
        }
        else
        {
            /* search the namespace path */
            relId = RelnameGetRelid(relation->relname);
        }

        /*
         * Invoke caller-supplied callback, if any.
         *
         * This callback is a good place to check permissions: we haven't
         * taken the table lock yet (and it's really best to check permissions
         * before locking anything!), but we've gotten far enough to know what
         * OID we think we should lock.  Of course, concurrent DDL might
         * change things while we're waiting for the lock, but in that case
         * the callback will be invoked again for the new OID.
         */
        if (callback)
            callback(relation, relId, oldRelId, callback_arg);

        /*
         * If no lock requested, we assume the caller knows what they're
         * doing.  They should have already acquired a heavyweight lock on
         * this relation earlier in the processing of this same statement, so
         * it wouldn't be appropriate to AcceptInvalidationMessages() here, as
         * that might pull the rug out from under them.
         */
        if (lockmode == NoLock)
            break;

        /*
         * If, upon retry, we get back the same OID we did last time, then the
         * invalidation messages we processed did not change the final answer.
         * So we're done.
         *
         * If we got a different OID, we've locked the relation that used to
         * have this name rather than the one that does now.  So release the
         * lock.
         */
        if (retry)
        {
            if (relId == oldRelId)
                break;
            if (OidIsValid(oldRelId))
                UnlockRelationOid(oldRelId, lockmode);
        }

        /*
         * Lock relation.  This will also accept any pending invalidation
         * messages.  If we got back InvalidOid, indicating not found, then
         * there's nothing to lock, but we accept invalidation messages
         * anyway, to flush any negative catcache entries that may be
         * lingering.
         */
        if (!OidIsValid(relId))
            AcceptInvalidationMessages();
        else if (!nowait)
            LockRelationOid(relId, lockmode);
        else if (!ConditionalLockRelationOid(relId, lockmode))
        {
            if (relation->schemaname)
                ereport(ERROR,
                        (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
                         errmsg("could not obtain lock on relation \"%s.%s\"",
                                relation->schemaname, relation->relname)));
            else
                ereport(ERROR,
                        (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
                         errmsg("could not obtain lock on relation \"%s\"",
                                relation->relname)));
        }

        /*
         * If no invalidation message were processed, we're done!
         */
        if (inval_count == SharedInvalidMessageCounter)
            break;

        /*
         * Something may have changed.  Let's repeat the name lookup, to make
         * sure this name still references the same relation it did
         * previously.
         */
        retry = true;
        oldRelId = relId;
    }

    if (!OidIsValid(relId) && !missing_ok)
    {
        if (relation->schemaname)
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_TABLE),
                     errmsg("relation \"%s.%s\" does not exist",
                            relation->schemaname, relation->relname)));
        else
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_TABLE),
                     errmsg("relation \"%s\" does not exist",
                            relation->relname)));
    }
    return relId;
}

static void recomputeNamespacePath ( void   )  [static]

Definition at line 3417 of file namespace.c.

References ACL_USAGE, ACLCHECK_OK, activeCreationNamespace, activeTempCreationPending, AUTHOID, baseCreationNamespace, baseSearchPathValid, baseTempCreationPending, elog, ERROR, get_namespace_oid(), GETSTRUCT, GetUserId(), HeapTupleIsValid, InvokeNamespaceSearchHook, lappend_oid(), lcons_oid(), lfirst, linitial_oid, list_copy(), list_free(), list_member_oid(), MemoryContextSwitchTo(), myTempNamespace, namespace_search_path, namespaceUser, NameStr, NIL, ObjectIdGetDatum, OidIsValid, pfree(), PG_CATALOG_NAMESPACE, pg_namespace_aclcheck(), pstrdup(), ReleaseSysCache(), SearchSysCache1, SplitIdentifierString(), and TopMemoryContext.

Referenced by CollationGetCollid(), CollationIsVisible(), ConversionGetConid(), ConversionIsVisible(), fetch_search_path(), fetch_search_path_array(), FindDefaultConversionProc(), FuncnameGetCandidates(), FunctionIsVisible(), get_collation_oid(), get_conversion_oid(), get_ts_config_oid(), get_ts_dict_oid(), get_ts_parser_oid(), get_ts_template_oid(), GetOverrideSearchPath(), OpclassIsVisible(), OpclassnameGetOpcid(), OperatorIsVisible(), OpernameGetCandidates(), OpernameGetOprid(), OpfamilyIsVisible(), OpfamilynameGetOpfid(), QualifiedNameGetCreationNamespace(), RangeVarGetCreationNamespace(), RelationIsVisible(), RelnameGetRelid(), TSConfigIsVisible(), TSDictionaryIsVisible(), TSParserIsVisible(), TSTemplateIsVisible(), TypeIsVisible(), and TypenameGetTypid().

{
    Oid         roleid = GetUserId();
    char       *rawname;
    List       *namelist;
    List       *oidlist;
    List       *newpath;
    ListCell   *l;
    bool        temp_missing;
    Oid         firstNS;
    MemoryContext oldcxt;

    /* Do nothing if an override search spec is active. */
    if (overrideStack)
        return;

    /* Do nothing if path is already valid. */
    if (baseSearchPathValid && namespaceUser == roleid)
        return;

    /* Need a modifiable copy of namespace_search_path string */
    rawname = pstrdup(namespace_search_path);

    /* Parse string into list of identifiers */
    if (!SplitIdentifierString(rawname, ',', &namelist))
    {
        /* syntax error in name list */
        /* this should not happen if GUC checked check_search_path */
        elog(ERROR, "invalid list syntax");
    }

    /*
     * Convert the list of names to a list of OIDs.  If any names are not
     * recognizable or we don't have read access, just leave them out of the
     * list.  (We can't raise an error, since the search_path setting has
     * already been accepted.)  Don't make duplicate entries, either.
     */
    oidlist = NIL;
    temp_missing = false;
    foreach(l, namelist)
    {
        char       *curname = (char *) lfirst(l);
        Oid         namespaceId;

        if (strcmp(curname, "$user") == 0)
        {
            /* $user --- substitute namespace matching user name, if any */
            HeapTuple   tuple;

            tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
            if (HeapTupleIsValid(tuple))
            {
                char       *rname;

                rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
                namespaceId = get_namespace_oid(rname, true);
                ReleaseSysCache(tuple);
                if (OidIsValid(namespaceId) &&
                    !list_member_oid(oidlist, namespaceId) &&
                    pg_namespace_aclcheck(namespaceId, roleid,
                                          ACL_USAGE) == ACLCHECK_OK &&
                    InvokeNamespaceSearchHook(namespaceId, false))
                    oidlist = lappend_oid(oidlist, namespaceId);
            }
        }
        else if (strcmp(curname, "pg_temp") == 0)
        {
            /* pg_temp --- substitute temp namespace, if any */
            if (OidIsValid(myTempNamespace))
            {
                if (!list_member_oid(oidlist, myTempNamespace) &&
                    InvokeNamespaceSearchHook(myTempNamespace, false))
                    oidlist = lappend_oid(oidlist, myTempNamespace);
            }
            else
            {
                /* If it ought to be the creation namespace, set flag */
                if (oidlist == NIL)
                    temp_missing = true;
            }
        }
        else
        {
            /* normal namespace reference */
            namespaceId = get_namespace_oid(curname, true);
            if (OidIsValid(namespaceId) &&
                !list_member_oid(oidlist, namespaceId) &&
                pg_namespace_aclcheck(namespaceId, roleid,
                                      ACL_USAGE) == ACLCHECK_OK &&
                InvokeNamespaceSearchHook(namespaceId, false))
                oidlist = lappend_oid(oidlist, namespaceId);
        }
    }

    /*
     * Remember the first member of the explicit list.  (Note: this is
     * nominally wrong if temp_missing, but we need it anyway to distinguish
     * explicit from implicit mention of pg_catalog.)
     */
    if (oidlist == NIL)
        firstNS = InvalidOid;
    else
        firstNS = linitial_oid(oidlist);

    /*
     * Add any implicitly-searched namespaces to the list.  Note these go on
     * the front, not the back; also notice that we do not check USAGE
     * permissions for these.
     */
    if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
        oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);

    if (OidIsValid(myTempNamespace) &&
        !list_member_oid(oidlist, myTempNamespace))
        oidlist = lcons_oid(myTempNamespace, oidlist);

    /*
     * Now that we've successfully built the new list of namespace OIDs, save
     * it in permanent storage.
     */
    oldcxt = MemoryContextSwitchTo(TopMemoryContext);
    newpath = list_copy(oidlist);
    MemoryContextSwitchTo(oldcxt);

    /* Now safe to assign to state variables. */
    list_free(baseSearchPath);
    baseSearchPath = newpath;
    baseCreationNamespace = firstNS;
    baseTempCreationPending = temp_missing;

    /* Mark the path valid. */
    baseSearchPathValid = true;
    namespaceUser = roleid;

    /* And make it active. */
    activeSearchPath = baseSearchPath;
    activeCreationNamespace = baseCreationNamespace;
    activeTempCreationPending = baseTempCreationPending;

    /* Clean up. */
    pfree(rawname);
    list_free(namelist);
    list_free(oidlist);
}

bool RelationIsVisible ( Oid  relid  ) 

Definition at line 693 of file namespace.c.

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

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

{
    HeapTuple   reltup;
    Form_pg_class relform;
    Oid         relnamespace;
    bool        visible;

    reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    if (!HeapTupleIsValid(reltup))
        elog(ERROR, "cache lookup failed for relation %u", relid);
    relform = (Form_pg_class) GETSTRUCT(reltup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    relnamespace = relform->relnamespace;
    if (relnamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, relnamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another relation of the same name earlier in the path. So
         * we must do a slow check for conflicting relations.
         */
        char       *relname = NameStr(relform->relname);
        ListCell   *l;

        visible = false;
        foreach(l, activeSearchPath)
        {
            Oid         namespaceId = lfirst_oid(l);

            if (namespaceId == relnamespace)
            {
                /* Found it first in path */
                visible = true;
                break;
            }
            if (OidIsValid(get_relname_relid(relname, namespaceId)))
            {
                /* Found something else first in path */
                break;
            }
        }
    }

    ReleaseSysCache(reltup);

    return visible;
}

Oid RelnameGetRelid ( const char *  relname  ) 

Definition at line 665 of file namespace.c.

References get_relname_relid(), lfirst_oid, OidIsValid, and recomputeNamespacePath().

Referenced by plpgsql_parse_cwordtype(), plpgsql_parse_wordrowtype(), and RangeVarGetRelidExtended().

{
    Oid         relid;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        relid = get_relname_relid(relname, namespaceId);
        if (OidIsValid(relid))
            return relid;
    }

    /* Not found in path */
    return InvalidOid;
}

static void RemoveTempRelations ( Oid  tempNamespaceId  )  [static]

Definition at line 3785 of file namespace.c.

References deleteWhatDependsOn().

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

{
    ObjectAddress object;

    /*
     * We want to get rid of everything in the target namespace, but not the
     * namespace itself (deleting it only to recreate it later would be a
     * waste of cycles).  We do this by finding everything that has a
     * dependency on the namespace.
     */
    object.classId = NamespaceRelationId;
    object.objectId = tempNamespaceId;
    object.objectSubId = 0;

    deleteWhatDependsOn(&object, false);
}

static void RemoveTempRelationsCallback ( int  code,
Datum  arg 
) [static]
void ResetTempTableNamespace ( void   ) 
bool TSConfigIsVisible ( Oid  cfgid  ) 

Definition at line 2527 of file namespace.c.

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

Referenced by pg_ts_config_is_visible(), and regconfigout().

{
    HeapTuple   tup;
    Form_pg_ts_config form;
    Oid         namespace;
    bool        visible;

    tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "cache lookup failed for text search configuration %u",
             cfgid);
    form = (Form_pg_ts_config) GETSTRUCT(tup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    namespace = form->cfgnamespace;
    if (namespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, namespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another configuration of the same name earlier in the
         * path. So we must do a slow check for conflicting configurations.
         */
        char       *name = NameStr(form->cfgname);
        ListCell   *l;

        visible = false;
        foreach(l, activeSearchPath)
        {
            Oid         namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            if (namespaceId == namespace)
            {
                /* Found it first in path */
                visible = true;
                break;
            }
            if (SearchSysCacheExists2(TSCONFIGNAMENSP,
                                      PointerGetDatum(name),
                                      ObjectIdGetDatum(namespaceId)))
            {
                /* Found something else first in path */
                break;
            }
        }
    }

    ReleaseSysCache(tup);

    return visible;
}

bool TSDictionaryIsVisible ( Oid  dictId  ) 

Definition at line 2274 of file namespace.c.

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

Referenced by pg_ts_dict_is_visible(), and regdictionaryout().

{
    HeapTuple   tup;
    Form_pg_ts_dict form;
    Oid         namespace;
    bool        visible;

    tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "cache lookup failed for text search dictionary %u",
             dictId);
    form = (Form_pg_ts_dict) GETSTRUCT(tup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    namespace = form->dictnamespace;
    if (namespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, namespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another dictionary of the same name earlier in the path.
         * So we must do a slow check for conflicting dictionaries.
         */
        char       *name = NameStr(form->dictname);
        ListCell   *l;

        visible = false;
        foreach(l, activeSearchPath)
        {
            Oid         namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            if (namespaceId == namespace)
            {
                /* Found it first in path */
                visible = true;
                break;
            }
            if (SearchSysCacheExists2(TSDICTNAMENSP,
                                      PointerGetDatum(name),
                                      ObjectIdGetDatum(namespaceId)))
            {
                /* Found something else first in path */
                break;
            }
        }
    }

    ReleaseSysCache(tup);

    return visible;
}

bool TSParserIsVisible ( Oid  prsId  ) 

Definition at line 2148 of file namespace.c.

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

Referenced by pg_ts_parser_is_visible().

{
    HeapTuple   tup;
    Form_pg_ts_parser form;
    Oid         namespace;
    bool        visible;

    tup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "cache lookup failed for text search parser %u", prsId);
    form = (Form_pg_ts_parser) GETSTRUCT(tup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    namespace = form->prsnamespace;
    if (namespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, namespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another parser of the same name earlier in the path. So
         * we must do a slow check for conflicting parsers.
         */
        char       *name = NameStr(form->prsname);
        ListCell   *l;

        visible = false;
        foreach(l, activeSearchPath)
        {
            Oid         namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            if (namespaceId == namespace)
            {
                /* Found it first in path */
                visible = true;
                break;
            }
            if (SearchSysCacheExists2(TSPARSERNAMENSP,
                                      PointerGetDatum(name),
                                      ObjectIdGetDatum(namespaceId)))
            {
                /* Found something else first in path */
                break;
            }
        }
    }

    ReleaseSysCache(tup);

    return visible;
}

bool TSTemplateIsVisible ( Oid  tmplId  ) 

Definition at line 2401 of file namespace.c.

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

Referenced by pg_ts_template_is_visible().

{
    HeapTuple   tup;
    Form_pg_ts_template form;
    Oid         namespace;
    bool        visible;

    tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "cache lookup failed for text search template %u", tmplId);
    form = (Form_pg_ts_template) GETSTRUCT(tup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    namespace = form->tmplnamespace;
    if (namespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, namespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another template of the same name earlier in the path. So
         * we must do a slow check for conflicting templates.
         */
        char       *name = NameStr(form->tmplname);
        ListCell   *l;

        visible = false;
        foreach(l, activeSearchPath)
        {
            Oid         namespaceId = lfirst_oid(l);

            if (namespaceId == myTempNamespace)
                continue;       /* do not look in temp namespace */

            if (namespaceId == namespace)
            {
                /* Found it first in path */
                visible = true;
                break;
            }
            if (SearchSysCacheExists2(TSTEMPLATENAMENSP,
                                      PointerGetDatum(name),
                                      ObjectIdGetDatum(namespaceId)))
            {
                /* Found something else first in path */
                break;
            }
        }
    }

    ReleaseSysCache(tup);

    return visible;
}

bool TypeIsVisible ( Oid  typid  ) 

Definition at line 788 of file namespace.c.

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

Referenced by format_type_internal(), and pg_type_is_visible().

{
    HeapTuple   typtup;
    Form_pg_type typform;
    Oid         typnamespace;
    bool        visible;

    typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    if (!HeapTupleIsValid(typtup))
        elog(ERROR, "cache lookup failed for type %u", typid);
    typform = (Form_pg_type) GETSTRUCT(typtup);

    recomputeNamespacePath();

    /*
     * Quick check: if it ain't in the path at all, it ain't visible. Items in
     * the system namespace are surely in the path and so we needn't even do
     * list_member_oid() for them.
     */
    typnamespace = typform->typnamespace;
    if (typnamespace != PG_CATALOG_NAMESPACE &&
        !list_member_oid(activeSearchPath, typnamespace))
        visible = false;
    else
    {
        /*
         * If it is in the path, it might still not be visible; it could be
         * hidden by another type of the same name earlier in the path. So we
         * must do a slow check for conflicting types.
         */
        char       *typname = NameStr(typform->typname);
        ListCell   *l;

        visible = false;
        foreach(l, activeSearchPath)
        {
            Oid         namespaceId = lfirst_oid(l);

            if (namespaceId == typnamespace)
            {
                /* Found it first in path */
                visible = true;
                break;
            }
            if (SearchSysCacheExists2(TYPENAMENSP,
                                      PointerGetDatum(typname),
                                      ObjectIdGetDatum(namespaceId)))
            {
                /* Found something else first in path */
                break;
            }
        }
    }

    ReleaseSysCache(typtup);

    return visible;
}

Oid TypenameGetTypid ( const char *  typname  ) 

Definition at line 759 of file namespace.c.

References GetSysCacheOid2, lfirst_oid, ObjectIdGetDatum, OidIsValid, PointerGetDatum, recomputeNamespacePath(), and TYPENAMENSP.

Referenced by LookupTypeName().

{
    Oid         typid;
    ListCell   *l;

    recomputeNamespacePath();

    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);

        typid = GetSysCacheOid2(TYPENAMENSP,
                                PointerGetDatum(typname),
                                ObjectIdGetDatum(namespaceId));
        if (OidIsValid(typid))
            return typid;
    }

    /* Not found in path */
    return InvalidOid;
}


Variable Documentation

Oid activeCreationNamespace = InvalidOid [static]
List* activeSearchPath = NIL [static]

Definition at line 130 of file namespace.c.

bool activeTempCreationPending = false [static]
Oid baseCreationNamespace = InvalidOid [static]
List* baseSearchPath = NIL [static]

Definition at line 140 of file namespace.c.

bool baseSearchPathValid = true [static]
bool baseTempCreationPending = false [static]
Oid myTempNamespace = InvalidOid [static]
SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId [static]

Definition at line 181 of file namespace.c.

Referenced by AtEOSubXact_Namespace(), AtEOXact_Namespace(), and InitTempTableNamespace().

Oid myTempToastNamespace = InvalidOid [static]
char* namespace_search_path = NULL

Definition at line 187 of file namespace.c.

Referenced by recomputeNamespacePath().

Oid namespaceUser = InvalidOid [static]

Definition at line 146 of file namespace.c.

Referenced by InitializeSearchPath(), and recomputeNamespacePath().

List* overrideStack = NIL [static]

Definition at line 160 of file namespace.c.