From a2794623d292f7bbfe3134d1407281055acce584 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 28 Aug 2008 23:09:48 +0000 Subject: Extend the parser location infrastructure to include a location field in most node types used in expression trees (both before and after parse analysis). This allows us to place an error cursor in many situations where we formerly could not, because the information wasn't available beyond the very first level of parse analysis. There's a fair amount of work still to be done to persuade individual ereport() calls to actually include an error location, but this gets the initdb-forcing part of the work out of the way; and the situation is already markedly better than before for complaints about unimplementable implicit casts, such as CASE and UNION constructs with incompatible alternative data types. Per my proposal of a few days ago. --- src/backend/parser/parse_node.c | 43 +++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'src/backend/parser/parse_node.c') diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 8cc531b350a..1760e492854 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.101 2008/08/25 22:42:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.102 2008/08/28 23:09:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -117,8 +117,9 @@ parser_errposition(ParseState *pstate, int location) * Build a Var node for an attribute identified by RTE and attrno */ Var * -make_var(ParseState *pstate, RangeTblEntry *rte, int attrno) +make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location) { + Var *result; int vnum, sublevels_up; Oid vartypeid; @@ -126,7 +127,9 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno) vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod); - return makeVar(vnum, attrno, vartypeid, type_mod, sublevels_up); + result = makeVar(vnum, attrno, vartypeid, type_mod, sublevels_up); + result->location = location; + return result; } /* @@ -243,11 +246,13 @@ transformArraySubscripts(ParseState *pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST); + COERCE_IMPLICIT_CAST, + -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("array subscript must have type integer"))); + errmsg("array subscript must have type integer"), + parser_errposition(pstate, exprLocation(ai->lidx)))); } else { @@ -267,11 +272,13 @@ transformArraySubscripts(ParseState *pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST); + COERCE_IMPLICIT_CAST, + -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("array subscript must have type integer"))); + errmsg("array subscript must have type integer"), + parser_errposition(pstate, exprLocation(ai->uidx)))); upperIndexpr = lappend(upperIndexpr, subexpr); } @@ -283,20 +290,24 @@ transformArraySubscripts(ParseState *pstate, { Oid typesource = exprType(assignFrom); Oid typeneeded = isSlice ? arrayType : elementType; + Node *newFrom; - assignFrom = coerce_to_target_type(pstate, - assignFrom, typesource, - typeneeded, elementTypMod, - COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST); - if (assignFrom == NULL) + newFrom = coerce_to_target_type(pstate, + assignFrom, typesource, + typeneeded, elementTypMod, + COERCION_ASSIGNMENT, + COERCE_IMPLICIT_CAST, + -1); + if (newFrom == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array assignment requires type %s" " but expression is of type %s", format_type_be(typeneeded), format_type_be(typesource)), - errhint("You will need to rewrite or cast the expression."))); + errhint("You will need to rewrite or cast the expression."), + parser_errposition(pstate, exprLocation(assignFrom)))); + assignFrom = newFrom; } /* @@ -333,7 +344,7 @@ transformArraySubscripts(ParseState *pstate, * too many examples that fail if we try. */ Const * -make_const(Value *value) +make_const(Value *value, int location) { Datum val; int64 val64; @@ -423,6 +434,7 @@ make_const(Value *value) (Datum) 0, true, false); + con->location = location; return con; default: @@ -436,6 +448,7 @@ make_const(Value *value) val, false, typebyval); + con->location = location; return con; } -- cgit v1.2.3