diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-01 20:42:46 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-01 20:42:46 +0000 |
commit | b153c0920960a6059b67969469166fb29c0105d7 (patch) | |
tree | 4e7100ecdca88746c369ae2a6a43468925f3194d /src/backend/parser/parse_relation.c | |
parent | 9ac4299163247645c6e391f5f65735c6cb78ccb9 (diff) | |
download | postgresql-b153c0920960a6059b67969469166fb29c0105d7.tar.gz postgresql-b153c0920960a6059b67969469166fb29c0105d7.zip |
Add a bunch of new error location reports to parse-analysis error messages.
There are still some weak spots around JOIN USING and relation alias lists,
but most errors reported within backend/parser/ now have locations.
Diffstat (limited to 'src/backend/parser/parse_relation.c')
-rw-r--r-- | src/backend/parser/parse_relation.c | 128 |
1 files changed, 84 insertions, 44 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index f7eb825f5d0..6accd96f0da 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.134 2008/08/28 23:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.135 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,20 +36,20 @@ bool add_missing_from; static RangeTblEntry *scanNameSpaceForRefname(ParseState *pstate, - const char *refname); -static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid); + const char *refname, int location); +static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid, + int location); static bool isLockedRel(ParseState *pstate, char *refname); static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars); static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars); static int specialAttNum(const char *attname); -static void warnAutoRange(ParseState *pstate, RangeVar *relation, - int location); +static void warnAutoRange(ParseState *pstate, RangeVar *relation); /* @@ -77,6 +77,7 @@ RangeTblEntry * refnameRangeTblEntry(ParseState *pstate, const char *schemaname, const char *refname, + int location, int *sublevels_up) { Oid relId = InvalidOid; @@ -99,9 +100,9 @@ refnameRangeTblEntry(ParseState *pstate, RangeTblEntry *result; if (OidIsValid(relId)) - result = scanNameSpaceForRelid(pstate, relId); + result = scanNameSpaceForRelid(pstate, relId, location); else - result = scanNameSpaceForRefname(pstate, refname); + result = scanNameSpaceForRefname(pstate, refname, location); if (result) return result; @@ -122,7 +123,7 @@ refnameRangeTblEntry(ParseState *pstate, * if no match. Raise error if multiple matches. */ static RangeTblEntry * -scanNameSpaceForRefname(ParseState *pstate, const char *refname) +scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location) { RangeTblEntry *result = NULL; ListCell *l; @@ -137,7 +138,8 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_ALIAS), errmsg("table reference \"%s\" is ambiguous", - refname))); + refname), + parser_errposition(pstate, location))); result = rte; } } @@ -154,7 +156,7 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname) * acts the way it does. */ static RangeTblEntry * -scanNameSpaceForRelid(ParseState *pstate, Oid relid) +scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location) { RangeTblEntry *result = NULL; ListCell *l; @@ -172,7 +174,8 @@ scanNameSpaceForRelid(ParseState *pstate, Oid relid) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_ALIAS), errmsg("table reference %u is ambiguous", - relid))); + relid), + parser_errposition(pstate, location))); result = rte; } } @@ -466,14 +469,15 @@ qualifiedNameToVar(ParseState *pstate, RangeTblEntry *rte; int sublevels_up; - rte = refnameRangeTblEntry(pstate, schemaname, refname, &sublevels_up); + rte = refnameRangeTblEntry(pstate, schemaname, refname, location, + &sublevels_up); if (rte == NULL) { if (!implicitRTEOK) return NULL; - rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname), - location); + rte = addImplicitRTE(pstate, + makeRangeVar(schemaname, refname, location)); } return scanRTEForColumn(pstate, rte, colname, location); @@ -608,6 +612,28 @@ buildScalarFunctionAlias(Node *funcexpr, char *funcname, } /* + * Open a table during parse analysis + * + * This is essentially just the same as heap_openrv(), except that it + * arranges to include the RangeVar's parse location in any resulting error. + * + * Note: properly, lockmode should be declared LOCKMODE not int, but that + * would require importing storage/lock.h into parse_relation.h. Since + * LOCKMODE is typedef'd as int anyway, that seems like overkill. + */ +Relation +parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode) +{ + Relation rel; + ParseCallbackState pcbstate; + + setup_parser_errposition_callback(&pcbstate, pstate, relation->location); + rel = heap_openrv(relation, lockmode); + cancel_parser_errposition_callback(&pcbstate); + return rel; +} + +/* * Add an entry for a relation to the pstate's range table (p_rtable). * * If pstate is NULL, we just build an RTE and return it without adding it @@ -638,7 +664,7 @@ addRangeTableEntry(ParseState *pstate, * depending on whether we're doing SELECT FOR UPDATE/SHARE. */ lockmode = isLockedRel(pstate, refname) ? RowShareLock : AccessShareLock; - rel = heap_openrv(relation, lockmode); + rel = parserOpenTable(pstate, relation, lockmode); rte->relid = RelationGetRelid(rel); /* @@ -859,14 +885,16 @@ addRangeTableEntryForFunction(ParseState *pstate, if (functypclass != TYPEFUNC_RECORD) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("a column definition list is only allowed for functions returning \"record\""))); + 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\""))); + errmsg("a column definition list is required for functions returning \"record\""), + parser_errposition(pstate, exprLocation(funcexpr)))); } if (functypclass == TYPEFUNC_COMPOSITE) @@ -901,7 +929,8 @@ addRangeTableEntryForFunction(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" cannot be declared SETOF", - attrname))); + attrname), + parser_errposition(pstate, n->typename->location))); attrtype = typenameTypeId(pstate, n->typename, &attrtypmod); eref->colnames = lappend(eref->colnames, makeString(attrname)); rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype); @@ -912,7 +941,8 @@ addRangeTableEntryForFunction(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("function \"%s\" in FROM has unsupported return type %s", - funcname, format_type_be(funcrettype)))); + funcname, format_type_be(funcrettype)), + parser_errposition(pstate, exprLocation(funcexpr)))); /*---------- * Flags: @@ -1107,9 +1137,9 @@ isLockedRel(ParseState *pstate, char *refname) foreach(l2, lc->lockedRels) { - char *rname = strVal(lfirst(l2)); + RangeVar *thisrel = (RangeVar *) lfirst(l2); - if (strcmp(refname, rname) == 0) + if (strcmp(refname, thisrel->relname) == 0) return true; } } @@ -1150,12 +1180,12 @@ addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, * a conflicting name. */ RangeTblEntry * -addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) +addImplicitRTE(ParseState *pstate, RangeVar *relation) { RangeTblEntry *rte; /* issue warning or error as needed */ - warnAutoRange(pstate, relation, location); + warnAutoRange(pstate, relation); /* * Note that we set inFromCl true, so that the RTE will be listed @@ -1179,9 +1209,9 @@ addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) * results. If include_dropped is TRUE then empty strings and NULL constants * (not Vars!) are returned for dropped columns. * - * rtindex and sublevels_up are the varno and varlevelsup values to use - * in the created Vars. Ordinarily rtindex should match the actual position - * of the RTE in its rangetable. + * rtindex, sublevels_up, and location are the varno, varlevelsup, and location + * values to use in the created Vars. Ordinarily rtindex should match the + * actual position of the RTE in its rangetable. * * The output lists go into *colnames and *colvars. * If only one of the two kinds of output list is needed, pass NULL for the @@ -1189,7 +1219,7 @@ addImplicitRTE(ParseState *pstate, RangeVar *relation, int location) */ void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars) { int varattno; @@ -1203,7 +1233,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, { case RTE_RELATION: /* Ordinary relation RTE */ - expandRelation(rte->relid, rte->eref, rtindex, sublevels_up, + expandRelation(rte->relid, rte->eref, + rtindex, sublevels_up, location, include_dropped, colnames, colvars); break; case RTE_SUBQUERY: @@ -1239,6 +1270,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprType((Node *) te->expr), exprTypmod((Node *) te->expr), sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1259,7 +1291,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, { /* Composite data type, e.g. a table's row type */ Assert(tupdesc); - expandTupleDesc(tupdesc, rte->eref, rtindex, sublevels_up, + expandTupleDesc(tupdesc, rte->eref, + rtindex, sublevels_up, location, include_dropped, colnames, colvars); } else if (functypclass == TYPEFUNC_SCALAR) @@ -1276,6 +1309,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, varnode = makeVar(rtindex, 1, funcrettype, -1, sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1302,6 +1336,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, attrtype, attrtypmod, sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } } @@ -1343,6 +1378,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprType(col), exprTypmod(col), sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } } @@ -1401,6 +1437,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprType(avar), exprTypmod(avar), sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1417,14 +1454,15 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, */ static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars) { Relation rel; /* Get the tupledesc and turn it over to expandTupleDesc */ rel = relation_open(relid, AccessShareLock); - expandTupleDesc(rel->rd_att, eref, rtindex, sublevels_up, include_dropped, + expandTupleDesc(rel->rd_att, eref, rtindex, sublevels_up, + location, include_dropped, colnames, colvars); relation_close(rel, AccessShareLock); } @@ -1435,7 +1473,7 @@ expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int rtindex, int sublevels_up, - bool include_dropped, + int location, bool include_dropped, List **colnames, List **colvars) { int maxattrs = tupdesc->natts; @@ -1482,6 +1520,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, varnode = makeVar(rtindex, attr->attnum, attr->atttypid, attr->atttypmod, sublevels_up); + varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -1491,15 +1530,15 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, /* * expandRelAttrs - * Workhorse for "*" expansion: produce a list of targetentries - * for the attributes of the rte + * for the attributes of the RTE * * As with expandRTE, rtindex/sublevels_up determine the varno/varlevelsup - * fields of the Vars produced. pstate->p_next_resno determines the resnos - * assigned to the TLEs. + * fields of the Vars produced, and location sets their location. + * pstate->p_next_resno determines the resnos assigned to the TLEs. */ List * expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, - int rtindex, int sublevels_up) + int rtindex, int sublevels_up, int location) { List *names, *vars; @@ -1507,7 +1546,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, *var; List *te_list = NIL; - expandRTE(rte, rtindex, sublevels_up, false, + expandRTE(rte, rtindex, sublevels_up, location, false, &names, &vars); forboth(name, names, var, vars) @@ -1523,7 +1562,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, te_list = lappend(te_list, te); } - Assert(name == NULL && var == NULL); /* lists not the same length? */ + Assert(name == NULL && var == NULL); /* lists not the same length? */ return te_list; } @@ -1966,7 +2005,7 @@ attnumTypeId(Relation rd, int attid) * a warning. */ static void -warnAutoRange(ParseState *pstate, RangeVar *relation, int location) +warnAutoRange(ParseState *pstate, RangeVar *relation) { RangeTblEntry *rte; int sublevels_up; @@ -1991,6 +2030,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) 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; @@ -2006,7 +2046,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) 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, location))); + parser_errposition(pstate, relation->location))); else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), @@ -2015,7 +2055,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) relation->relname) : errmsg("missing FROM-clause entry for table \"%s\"", relation->relname)), - parser_errposition(pstate, location))); + parser_errposition(pstate, relation->location))); } else { @@ -2033,6 +2073,6 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) (rte ? errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.", rte->eref->aliasname) : 0)), - parser_errposition(pstate, location))); + parser_errposition(pstate, relation->location))); } } |