aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_relation.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-09-01 20:42:46 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-09-01 20:42:46 +0000
commitb153c0920960a6059b67969469166fb29c0105d7 (patch)
tree4e7100ecdca88746c369ae2a6a43468925f3194d /src/backend/parser/parse_relation.c
parent9ac4299163247645c6e391f5f65735c6cb78ccb9 (diff)
downloadpostgresql-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.c128
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)));
}
}