#include "parser/parse_node.h"
Go to the source code of this file.
Functions | |
RangeTblEntry * | refnameRangeTblEntry (ParseState *pstate, const char *schemaname, const char *refname, int location, int *sublevels_up) |
CommonTableExpr * | scanNameSpaceForCTE (ParseState *pstate, const char *refname, Index *ctelevelsup) |
void | checkNameSpaceConflicts (ParseState *pstate, List *namespace1, List *namespace2) |
int | RTERangeTablePosn (ParseState *pstate, RangeTblEntry *rte, int *sublevels_up) |
RangeTblEntry * | GetRTEByRangeTablePosn (ParseState *pstate, int varno, int sublevels_up) |
CommonTableExpr * | GetCTEForRTE (ParseState *pstate, RangeTblEntry *rte, int rtelevelsup) |
Node * | scanRTEForColumn (ParseState *pstate, RangeTblEntry *rte, char *colname, int location) |
Node * | colNameToVar (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) |
RangeTblEntry * | addRangeTableEntry (ParseState *pstate, RangeVar *relation, Alias *alias, bool inh, bool inFromCl) |
RangeTblEntry * | addRangeTableEntryForRelation (ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl) |
RangeTblEntry * | addRangeTableEntryForSubquery (ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl) |
RangeTblEntry * | addRangeTableEntryForFunction (ParseState *pstate, char *funcname, Node *funcexpr, RangeFunction *rangefunc, bool lateral, bool inFromCl) |
RangeTblEntry * | addRangeTableEntryForValues (ParseState *pstate, List *exprs, List *collations, Alias *alias, bool lateral, bool inFromCl) |
RangeTblEntry * | addRangeTableEntryForJoin (ParseState *pstate, List *colnames, JoinType jointype, List *aliasvars, Alias *alias, bool inFromCl) |
RangeTblEntry * | addRangeTableEntryForCTE (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) |
List * | expandRelAttrs (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) |
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 | |||
) |
Definition at line 1603 of file parse_relation.c.
References lappend(), makeNode, NULL, ParseNamespaceItem::p_cols_visible, ParseState::p_joinlist, ParseNamespaceItem::p_lateral_ok, ParseNamespaceItem::p_lateral_only, ParseState::p_namespace, ParseNamespaceItem::p_rel_visible, ParseNamespaceItem::p_rte, palloc(), RTERangeTablePosn(), and RangeTblRef::rtindex.
Referenced by AddRelationNewConstraints(), ATPrepAlterColumnType(), CreateTrigger(), setTargetTable(), transformIndexStmt(), transformRuleStmt(), transformSetOperationStmt(), and transformValuesClause().
{ if (addToJoinList) { int rtindex = RTERangeTablePosn(pstate, rte, NULL); RangeTblRef *rtr = makeNode(RangeTblRef); rtr->rtindex = rtindex; pstate->p_joinlist = lappend(pstate->p_joinlist, rtr); } if (addToRelNameSpace || addToVarNameSpace) { ParseNamespaceItem *nsitem; nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem)); nsitem->p_rte = rte; nsitem->p_rel_visible = addToRelNameSpace; nsitem->p_cols_visible = addToVarNameSpace; nsitem->p_lateral_only = false; nsitem->p_lateral_ok = true; pstate->p_namespace = lappend(pstate->p_namespace, nsitem); } }
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; }
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; }
Definition at line 2512 of file parse_relation.c.
References tupleDesc::attrs, elog, ERROR, tupleDesc::natts, and RelationData::rd_att.
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; }
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; }