Header And Logo

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

Functions

parse_relation.h File Reference

#include "parser/parse_node.h"
Include dependency graph for parse_relation.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

RangeTblEntryrefnameRangeTblEntry (ParseState *pstate, const char *schemaname, const char *refname, int location, int *sublevels_up)
CommonTableExprscanNameSpaceForCTE (ParseState *pstate, const char *refname, Index *ctelevelsup)
void checkNameSpaceConflicts (ParseState *pstate, List *namespace1, List *namespace2)
int RTERangeTablePosn (ParseState *pstate, RangeTblEntry *rte, int *sublevels_up)
RangeTblEntryGetRTEByRangeTablePosn (ParseState *pstate, int varno, int sublevels_up)
CommonTableExprGetCTEForRTE (ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
NodescanRTEForColumn (ParseState *pstate, RangeTblEntry *rte, char *colname, int location)
NodecolNameToVar (ParseState *pstate, char *colname, bool localonly, int location)
void markVarForSelectPriv (ParseState *pstate, Var *var, RangeTblEntry *rte)
Relation parserOpenTable (ParseState *pstate, const RangeVar *relation, int lockmode)
RangeTblEntryaddRangeTableEntry (ParseState *pstate, RangeVar *relation, Alias *alias, bool inh, bool inFromCl)
RangeTblEntryaddRangeTableEntryForRelation (ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
RangeTblEntryaddRangeTableEntryForSubquery (ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
RangeTblEntryaddRangeTableEntryForFunction (ParseState *pstate, char *funcname, Node *funcexpr, RangeFunction *rangefunc, bool lateral, bool inFromCl)
RangeTblEntryaddRangeTableEntryForValues (ParseState *pstate, List *exprs, List *collations, Alias *alias, bool lateral, bool inFromCl)
RangeTblEntryaddRangeTableEntryForJoin (ParseState *pstate, List *colnames, JoinType jointype, List *aliasvars, Alias *alias, bool inFromCl)
RangeTblEntryaddRangeTableEntryForCTE (ParseState *pstate, CommonTableExpr *cte, Index levelsup, RangeVar *rv, bool inFromCl)
bool isLockedRefname (ParseState *pstate, const char *refname)
void addRTEtoQuery (ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
void errorMissingRTE (ParseState *pstate, RangeVar *relation) __attribute__((noreturn))
void errorMissingColumn (ParseState *pstate, char *relname, char *colname, int location) __attribute__((noreturn))
void expandRTE (RangeTblEntry *rte, int rtindex, int sublevels_up, int location, bool include_dropped, List **colnames, List **colvars)
ListexpandRelAttrs (ParseState *pstate, RangeTblEntry *rte, int rtindex, int sublevels_up, int location)
int attnameAttNum (Relation rd, const char *attname, bool sysColOK)
Name attnumAttName (Relation rd, int attid)
Oid attnumTypeId (Relation rd, int attid)
Oid attnumCollationId (Relation rd, int attid)
bool isQueryUsingTempRelation (Query *query)

Function Documentation

RangeTblEntry* addRangeTableEntry ( ParseState pstate,
RangeVar relation,
Alias alias,
bool  inh,
bool  inFromCl 
)

Definition at line 976 of file parse_relation.c.

References RangeTblEntry::alias, Alias::aliasname, buildRelationAliases(), RangeTblEntry::checkAsUser, RangeTblEntry::eref, heap_close, RangeTblEntry::inFromCl, RangeTblEntry::inh, isLockedRefname(), lappend(), RangeTblEntry::lateral, makeAlias(), makeNode, RangeTblEntry::modifiedCols, NIL, NoLock, NULL, ParseState::p_rtable, parserOpenTable(), RelationData::rd_att, RelationData::rd_rel, RelationGetRelid, RangeTblEntry::relid, RangeTblEntry::relkind, RangeVar::relname, RangeTblEntry::requiredPerms, RowShareLock, RangeTblEntry::rtekind, and RangeTblEntry::selectedCols.

Referenced by transformIndexStmt(), and transformTableEntry().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    char       *refname = alias ? alias->aliasname : relation->relname;
    LOCKMODE    lockmode;
    Relation    rel;

    rte->rtekind = RTE_RELATION;
    rte->alias = alias;

    /*
     * Get the rel's OID.  This access also ensures that we have an up-to-date
     * relcache entry for the rel.  Since this is typically the first access
     * to a rel in a statement, be careful to get the right access level
     * depending on whether we're doing SELECT FOR UPDATE/SHARE.
     */
    lockmode = isLockedRefname(pstate, refname) ? RowShareLock : AccessShareLock;
    rel = parserOpenTable(pstate, relation, lockmode);
    rte->relid = RelationGetRelid(rel);
    rte->relkind = rel->rd_rel->relkind;

    /*
     * Build the list of effective column names using user-supplied aliases
     * and/or actual column names.
     */
    rte->eref = makeAlias(refname, NIL);
    buildRelationAliases(rel->rd_att, alias, rte->eref);

    /*
     * Drop the rel refcount, but keep the access lock till end of transaction
     * so that the table can't be deleted or have its schema modified
     * underneath us.
     */
    heap_close(rel, NoLock);

    /*
     * Set flags and access permissions.
     *
     * The initial default on access checks is always check-for-READ-access,
     * which is the right thing for all except target tables.
     */
    rte->lateral = false;
    rte->inh = inh;
    rte->inFromCl = inFromCl;

    rte->requiredPerms = ACL_SELECT;
    rte->checkAsUser = InvalidOid;      /* not set-uid by default, either */
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

RangeTblEntry* addRangeTableEntryForCTE ( ParseState pstate,
CommonTableExpr cte,
Index  levelsup,
RangeVar rv,
bool  inFromCl 
)

Definition at line 1454 of file parse_relation.c.

References RangeTblEntry::alias, RangeVar::alias, Alias::aliasname, Assert, RangeTblEntry::checkAsUser, CMD_SELECT, Alias::colnames, Query::commandType, copyObject(), CommonTableExpr::ctecolcollations, RangeTblEntry::ctecolcollations, CommonTableExpr::ctecolnames, CommonTableExpr::ctecoltypes, RangeTblEntry::ctecoltypes, CommonTableExpr::ctecoltypmods, RangeTblEntry::ctecoltypmods, RangeTblEntry::ctelevelsup, RangeTblEntry::ctename, CommonTableExpr::ctename, CommonTableExpr::ctequery, CommonTableExpr::cterecursive, CommonTableExpr::cterefcount, RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, RangeTblEntry::inFromCl, RangeTblEntry::inh, IsA, lappend(), RangeTblEntry::lateral, lfirst, list_length(), RangeVar::location, makeAlias(), makeNode, RangeTblEntry::modifiedCols, NIL, NULL, ParseState::p_rtable, parser_errposition(), RangeTblEntry::requiredPerms, Query::returningList, RangeTblEntry::rtekind, RangeTblEntry::selectedCols, and RangeTblEntry::self_reference.

Referenced by transformCTEReference().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    Alias      *alias = rv->alias;
    char       *refname = alias ? alias->aliasname : cte->ctename;
    Alias      *eref;
    int         numaliases;
    int         varattno;
    ListCell   *lc;

    rte->rtekind = RTE_CTE;
    rte->ctename = cte->ctename;
    rte->ctelevelsup = levelsup;

    /* Self-reference if and only if CTE's parse analysis isn't completed */
    rte->self_reference = !IsA(cte->ctequery, Query);
    Assert(cte->cterecursive || !rte->self_reference);
    /* Bump the CTE's refcount if this isn't a self-reference */
    if (!rte->self_reference)
        cte->cterefcount++;

    /*
     * We throw error if the CTE is INSERT/UPDATE/DELETE without RETURNING.
     * This won't get checked in case of a self-reference, but that's OK
     * because data-modifying CTEs aren't allowed to be recursive anyhow.
     */
    if (IsA(cte->ctequery, Query))
    {
        Query      *ctequery = (Query *) cte->ctequery;

        if (ctequery->commandType != CMD_SELECT &&
            ctequery->returningList == NIL)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("WITH query \"%s\" does not have a RETURNING clause",
                        cte->ctename),
                     parser_errposition(pstate, rv->location)));
    }

    rte->ctecoltypes = cte->ctecoltypes;
    rte->ctecoltypmods = cte->ctecoltypmods;
    rte->ctecolcollations = cte->ctecolcollations;

    rte->alias = alias;
    if (alias)
        eref = copyObject(alias);
    else
        eref = makeAlias(refname, NIL);
    numaliases = list_length(eref->colnames);

    /* fill in any unspecified alias columns */
    varattno = 0;
    foreach(lc, cte->ctecolnames)
    {
        varattno++;
        if (varattno > numaliases)
            eref->colnames = lappend(eref->colnames, lfirst(lc));
    }
    if (varattno < numaliases)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                 errmsg("table \"%s\" has %d columns available but %d columns specified",
                        refname, varattno, numaliases)));

    rte->eref = eref;

    /*
     * Set flags and access permissions.
     *
     * Subqueries are never checked for access rights.
     */
    rte->lateral = false;
    rte->inh = false;           /* never true for subqueries */
    rte->inFromCl = inFromCl;

    rte->requiredPerms = 0;
    rte->checkAsUser = InvalidOid;
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

RangeTblEntry* addRangeTableEntryForFunction ( ParseState pstate,
char *  funcname,
Node funcexpr,
RangeFunction rangefunc,
bool  lateral,
bool  inFromCl 
)

Definition at line 1177 of file parse_relation.c.

References RangeTblEntry::alias, RangeFunction::alias, Alias::aliasname, Assert, buildRelationAliases(), buildScalarFunctionAlias(), RangeTblEntry::checkAsUser, RangeFunction::coldeflist, ColumnDef::colname, Alias::colnames, RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, exprLocation(), format_type_be(), RangeTblEntry::funccolcollations, RangeTblEntry::funccoltypes, RangeTblEntry::funccoltypmods, RangeTblEntry::funcexpr, get_expr_result_type(), GetColumnDefCollation(), RangeTblEntry::inFromCl, RangeTblEntry::inh, lappend(), lappend_int(), lappend_oid(), RangeTblEntry::lateral, lfirst, TypeName::location, makeAlias(), makeNode, makeString(), RangeTblEntry::modifiedCols, NIL, NULL, ParseState::p_rtable, parser_errposition(), pstrdup(), RangeTblEntry::relid, RangeTblEntry::requiredPerms, RangeTblEntry::rtekind, RangeTblEntry::selectedCols, TypeName::setof, RangeTblEntry::subquery, TYPEFUNC_COMPOSITE, TYPEFUNC_RECORD, TYPEFUNC_SCALAR, ColumnDef::typeName, and typenameTypeIdAndMod().

Referenced by transformRangeFunction().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    TypeFuncClass functypclass;
    Oid         funcrettype;
    TupleDesc   tupdesc;
    Alias      *alias = rangefunc->alias;
    List       *coldeflist = rangefunc->coldeflist;
    Alias      *eref;

    rte->rtekind = RTE_FUNCTION;
    rte->relid = InvalidOid;
    rte->subquery = NULL;
    rte->funcexpr = funcexpr;
    rte->funccoltypes = NIL;
    rte->funccoltypmods = NIL;
    rte->funccolcollations = NIL;
    rte->alias = alias;

    eref = makeAlias(alias ? alias->aliasname : funcname, NIL);
    rte->eref = eref;

    /*
     * Now determine if the function returns a simple or composite type.
     */
    functypclass = get_expr_result_type(funcexpr,
                                        &funcrettype,
                                        &tupdesc);

    /*
     * A coldeflist is required if the function returns RECORD and hasn't got
     * a predetermined record type, and is prohibited otherwise.
     */
    if (coldeflist != NIL)
    {
        if (functypclass != TYPEFUNC_RECORD)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("a column definition list is only allowed for functions returning \"record\""),
                     parser_errposition(pstate, exprLocation(funcexpr))));
    }
    else
    {
        if (functypclass == TYPEFUNC_RECORD)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("a column definition list is required for functions returning \"record\""),
                     parser_errposition(pstate, exprLocation(funcexpr))));
    }

    if (functypclass == TYPEFUNC_COMPOSITE)
    {
        /* Composite data type, e.g. a table's row type */
        Assert(tupdesc);
        /* Build the column alias list */
        buildRelationAliases(tupdesc, alias, eref);
    }
    else if (functypclass == TYPEFUNC_SCALAR)
    {
        /* Base data type, i.e. scalar */
        buildScalarFunctionAlias(funcexpr, funcname, alias, eref);
    }
    else if (functypclass == TYPEFUNC_RECORD)
    {
        ListCell   *col;

        /*
         * Use the column definition list to form the alias list and
         * funccoltypes/funccoltypmods/funccolcollations lists.
         */
        foreach(col, coldeflist)
        {
            ColumnDef  *n = (ColumnDef *) lfirst(col);
            char       *attrname;
            Oid         attrtype;
            int32       attrtypmod;
            Oid         attrcollation;

            attrname = pstrdup(n->colname);
            if (n->typeName->setof)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                         errmsg("column \"%s\" cannot be declared SETOF",
                                attrname),
                         parser_errposition(pstate, n->typeName->location)));
            typenameTypeIdAndMod(pstate, n->typeName, &attrtype, &attrtypmod);
            attrcollation = GetColumnDefCollation(pstate, n, attrtype);
            eref->colnames = lappend(eref->colnames, makeString(attrname));
            rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
            rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
            rte->funccolcollations = lappend_oid(rte->funccolcollations,
                                                 attrcollation);
        }
    }
    else
        ereport(ERROR,
                (errcode(ERRCODE_DATATYPE_MISMATCH),
             errmsg("function \"%s\" in FROM has unsupported return type %s",
                    funcname, format_type_be(funcrettype)),
                 parser_errposition(pstate, exprLocation(funcexpr))));

    /*
     * Set flags and access permissions.
     *
     * Functions are never checked for access rights (at least, not by the RTE
     * permissions mechanism).
     */
    rte->lateral = lateral;
    rte->inh = false;           /* never true for functions */
    rte->inFromCl = inFromCl;

    rte->requiredPerms = 0;
    rte->checkAsUser = InvalidOid;
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

RangeTblEntry* addRangeTableEntryForJoin ( ParseState pstate,
List colnames,
JoinType  jointype,
List aliasvars,
Alias alias,
bool  inFromCl 
)

Definition at line 1386 of file parse_relation.c.

References RangeTblEntry::alias, RangeTblEntry::checkAsUser, Alias::colnames, copyObject(), RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::joinaliasvars, RangeTblEntry::jointype, lappend(), RangeTblEntry::lateral, list_concat(), list_copy_tail(), list_length(), makeAlias(), makeNode, MaxAttrNumber, RangeTblEntry::modifiedCols, NIL, NULL, ParseState::p_rtable, RangeTblEntry::relid, RangeTblEntry::requiredPerms, RangeTblEntry::rtekind, RangeTblEntry::selectedCols, and RangeTblEntry::subquery.

Referenced by transformFromClauseItem(), and transformSetOperationStmt().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    Alias      *eref;
    int         numaliases;

    /*
     * Fail if join has too many columns --- we must be able to reference any
     * of the columns with an AttrNumber.
     */
    if (list_length(aliasvars) > MaxAttrNumber)
        ereport(ERROR,
                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                 errmsg("joins can have at most %d columns",
                        MaxAttrNumber)));

    rte->rtekind = RTE_JOIN;
    rte->relid = InvalidOid;
    rte->subquery = NULL;
    rte->jointype = jointype;
    rte->joinaliasvars = aliasvars;
    rte->alias = alias;

    eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL);
    numaliases = list_length(eref->colnames);

    /* fill in any unspecified alias columns */
    if (numaliases < list_length(colnames))
        eref->colnames = list_concat(eref->colnames,
                                     list_copy_tail(colnames, numaliases));

    rte->eref = eref;

    /*
     * Set flags and access permissions.
     *
     * Joins are never checked for access rights.
     */
    rte->lateral = false;
    rte->inh = false;           /* never true for joins */
    rte->inFromCl = inFromCl;

    rte->requiredPerms = 0;
    rte->checkAsUser = InvalidOid;
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

RangeTblEntry* addRangeTableEntryForRelation ( ParseState pstate,
Relation  rel,
Alias alias,
bool  inh,
bool  inFromCl 
)

Definition at line 1047 of file parse_relation.c.

References RangeTblEntry::alias, Alias::aliasname, buildRelationAliases(), RangeTblEntry::checkAsUser, RangeTblEntry::eref, RangeTblEntry::inFromCl, RangeTblEntry::inh, lappend(), RangeTblEntry::lateral, makeAlias(), makeNode, RangeTblEntry::modifiedCols, NIL, NULL, ParseState::p_rtable, RelationData::rd_att, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::requiredPerms, RangeTblEntry::rtekind, and RangeTblEntry::selectedCols.

Referenced by AddRelationNewConstraints(), ATPrepAlterColumnType(), CreateTrigger(), setTargetTable(), transformRuleStmt(), and UpdateRangeTableOfViewParse().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    char       *refname = alias ? alias->aliasname : RelationGetRelationName(rel);

    rte->rtekind = RTE_RELATION;
    rte->alias = alias;
    rte->relid = RelationGetRelid(rel);
    rte->relkind = rel->rd_rel->relkind;

    /*
     * Build the list of effective column names using user-supplied aliases
     * and/or actual column names.
     */
    rte->eref = makeAlias(refname, NIL);
    buildRelationAliases(rel->rd_att, alias, rte->eref);

    /*
     * Set flags and access permissions.
     *
     * The initial default on access checks is always check-for-READ-access,
     * which is the right thing for all except target tables.
     */
    rte->lateral = false;
    rte->inh = inh;
    rte->inFromCl = inFromCl;

    rte->requiredPerms = ACL_SELECT;
    rte->checkAsUser = InvalidOid;      /* not set-uid by default, either */
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

RangeTblEntry* addRangeTableEntryForSubquery ( ParseState pstate,
Query subquery,
Alias alias,
bool  lateral,
bool  inFromCl 
)

Definition at line 1100 of file parse_relation.c.

References RangeTblEntry::alias, Alias::aliasname, Assert, RangeTblEntry::checkAsUser, Alias::colnames, copyObject(), RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, RangeTblEntry::inFromCl, RangeTblEntry::inh, lappend(), RangeTblEntry::lateral, lfirst, list_length(), makeNode, makeString(), RangeTblEntry::modifiedCols, NULL, ParseState::p_rtable, pstrdup(), RangeTblEntry::relid, RangeTblEntry::requiredPerms, TargetEntry::resjunk, TargetEntry::resname, TargetEntry::resno, RangeTblEntry::rtekind, RangeTblEntry::selectedCols, RangeTblEntry::subquery, and Query::targetList.

Referenced by convert_ANY_sublink_to_join(), transformInsertStmt(), transformRangeSubselect(), and transformSetOperationTree().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    char       *refname = alias->aliasname;
    Alias      *eref;
    int         numaliases;
    int         varattno;
    ListCell   *tlistitem;

    rte->rtekind = RTE_SUBQUERY;
    rte->relid = InvalidOid;
    rte->subquery = subquery;
    rte->alias = alias;

    eref = copyObject(alias);
    numaliases = list_length(eref->colnames);

    /* fill in any unspecified alias columns */
    varattno = 0;
    foreach(tlistitem, subquery->targetList)
    {
        TargetEntry *te = (TargetEntry *) lfirst(tlistitem);

        if (te->resjunk)
            continue;
        varattno++;
        Assert(varattno == te->resno);
        if (varattno > numaliases)
        {
            char       *attrname;

            attrname = pstrdup(te->resname);
            eref->colnames = lappend(eref->colnames, makeString(attrname));
        }
    }
    if (varattno < numaliases)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                 errmsg("table \"%s\" has %d columns available but %d columns specified",
                        refname, varattno, numaliases)));

    rte->eref = eref;

    /*
     * Set flags and access permissions.
     *
     * Subqueries are never checked for access rights.
     */
    rte->lateral = lateral;
    rte->inh = false;           /* never true for subqueries */
    rte->inFromCl = inFromCl;

    rte->requiredPerms = 0;
    rte->checkAsUser = InvalidOid;
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

RangeTblEntry* addRangeTableEntryForValues ( ParseState pstate,
List exprs,
List collations,
Alias alias,
bool  lateral,
bool  inFromCl 
)

Definition at line 1314 of file parse_relation.c.

References RangeTblEntry::alias, Alias::aliasname, RangeTblEntry::checkAsUser, Alias::colnames, copyObject(), RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, RangeTblEntry::inFromCl, RangeTblEntry::inh, lappend(), RangeTblEntry::lateral, linitial, list_length(), makeAlias(), makeNode, makeString(), RangeTblEntry::modifiedCols, NIL, NULL, ParseState::p_rtable, pstrdup(), RangeTblEntry::relid, RangeTblEntry::requiredPerms, RangeTblEntry::rtekind, RangeTblEntry::selectedCols, snprintf(), RangeTblEntry::subquery, RangeTblEntry::values_collations, and RangeTblEntry::values_lists.

Referenced by transformValuesClause().

{
    RangeTblEntry *rte = makeNode(RangeTblEntry);
    char       *refname = alias ? alias->aliasname : pstrdup("*VALUES*");
    Alias      *eref;
    int         numaliases;
    int         numcolumns;

    rte->rtekind = RTE_VALUES;
    rte->relid = InvalidOid;
    rte->subquery = NULL;
    rte->values_lists = exprs;
    rte->values_collations = collations;
    rte->alias = alias;

    eref = alias ? copyObject(alias) : makeAlias(refname, NIL);

    /* fill in any unspecified alias columns */
    numcolumns = list_length((List *) linitial(exprs));
    numaliases = list_length(eref->colnames);
    while (numaliases < numcolumns)
    {
        char        attrname[64];

        numaliases++;
        snprintf(attrname, sizeof(attrname), "column%d", numaliases);
        eref->colnames = lappend(eref->colnames,
                                 makeString(pstrdup(attrname)));
    }
    if (numcolumns < numaliases)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                 errmsg("VALUES lists \"%s\" have %d columns available but %d columns specified",
                        refname, numcolumns, numaliases)));

    rte->eref = eref;

    /*
     * Set flags and access permissions.
     *
     * Subqueries are never checked for access rights.
     */
    rte->lateral = lateral;
    rte->inh = false;           /* never true for values RTEs */
    rte->inFromCl = inFromCl;

    rte->requiredPerms = 0;
    rte->checkAsUser = InvalidOid;
    rte->selectedCols = NULL;
    rte->modifiedCols = NULL;

    /*
     * Add completed RTE to pstate's range table list, but not to join list
     * nor namespace --- caller must do that if appropriate.
     */
    if (pstate != NULL)
        pstate->p_rtable = lappend(pstate->p_rtable, rte);

    return rte;
}

void addRTEtoQuery ( ParseState pstate,
RangeTblEntry rte,
bool  addToJoinList,
bool  addToRelNameSpace,
bool  addToVarNameSpace 
)
int attnameAttNum ( Relation  rd,
const char *  attname,
bool  sysColOK 
)

Definition at line 2415 of file parse_relation.c.

References tupleDesc::attrs, i, InvalidAttrNumber, namestrcmp(), ObjectIdAttributeNumber, RelationData::rd_att, RelationData::rd_rel, and specialAttNum().

Referenced by checkInsertTargets(), CreateTrigger(), do_analyze_rel(), and transformUpdateStmt().

{
    int         i;

    for (i = 0; i < rd->rd_rel->relnatts; i++)
    {
        Form_pg_attribute att = rd->rd_att->attrs[i];

        if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
            return i + 1;
    }

    if (sysColOK)
    {
        if ((i = specialAttNum(attname)) != InvalidAttrNumber)
        {
            if (i != ObjectIdAttributeNumber || rd->rd_rel->relhasoids)
                return i;
        }
    }

    /* on failure */
    return InvalidAttrNumber;
}

Name attnumAttName ( Relation  rd,
int  attid 
)

Definition at line 2470 of file parse_relation.c.

References tupleDesc::attrs, elog, ERROR, tupleDesc::natts, RelationData::rd_att, RelationData::rd_rel, and SystemAttributeDefinition().

Referenced by transformFkeyGetPrimaryKey().

{
    if (attid <= 0)
    {
        Form_pg_attribute sysatt;

        sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
        return &sysatt->attname;
    }
    if (attid > rd->rd_att->natts)
        elog(ERROR, "invalid attribute number %d", attid);
    return &rd->rd_att->attrs[attid - 1]->attname;
}

Oid attnumCollationId ( Relation  rd,
int  attid 
)

Definition at line 2512 of file parse_relation.c.

References tupleDesc::attrs, elog, ERROR, tupleDesc::natts, and RelationData::rd_att.

{
    if (attid <= 0)
    {
        /* All system attributes are of noncollatable types. */
        return InvalidOid;
    }
    if (attid > rd->rd_att->natts)
        elog(ERROR, "invalid attribute number %d", attid);
    return rd->rd_att->attrs[attid - 1]->attcollation;
}

Oid attnumTypeId ( Relation  rd,
int  attid 
)

Definition at line 2492 of file parse_relation.c.

References tupleDesc::attrs, elog, ERROR, tupleDesc::natts, RelationData::rd_att, RelationData::rd_rel, and SystemAttributeDefinition().

Referenced by transformAssignedExpr(), and transformFkeyGetPrimaryKey().

{
    if (attid <= 0)
    {
        Form_pg_attribute sysatt;

        sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
        return sysatt->atttypid;
    }
    if (attid > rd->rd_att->natts)
        elog(ERROR, "invalid attribute number %d", attid);
    return rd->rd_att->attrs[attid - 1]->atttypid;
}

void checkNameSpaceConflicts ( ParseState pstate,
List namespace1,
List namespace2 
)

Definition at line 365 of file parse_relation.c.

References RangeTblEntry::alias, Alias::aliasname, RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, lfirst, NULL, ParseNamespaceItem::p_rel_visible, ParseNamespaceItem::p_rte, RangeTblEntry::relid, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by transformFromClause(), and transformFromClauseItem().

{
    ListCell   *l1;

    foreach(l1, namespace1)
    {
        ParseNamespaceItem *nsitem1 = (ParseNamespaceItem *) lfirst(l1);
        RangeTblEntry *rte1 = nsitem1->p_rte;
        const char *aliasname1 = rte1->eref->aliasname;
        ListCell   *l2;

        if (!nsitem1->p_rel_visible)
            continue;

        foreach(l2, namespace2)
        {
            ParseNamespaceItem *nsitem2 = (ParseNamespaceItem *) lfirst(l2);
            RangeTblEntry *rte2 = nsitem2->p_rte;

            if (!nsitem2->p_rel_visible)
                continue;
            if (strcmp(rte2->eref->aliasname, aliasname1) != 0)
                continue;       /* definitely no conflict */
            if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
                rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
                rte1->relid != rte2->relid)
                continue;       /* no conflict per SQL rule */
            ereport(ERROR,
                    (errcode(ERRCODE_DUPLICATE_ALIAS),
                     errmsg("table name \"%s\" specified more than once",
                            aliasname1)));
        }
    }
}

Node* colNameToVar ( ParseState pstate,
char *  colname,
bool  localonly,
int  location 
)

Definition at line 580 of file parse_relation.c.

References Alias::aliasname, RangeTblEntry::eref, ereport, errcode(), errdetail(), errmsg(), ERROR, lfirst, NULL, ParseNamespaceItem::p_cols_visible, ParseState::p_lateral_active, ParseNamespaceItem::p_lateral_ok, ParseNamespaceItem::p_lateral_only, ParseState::p_namespace, ParseNamespaceItem::p_rte, ParseState::parentParseState, parser_errposition(), and scanRTEForColumn().

Referenced by findTargetlistEntrySQL92(), and transformColumnRef().

{
    Node       *result = NULL;
    ParseState *orig_pstate = pstate;

    while (pstate != NULL)
    {
        ListCell   *l;

        foreach(l, pstate->p_namespace)
        {
            ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
            RangeTblEntry *rte = nsitem->p_rte;
            Node       *newresult;

            /* Ignore table-only items */
            if (!nsitem->p_cols_visible)
                continue;
            /* If not inside LATERAL, ignore lateral-only items */
            if (nsitem->p_lateral_only && !pstate->p_lateral_active)
                continue;

            /* use orig_pstate here to get the right sublevels_up */
            newresult = scanRTEForColumn(orig_pstate, rte, colname, location);

            if (newresult)
            {
                if (result)
                    ereport(ERROR,
                            (errcode(ERRCODE_AMBIGUOUS_COLUMN),
                             errmsg("column reference \"%s\" is ambiguous",
                                    colname),
                             parser_errposition(orig_pstate, location)));
                /* SQL:2008 demands this be an error, not an invisible item */
                if (nsitem->p_lateral_only && !nsitem->p_lateral_ok)
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                             errmsg("invalid reference to FROM-clause entry for table \"%s\"",
                                    rte->eref->aliasname),
                             errdetail("The combining JOIN type must be INNER or LEFT for a LATERAL reference."),
                             parser_errposition(orig_pstate, location)));
                result = newresult;
            }
        }

        if (result != NULL || localonly)
            break;              /* found, or don't want to look at parent */

        pstate = pstate->parentParseState;
    }

    return result;
}

void errorMissingColumn ( ParseState pstate,
char *  relname,
char *  colname,
int  location 
)

Definition at line 2587 of file parse_relation.c.

References Alias::aliasname, RangeTblEntry::eref, ereport, errcode(), errhint(), errmsg(), ERROR, parser_errposition(), and searchRangeTableForCol().

Referenced by transformColumnRef().

{
    RangeTblEntry *rte;

    /*
     * If relname was given, just play dumb and report it.  (In practice, a
     * bad qualification name should end up at errorMissingRTE, not here, so
     * no need to work hard on this case.)
     */
    if (relname)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_COLUMN),
                 errmsg("column %s.%s does not exist", relname, colname),
                 parser_errposition(pstate, location)));

    /*
     * Otherwise, search the entire rtable looking for possible matches.  If
     * we find one, emit a hint about it.
     *
     * TODO: improve this code (and also errorMissingRTE) to mention using
     * LATERAL if appropriate.
     */
    rte = searchRangeTableForCol(pstate, colname, location);

    ereport(ERROR,
            (errcode(ERRCODE_UNDEFINED_COLUMN),
             errmsg("column \"%s\" does not exist", colname),
             rte ? errhint("There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query.",
                           colname, rte->eref->aliasname) : 0,
             parser_errposition(pstate, location)));
}

void errorMissingRTE ( ParseState pstate,
RangeVar relation 
)

Definition at line 2531 of file parse_relation.c.

References RangeTblEntry::alias, Alias::aliasname, RangeTblEntry::eref, ereport, errcode(), errhint(), errmsg(), ERROR, RangeVar::location, NULL, parser_errposition(), refnameRangeTblEntry(), RangeVar::relname, and searchRangeTableForRel().

Referenced by ExpandColumnRefStar(), and transformColumnRef().

{
    RangeTblEntry *rte;
    int         sublevels_up;
    const char *badAlias = NULL;

    /*
     * Check to see if there are any potential matches in the query's
     * rangetable.  (Note: cases involving a bad schema name in the RangeVar
     * will throw error immediately here.  That seems OK.)
     */
    rte = searchRangeTableForRel(pstate, relation);

    /*
     * If we found a match that has an alias and the alias is visible in the
     * namespace, then the problem is probably use of the relation's real name
     * instead of its alias, ie "SELECT foo.* FROM foo f". This mistake is
     * common enough to justify a specific hint.
     *
     * If we found a match that doesn't meet those criteria, assume the
     * problem is illegal use of a relation outside its scope, as in the
     * MySQL-ism "SELECT ... FROM a, b LEFT JOIN c ON (a.x = c.y)".
     */
    if (rte && rte->alias &&
        strcmp(rte->eref->aliasname, relation->relname) != 0 &&
        refnameRangeTblEntry(pstate, NULL, rte->eref->aliasname,
                             relation->location,
                             &sublevels_up) == rte)
        badAlias = rte->eref->aliasname;

    if (rte)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_TABLE),
            errmsg("invalid reference to FROM-clause entry for table \"%s\"",
                   relation->relname),
                 (badAlias ?
            errhint("Perhaps you meant to reference the table alias \"%s\".",
                    badAlias) :
                  errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
                          rte->eref->aliasname)),
                 parser_errposition(pstate, relation->location)));
    else
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_TABLE),
                 errmsg("missing FROM-clause entry for table \"%s\"",
                        relation->relname),
                 parser_errposition(pstate, relation->location)));
}

List* expandRelAttrs ( ParseState pstate,
RangeTblEntry rte,
int  rtindex,
int  sublevels_up,
int  location 
)

Definition at line 2020 of file parse_relation.c.

References Assert, expandRTE(), forboth, label, lappend(), lfirst, makeTargetEntry(), markVarForSelectPriv(), name, NULL, ParseState::p_next_resno, RangeTblEntry::requiredPerms, and strVal.

Referenced by ExpandAllTables(), ExpandSingleTable(), and transformValuesClause().

{
    List       *names,
               *vars;
    ListCell   *name,
               *var;
    List       *te_list = NIL;

    expandRTE(rte, rtindex, sublevels_up, location, false,
              &names, &vars);

    /*
     * Require read access to the table.  This is normally redundant with the
     * markVarForSelectPriv calls below, but not if the table has zero
     * columns.
     */
    rte->requiredPerms |= ACL_SELECT;

    forboth(name, names, var, vars)
    {
        char       *label = strVal(lfirst(name));
        Var        *varnode = (Var *) lfirst(var);
        TargetEntry *te;

        te = makeTargetEntry((Expr *) varnode,
                             (AttrNumber) pstate->p_next_resno++,
                             label,
                             false);
        te_list = lappend(te_list, te);

        /* Require read access to each column */
        markVarForSelectPriv(pstate, varnode, rte);
    }

    Assert(name == NULL && var == NULL);        /* lists not the same length? */

    return te_list;
}

void expandRTE ( RangeTblEntry rte,
int  rtindex,
int  sublevels_up,
int  location,
bool  include_dropped,
List **  colnames,
List **  colvars 
)

Definition at line 1647 of file parse_relation.c.

References Assert, Alias::colnames, copyObject(), RangeTblEntry::ctecolcollations, RangeTblEntry::ctecoltypes, RangeTblEntry::ctecoltypmods, elog, RangeTblEntry::eref, ERROR, expandRelation(), expandTupleDesc(), TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), forboth, forthree, RangeTblEntry::funccolcollations, RangeTblEntry::funccoltypes, RangeTblEntry::funccoltypmods, RangeTblEntry::funcexpr, get_expr_result_type(), IsA, RangeTblEntry::joinaliasvars, label, lappend(), lfirst, lfirst_int, lfirst_oid, linitial, list_head(), list_length(), lnext, Var::location, makeString(), makeVar(), pstrdup(), RangeTblEntry::relid, TargetEntry::resjunk, TargetEntry::resno, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, RTE_VALUES, RangeTblEntry::rtekind, strVal, RangeTblEntry::subquery, Query::targetList, TYPEFUNC_COMPOSITE, TYPEFUNC_RECORD, TYPEFUNC_SCALAR, RangeTblEntry::values_collations, and RangeTblEntry::values_lists.

Referenced by build_physical_tlist(), coerce_record_to_complex(), expandRecordVariable(), expandRelAttrs(), ExpandSingleTable(), pullup_replace_vars_callback(), ReplaceVarsFromTargetList_callback(), and transformFromClauseItem().

{
    int         varattno;

    if (colnames)
        *colnames = NIL;
    if (colvars)
        *colvars = NIL;

    switch (rte->rtekind)
    {
        case RTE_RELATION:
            /* Ordinary relation RTE */
            expandRelation(rte->relid, rte->eref,
                           rtindex, sublevels_up, location,
                           include_dropped, colnames, colvars);
            break;
        case RTE_SUBQUERY:
            {
                /* Subquery RTE */
                ListCell   *aliasp_item = list_head(rte->eref->colnames);
                ListCell   *tlistitem;

                varattno = 0;
                foreach(tlistitem, rte->subquery->targetList)
                {
                    TargetEntry *te = (TargetEntry *) lfirst(tlistitem);

                    if (te->resjunk)
                        continue;
                    varattno++;
                    Assert(varattno == te->resno);

                    if (colnames)
                    {
                        /* Assume there is one alias per target item */
                        char       *label = strVal(lfirst(aliasp_item));

                        *colnames = lappend(*colnames, makeString(pstrdup(label)));
                        aliasp_item = lnext(aliasp_item);
                    }

                    if (colvars)
                    {
                        Var        *varnode;

                        varnode = makeVar(rtindex, varattno,
                                          exprType((Node *) te->expr),
                                          exprTypmod((Node *) te->expr),
                                          exprCollation((Node *) te->expr),
                                          sublevels_up);
                        varnode->location = location;

                        *colvars = lappend(*colvars, varnode);
                    }
                }
            }
            break;
        case RTE_FUNCTION:
            {
                /* Function RTE */
                TypeFuncClass functypclass;
                Oid         funcrettype;
                TupleDesc   tupdesc;

                functypclass = get_expr_result_type(rte->funcexpr,
                                                    &funcrettype,
                                                    &tupdesc);
                if (functypclass == TYPEFUNC_COMPOSITE)
                {
                    /* Composite data type, e.g. a table's row type */
                    Assert(tupdesc);
                    expandTupleDesc(tupdesc, rte->eref,
                                    rtindex, sublevels_up, location,
                                    include_dropped, colnames, colvars);
                }
                else if (functypclass == TYPEFUNC_SCALAR)
                {
                    /* Base data type, i.e. scalar */
                    if (colnames)
                        *colnames = lappend(*colnames,
                                            linitial(rte->eref->colnames));

                    if (colvars)
                    {
                        Var        *varnode;

                        varnode = makeVar(rtindex, 1,
                                          funcrettype, -1,
                                          exprCollation(rte->funcexpr),
                                          sublevels_up);
                        varnode->location = location;

                        *colvars = lappend(*colvars, varnode);
                    }
                }
                else if (functypclass == TYPEFUNC_RECORD)
                {
                    if (colnames)
                        *colnames = copyObject(rte->eref->colnames);
                    if (colvars)
                    {
                        ListCell   *l1;
                        ListCell   *l2;
                        ListCell   *l3;
                        int         attnum = 0;

                        forthree(l1, rte->funccoltypes,
                                 l2, rte->funccoltypmods,
                                 l3, rte->funccolcollations)
                        {
                            Oid         attrtype = lfirst_oid(l1);
                            int32       attrtypmod = lfirst_int(l2);
                            Oid         attrcollation = lfirst_oid(l3);
                            Var        *varnode;

                            attnum++;
                            varnode = makeVar(rtindex,
                                              attnum,
                                              attrtype,
                                              attrtypmod,
                                              attrcollation,
                                              sublevels_up);
                            varnode->location = location;
                            *colvars = lappend(*colvars, varnode);
                        }
                    }
                }
                else
                {
                    /* addRangeTableEntryForFunction should've caught this */
                    elog(ERROR, "function in FROM has unsupported return type");
                }
            }
            break;
        case RTE_VALUES:
            {
                /* Values RTE */
                ListCell   *aliasp_item = list_head(rte->eref->colnames);
                ListCell   *lcv;
                ListCell   *lcc;

                varattno = 0;
                forboth(lcv, (List *) linitial(rte->values_lists),
                        lcc, rte->values_collations)
                {
                    Node       *col = (Node *) lfirst(lcv);
                    Oid         colcollation = lfirst_oid(lcc);

                    varattno++;
                    if (colnames)
                    {
                        /* Assume there is one alias per column */
                        char       *label = strVal(lfirst(aliasp_item));

                        *colnames = lappend(*colnames,
                                            makeString(pstrdup(label)));
                        aliasp_item = lnext(aliasp_item);
                    }

                    if (colvars)
                    {
                        Var        *varnode;

                        varnode = makeVar(rtindex, varattno,
                                          exprType(col),
                                          exprTypmod(col),
                                          colcollation,
                                          sublevels_up);
                        varnode->location = location;
                        *colvars = lappend(*colvars, varnode);
                    }
                }
            }
            break;
        case RTE_JOIN:
            {
                /* Join RTE */
                ListCell   *colname;
                ListCell   *aliasvar;

                Assert(list_length(rte->eref->colnames) == list_length(rte->joinaliasvars));

                varattno = 0;
                forboth(colname, rte->eref->colnames, aliasvar, rte->joinaliasvars)
                {
                    Node       *avar = (Node *) lfirst(aliasvar);

                    varattno++;

                    /*
                     * During ordinary parsing, there will never be any
                     * deleted columns in the join; but we have to check since
                     * this routine is also used by the rewriter, and joins
                     * found in stored rules might have join columns for
                     * since-deleted columns.  This will be signaled by a NULL
                     * Const in the alias-vars list.
                     */
                    if (IsA(avar, Const))
                    {
                        if (include_dropped)
                        {
                            if (colnames)
                                *colnames = lappend(*colnames,
                                                    makeString(pstrdup("")));
                            if (colvars)
                                *colvars = lappend(*colvars,
                                                   copyObject(avar));
                        }
                        continue;
                    }

                    if (colnames)
                    {
                        char       *label = strVal(lfirst(colname));

                        *colnames = lappend(*colnames,
                                            makeString(pstrdup(label)));
                    }

                    if (colvars)
                    {
                        Var        *varnode;

                        varnode = makeVar(rtindex, varattno,
                                          exprType(avar),
                                          exprTypmod(avar),
                                          exprCollation(avar),
                                          sublevels_up);
                        varnode->location = location;

                        *colvars = lappend(*colvars, varnode);
                    }
                }
            }
            break;
        case RTE_CTE:
            {
                ListCell   *aliasp_item = list_head(rte->eref->colnames);
                ListCell   *lct;
                ListCell   *lcm;
                ListCell   *lcc;

                varattno = 0;
                forthree(lct, rte->ctecoltypes,
                         lcm, rte->ctecoltypmods,
                         lcc, rte->ctecolcollations)
                {
                    Oid         coltype = lfirst_oid(lct);
                    int32       coltypmod = lfirst_int(lcm);
                    Oid         colcoll = lfirst_oid(lcc);

                    varattno++;

                    if (colnames)
                    {
                        /* Assume there is one alias per output column */
                        char       *label = strVal(lfirst(aliasp_item));

                        *colnames = lappend(*colnames, makeString(pstrdup(label)));
                        aliasp_item = lnext(aliasp_item);
                    }

                    if (colvars)
                    {
                        Var        *varnode;

                        varnode = makeVar(rtindex, varattno,
                                          coltype, coltypmod, colcoll,
                                          sublevels_up);
                        *colvars = lappend(*colvars, varnode);
                    }
                }
            }
            break;
        default:
            elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
    }
}

CommonTableExpr* GetCTEForRTE ( ParseState pstate,
RangeTblEntry rte,
int  rtelevelsup 
)

Definition at line 462 of file parse_relation.c.

References Assert, RangeTblEntry::ctelevelsup, CommonTableExpr::ctename, RangeTblEntry::ctename, elog, ERROR, lfirst, ParseState::p_ctenamespace, ParseState::parentParseState, RTE_CTE, RangeTblEntry::rtekind, and RTERangeTablePosn().

Referenced by expandRecordVariable(), and markTargetListOrigin().

{
    Index       levelsup;
    ListCell   *lc;

    /* Determine RTE's levelsup if caller didn't know it */
    if (rtelevelsup < 0)
        (void) RTERangeTablePosn(pstate, rte, &rtelevelsup);

    Assert(rte->rtekind == RTE_CTE);
    levelsup = rte->ctelevelsup + rtelevelsup;
    while (levelsup-- > 0)
    {
        pstate = pstate->parentParseState;
        if (!pstate)            /* shouldn't happen */
            elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
    }
    foreach(lc, pstate->p_ctenamespace)
    {
        CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);

        if (strcmp(cte->ctename, rte->ctename) == 0)
            return cte;
    }
    /* shouldn't happen */
    elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
    return NULL;                /* keep compiler quiet */
}

RangeTblEntry* GetRTEByRangeTablePosn ( ParseState pstate,
int  varno,
int  sublevels_up 
)

Definition at line 441 of file parse_relation.c.

References Assert, list_length(), NULL, ParseState::p_rtable, ParseState::parentParseState, and rt_fetch.

Referenced by coerce_record_to_complex(), count_rowexpr_columns(), expandRecordVariable(), ExpandRowReference(), markTargetListOrigin(), ParseComplexProjection(), and unknown_attribute().

{
    while (sublevels_up-- > 0)
    {
        pstate = pstate->parentParseState;
        Assert(pstate != NULL);
    }
    Assert(varno > 0 && varno <= list_length(pstate->p_rtable));
    return rt_fetch(varno, pstate->p_rtable);
}

bool isLockedRefname ( ParseState pstate,
const char *  refname 
)

Definition at line 1559 of file parse_relation.c.

References lfirst, LockingClause::lockedRels, NIL, ParseState::p_locked_from_parent, ParseState::p_locking_clause, and RangeVar::relname.

Referenced by addRangeTableEntry(), and transformRangeSubselect().

{
    ListCell   *l;

    /*
     * If we are in a subquery specified as locked FOR UPDATE/SHARE from
     * parent level, then act as though there's a generic FOR UPDATE here.
     */
    if (pstate->p_locked_from_parent)
        return true;

    foreach(l, pstate->p_locking_clause)
    {
        LockingClause *lc = (LockingClause *) lfirst(l);

        if (lc->lockedRels == NIL)
        {
            /* all tables used in query */
            return true;
        }
        else
        {
            /* just the named tables */
            ListCell   *l2;

            foreach(l2, lc->lockedRels)
            {
                RangeVar   *thisrel = (RangeVar *) lfirst(l2);

                if (strcmp(refname, thisrel->relname) == 0)
                    return true;
            }
        }
    }
    return false;
}

bool isQueryUsingTempRelation ( Query query  ) 

Definition at line 2626 of file parse_relation.c.

References isQueryUsingTempRelation_walker(), and NULL.

Referenced by DefineView(), and transformCreateTableAsStmt().

{
    return isQueryUsingTempRelation_walker((Node *) query, NULL);
}

void markVarForSelectPriv ( ParseState pstate,
Var var,
RangeTblEntry rte 
)

Definition at line 774 of file parse_relation.c.

References Assert, IsA, markRTEForSelectPriv(), ParseState::parentParseState, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by expandRelAttrs(), ExpandSingleTable(), markRTEForSelectPriv(), scanRTEForColumn(), transformJoinUsingClause(), and transformWholeRowRef().

{
    Index       lv;

    Assert(IsA(var, Var));
    /* Find the appropriate pstate if it's an uplevel Var */
    for (lv = 0; lv < var->varlevelsup; lv++)
        pstate = pstate->parentParseState;
    markRTEForSelectPriv(pstate, rte, var->varno, var->varattno);
}

Relation parserOpenTable ( ParseState pstate,
const RangeVar relation,
int  lockmode 
)

Definition at line 925 of file parse_relation.c.

References cancel_parser_errposition_callback(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, heap_openrv_extended(), isFutureCTE(), RangeVar::location, NULL, RangeVar::relname, RangeVar::schemaname, and setup_parser_errposition_callback().

Referenced by addRangeTableEntry(), and setTargetTable().

{
    Relation    rel;
    ParseCallbackState pcbstate;

    setup_parser_errposition_callback(&pcbstate, pstate, relation->location);
    rel = heap_openrv_extended(relation, lockmode, true);
    if (rel == NULL)
    {
        if (relation->schemaname)
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_TABLE),
                     errmsg("relation \"%s.%s\" does not exist",
                            relation->schemaname, relation->relname)));
        else
        {
            /*
             * An unqualified name might have been meant as a reference to
             * some not-yet-in-scope CTE.  The bare "does not exist" message
             * has proven remarkably unhelpful for figuring out such problems,
             * so we take pains to offer a specific hint.
             */
            if (isFutureCTE(pstate, relation->relname))
                ereport(ERROR,
                        (errcode(ERRCODE_UNDEFINED_TABLE),
                         errmsg("relation \"%s\" does not exist",
                                relation->relname),
                         errdetail("There is a WITH item named \"%s\", but it cannot be referenced from this part of the query.",
                                   relation->relname),
                         errhint("Use WITH RECURSIVE, or re-order the WITH items to remove forward references.")));
            else
                ereport(ERROR,
                        (errcode(ERRCODE_UNDEFINED_TABLE),
                         errmsg("relation \"%s\" does not exist",
                                relation->relname)));
        }
    }
    cancel_parser_errposition_callback(&pcbstate);
    return rel;
}

RangeTblEntry* refnameRangeTblEntry ( ParseState pstate,
const char *  schemaname,
const char *  refname,
int  location,
int *  sublevels_up 
)

Definition at line 76 of file parse_relation.c.

References get_relname_relid(), LookupNamespaceNoError(), NULL, OidIsValid, ParseState::parentParseState, scanNameSpaceForRefname(), and scanNameSpaceForRelid().

Referenced by errorMissingRTE(), ExpandColumnRefStar(), and transformColumnRef().

{
    Oid         relId = InvalidOid;

    if (sublevels_up)
        *sublevels_up = 0;

    if (schemaname != NULL)
    {
        Oid         namespaceId;

        /*
         * We can use LookupNamespaceNoError() here because we are only
         * interested in finding existing RTEs.  Checking USAGE permission on
         * the schema is unnecessary since it would have already been checked
         * when the RTE was made.  Furthermore, we want to report "RTE not
         * found", not "no permissions for schema", if the name happens to
         * match a schema name the user hasn't got access to.
         */
        namespaceId = LookupNamespaceNoError(schemaname);
        if (!OidIsValid(namespaceId))
            return NULL;
        relId = get_relname_relid(refname, namespaceId);
        if (!OidIsValid(relId))
            return NULL;
    }

    while (pstate != NULL)
    {
        RangeTblEntry *result;

        if (OidIsValid(relId))
            result = scanNameSpaceForRelid(pstate, relId, location);
        else
            result = scanNameSpaceForRefname(pstate, refname, location);

        if (result)
            return result;

        if (sublevels_up)
            (*sublevels_up)++;
        else
            break;

        pstate = pstate->parentParseState;
    }
    return NULL;
}

int RTERangeTablePosn ( ParseState pstate,
RangeTblEntry rte,
int *  sublevels_up 
)

Definition at line 408 of file parse_relation.c.

References elog, ERROR, lfirst, NULL, ParseState::p_rtable, and ParseState::parentParseState.

Referenced by addRTEtoQuery(), ExpandAllTables(), ExpandSingleTable(), GetCTEForRTE(), make_var(), transformCurrentOfExpr(), and transformWholeRowRef().

{
    int         index;
    ListCell   *l;

    if (sublevels_up)
        *sublevels_up = 0;

    while (pstate != NULL)
    {
        index = 1;
        foreach(l, pstate->p_rtable)
        {
            if (rte == (RangeTblEntry *) lfirst(l))
                return index;
            index++;
        }
        pstate = pstate->parentParseState;
        if (sublevels_up)
            (*sublevels_up)++;
        else
            break;
    }

    elog(ERROR, "RTE not found (internal error)");
    return 0;                   /* keep compiler quiet */
}

CommonTableExpr* scanNameSpaceForCTE ( ParseState pstate,
const char *  refname,
Index ctelevelsup 
)

Definition at line 233 of file parse_relation.c.

References CommonTableExpr::ctename, lfirst, ParseState::p_ctenamespace, and ParseState::parentParseState.

Referenced by searchRangeTableForRel(), and transformFromClauseItem().

{
    Index       levelsup;

    for (levelsup = 0;
         pstate != NULL;
         pstate = pstate->parentParseState, levelsup++)
    {
        ListCell   *lc;

        foreach(lc, pstate->p_ctenamespace)
        {
            CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);

            if (strcmp(cte->ctename, refname) == 0)
            {
                *ctelevelsup = levelsup;
                return cte;
            }
        }
    }
    return NULL;
}

Node* scanRTEForColumn ( ParseState pstate,
RangeTblEntry rte,
char *  colname,
int  location 
)

Definition at line 501 of file parse_relation.c.

References ATTNUM, Alias::colnames, RangeTblEntry::eref, ereport, errcode(), errmsg(), ERROR, Int16GetDatum, InvalidAttrNumber, lfirst, make_var(), markVarForSelectPriv(), ObjectIdGetDatum, parser_errposition(), RangeTblEntry::relid, RTE_RELATION, RangeTblEntry::rtekind, SearchSysCacheExists2, specialAttNum(), and strVal.

Referenced by colNameToVar(), ParseComplexProjection(), searchRangeTableForCol(), and transformColumnRef().

{
    Node       *result = NULL;
    int         attnum = 0;
    Var        *var;
    ListCell   *c;

    /*
     * Scan the user column names (or aliases) for a match. Complain if
     * multiple matches.
     *
     * Note: eref->colnames may include entries for dropped columns, but those
     * will be empty strings that cannot match any legal SQL identifier, so we
     * don't bother to test for that case here.
     *
     * Should this somehow go wrong and we try to access a dropped column,
     * we'll still catch it by virtue of the checks in
     * get_rte_attribute_type(), which is called by make_var().  That routine
     * has to do a cache lookup anyway, so the check there is cheap.
     */
    foreach(c, rte->eref->colnames)
    {
        attnum++;
        if (strcmp(strVal(lfirst(c)), colname) == 0)
        {
            if (result)
                ereport(ERROR,
                        (errcode(ERRCODE_AMBIGUOUS_COLUMN),
                         errmsg("column reference \"%s\" is ambiguous",
                                colname),
                         parser_errposition(pstate, location)));
            var = make_var(pstate, rte, attnum, location);
            /* Require read access to the column */
            markVarForSelectPriv(pstate, var, rte);
            result = (Node *) var;
        }
    }

    /*
     * If we have a unique match, return it.  Note that this allows a user
     * alias to override a system column name (such as OID) without error.
     */
    if (result)
        return result;

    /*
     * If the RTE represents a real table, consider system column names.
     */
    if (rte->rtekind == RTE_RELATION)
    {
        /* quick check to see if name could be a system column */
        attnum = specialAttNum(colname);
        if (attnum != InvalidAttrNumber)
        {
            /* now check to see if column actually is defined */
            if (SearchSysCacheExists2(ATTNUM,
                                      ObjectIdGetDatum(rte->relid),
                                      Int16GetDatum(attnum)))
            {
                var = make_var(pstate, rte, attnum, location);
                /* Require read access to the column */
                markVarForSelectPriv(pstate, var, rte);
                result = (Node *) var;
            }
        }
    }

    return result;
}