Extend the parser location infrastructure to include a location field in
authorTom Lane <[email protected]>
Thu, 28 Aug 2008 23:09:48 +0000 (23:09 +0000)
committerTom Lane <[email protected]>
Thu, 28 Aug 2008 23:09:48 +0000 (23:09 +0000)
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.

44 files changed:
src/backend/catalog/heap.c
src/backend/commands/prepare.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/makefuncs.c
src/backend/nodes/nodeFuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepqual.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/var.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/parser/parse_agg.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_func.c
src/backend/parser/parse_node.c
src/backend/parser/parse_oper.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/parser/parse_utilcmd.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/include/catalog/catversion.h
src/include/nodes/makefuncs.h
src/include/nodes/nodeFuncs.h
src/include/nodes/parsenodes.h
src/include/nodes/primnodes.h
src/include/parser/parse_coerce.h
src/include/parser/parse_node.h
src/test/regress/expected/arrays.out
src/test/regress/expected/select_implicit.out
src/test/regress/expected/select_implicit_1.out
src/test/regress/expected/select_implicit_2.out
src/test/regress/expected/xml.out
src/test/regress/expected/xml_1.out

index 499929ef1028531765e54ceea36e334a6e2f567d..5b26b91b6976f35a342187899f1f59c29fb13f1f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.338 2008/08/25 22:42:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.339 2008/08/28 23:09:45 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -2121,7 +2121,8 @@ cookDefault(ParseState *pstate,
                expr = coerce_to_target_type(pstate, expr, type_id,
                                                                         atttypid, atttypmod,
                                                                         COERCION_ASSIGNMENT,
-                                                                        COERCE_IMPLICIT_CAST);
+                                                                        COERCE_IMPLICIT_CAST,
+                                                                        -1);
                if (expr == NULL)
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
index 2fca3a5e8135612101061ab978799fc528eb4799..dee994c550968b75ba83c17f9d78eb2978d3f198 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.90 2008/08/25 22:42:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.91 2008/08/28 23:09:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -353,7 +353,8 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
                expr = coerce_to_target_type(pstate, expr, given_type_id,
                                                                         expected_type_id, -1,
                                                                         COERCION_ASSIGNMENT,
-                                                                        COERCE_IMPLICIT_CAST);
+                                                                        COERCE_IMPLICIT_CAST,
+                                                                        -1);
 
                if (expr == NULL)
                        ereport(ERROR,
index a8ae2e4be129156469868e141657ec5a8d9acd98..6f2303f62cebf0fe27736a26100fbd0d0200193d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.263 2008/08/25 22:42:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.264 2008/08/28 23:09:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3649,7 +3649,8 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
                                                                                                typeOid,
                                                                                                typmod,
                                                                                                COERCION_ASSIGNMENT,
-                                                                                               COERCE_IMPLICIT_CAST);
+                                                                                               COERCE_IMPLICIT_CAST,
+                                                                                               -1);
                if (defval == NULL)             /* should not happen */
                        elog(ERROR, "failed to coerce base type to domain");
        }
@@ -5509,7 +5510,8 @@ ATPrepAlterColumnType(List **wqueue,
                                                                          transform, exprType(transform),
                                                                          targettype, targettypmod,
                                                                          COERCION_ASSIGNMENT,
-                                                                         COERCE_IMPLICIT_CAST);
+                                                                         COERCE_IMPLICIT_CAST,
+                                                                         -1);
        if (transform == NULL)
                ereport(ERROR,
                                (errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -5607,7 +5609,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
                                                                                  defaultexpr, exprType(defaultexpr),
                                                                                        targettype, targettypmod,
                                                                                        COERCION_ASSIGNMENT,
-                                                                                       COERCE_IMPLICIT_CAST);
+                                                                                       COERCE_IMPLICIT_CAST,
+                                                                                       -1);
                if (defaultexpr == NULL)
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
index ee30d32704ab7b393b459fedbac1fbd13f65d5b7..c0dc74bee79d91159f842183f2d0b8c60aa6e22a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.122 2008/07/31 16:27:16 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.123 2008/08/28 23:09:45 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -2135,6 +2135,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
        domVal = makeNode(CoerceToDomainValue);
        domVal->typeId = baseTypeOid;
        domVal->typeMod = typMod;
+       domVal->location = -1;          /* will be set when/if used */
 
        pstate->p_value_substitute = (Node *) domVal;
 
index 4a30a3d82287952e33f15dc36bfe168a18ba03f0..4e984719d3d7454d9c61bd4731293fbd23dc2583 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.401 2008/08/22 00:16:03 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.402 2008/08/28 23:09:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
                memcpy(newnode->fldname, from->fldname, _size); \
        } while (0)
 
+/* Copy a parse location field (for Copy, this is same as scalar case) */
+#define COPY_LOCATION_FIELD(fldname) \
+       (newnode->fldname = from->fldname)
+
 
 /* ****************************************************************
  *                                      plannodes.h copy functions
@@ -761,6 +765,7 @@ _copyVar(Var *from)
        COPY_SCALAR_FIELD(varlevelsup);
        COPY_SCALAR_FIELD(varnoold);
        COPY_SCALAR_FIELD(varoattno);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -797,6 +802,7 @@ _copyConst(Const *from)
 
        COPY_SCALAR_FIELD(constisnull);
        COPY_SCALAR_FIELD(constbyval);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -813,6 +819,7 @@ _copyParam(Param *from)
        COPY_SCALAR_FIELD(paramid);
        COPY_SCALAR_FIELD(paramtype);
        COPY_SCALAR_FIELD(paramtypmod);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -831,6 +838,7 @@ _copyAggref(Aggref *from)
        COPY_SCALAR_FIELD(agglevelsup);
        COPY_SCALAR_FIELD(aggstar);
        COPY_SCALAR_FIELD(aggdistinct);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -867,6 +875,7 @@ _copyFuncExpr(FuncExpr *from)
        COPY_SCALAR_FIELD(funcretset);
        COPY_SCALAR_FIELD(funcformat);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -884,6 +893,7 @@ _copyOpExpr(OpExpr *from)
        COPY_SCALAR_FIELD(opresulttype);
        COPY_SCALAR_FIELD(opretset);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -901,6 +911,7 @@ _copyDistinctExpr(DistinctExpr *from)
        COPY_SCALAR_FIELD(opresulttype);
        COPY_SCALAR_FIELD(opretset);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -917,6 +928,7 @@ _copyScalarArrayOpExpr(ScalarArrayOpExpr *from)
        COPY_SCALAR_FIELD(opfuncid);
        COPY_SCALAR_FIELD(useOr);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -931,6 +943,7 @@ _copyBoolExpr(BoolExpr *from)
 
        COPY_SCALAR_FIELD(boolop);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -947,6 +960,7 @@ _copySubLink(SubLink *from)
        COPY_NODE_FIELD(testexpr);
        COPY_NODE_FIELD(operName);
        COPY_NODE_FIELD(subselect);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1032,6 +1046,7 @@ _copyRelabelType(RelabelType *from)
        COPY_SCALAR_FIELD(resulttype);
        COPY_SCALAR_FIELD(resulttypmod);
        COPY_SCALAR_FIELD(relabelformat);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1047,6 +1062,7 @@ _copyCoerceViaIO(CoerceViaIO *from)
        COPY_NODE_FIELD(arg);
        COPY_SCALAR_FIELD(resulttype);
        COPY_SCALAR_FIELD(coerceformat);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1065,6 +1081,7 @@ _copyArrayCoerceExpr(ArrayCoerceExpr *from)
        COPY_SCALAR_FIELD(resulttypmod);
        COPY_SCALAR_FIELD(isExplicit);
        COPY_SCALAR_FIELD(coerceformat);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1080,6 +1097,7 @@ _copyConvertRowtypeExpr(ConvertRowtypeExpr *from)
        COPY_NODE_FIELD(arg);
        COPY_SCALAR_FIELD(resulttype);
        COPY_SCALAR_FIELD(convertformat);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1096,6 +1114,7 @@ _copyCaseExpr(CaseExpr *from)
        COPY_NODE_FIELD(arg);
        COPY_NODE_FIELD(args);
        COPY_NODE_FIELD(defresult);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1110,6 +1129,7 @@ _copyCaseWhen(CaseWhen *from)
 
        COPY_NODE_FIELD(expr);
        COPY_NODE_FIELD(result);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1140,6 +1160,7 @@ _copyArrayExpr(ArrayExpr *from)
        COPY_SCALAR_FIELD(element_typeid);
        COPY_NODE_FIELD(elements);
        COPY_SCALAR_FIELD(multidims);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1155,6 +1176,7 @@ _copyRowExpr(RowExpr *from)
        COPY_NODE_FIELD(args);
        COPY_SCALAR_FIELD(row_typeid);
        COPY_SCALAR_FIELD(row_format);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1186,6 +1208,7 @@ _copyCoalesceExpr(CoalesceExpr *from)
 
        COPY_SCALAR_FIELD(coalescetype);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1201,6 +1224,7 @@ _copyMinMaxExpr(MinMaxExpr *from)
        COPY_SCALAR_FIELD(minmaxtype);
        COPY_SCALAR_FIELD(op);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1221,6 +1245,7 @@ _copyXmlExpr(XmlExpr *from)
        COPY_SCALAR_FIELD(xmloption);
        COPY_SCALAR_FIELD(type);
        COPY_SCALAR_FIELD(typmod);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1238,6 +1263,7 @@ _copyNullIfExpr(NullIfExpr *from)
        COPY_SCALAR_FIELD(opresulttype);
        COPY_SCALAR_FIELD(opretset);
        COPY_NODE_FIELD(args);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1282,6 +1308,7 @@ _copyCoerceToDomain(CoerceToDomain *from)
        COPY_SCALAR_FIELD(resulttype);
        COPY_SCALAR_FIELD(resulttypmod);
        COPY_SCALAR_FIELD(coercionformat);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1296,6 +1323,7 @@ _copyCoerceToDomainValue(CoerceToDomainValue *from)
 
        COPY_SCALAR_FIELD(typeId);
        COPY_SCALAR_FIELD(typeMod);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1310,6 +1338,7 @@ _copySetToDefault(SetToDefault *from)
 
        COPY_SCALAR_FIELD(typeId);
        COPY_SCALAR_FIELD(typeMod);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1595,7 +1624,7 @@ _copyAExpr(A_Expr *from)
        COPY_NODE_FIELD(name);
        COPY_NODE_FIELD(lexpr);
        COPY_NODE_FIELD(rexpr);
-       COPY_SCALAR_FIELD(location);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1606,7 +1635,7 @@ _copyColumnRef(ColumnRef *from)
        ColumnRef  *newnode = makeNode(ColumnRef);
 
        COPY_NODE_FIELD(fields);
-       COPY_SCALAR_FIELD(location);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1617,6 +1646,7 @@ _copyParamRef(ParamRef *from)
        ParamRef   *newnode = makeNode(ParamRef);
 
        COPY_SCALAR_FIELD(number);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1647,6 +1677,8 @@ _copyAConst(A_Const *from)
                        break;
        }
 
+       COPY_LOCATION_FIELD(location);
+
        return newnode;
 }
 
@@ -1660,7 +1692,7 @@ _copyFuncCall(FuncCall *from)
        COPY_SCALAR_FIELD(agg_star);
        COPY_SCALAR_FIELD(agg_distinct);
        COPY_SCALAR_FIELD(func_variadic);
-       COPY_SCALAR_FIELD(location);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1693,6 +1725,7 @@ _copyA_ArrayExpr(A_ArrayExpr *from)
        A_ArrayExpr  *newnode = makeNode(A_ArrayExpr);
 
        COPY_NODE_FIELD(elements);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1705,7 +1738,7 @@ _copyResTarget(ResTarget *from)
        COPY_STRING_FIELD(name);
        COPY_NODE_FIELD(indirection);
        COPY_NODE_FIELD(val);
-       COPY_SCALAR_FIELD(location);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1722,7 +1755,7 @@ _copyTypeName(TypeName *from)
        COPY_NODE_FIELD(typmods);
        COPY_SCALAR_FIELD(typemod);
        COPY_NODE_FIELD(arrayBounds);
-       COPY_SCALAR_FIELD(location);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1770,6 +1803,7 @@ _copyTypeCast(TypeCast *from)
 
        COPY_NODE_FIELD(arg);
        COPY_NODE_FIELD(typename);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
@@ -1852,6 +1886,7 @@ _copyXmlSerialize(XmlSerialize *from)
        COPY_SCALAR_FIELD(xmloption);
        COPY_NODE_FIELD(expr);
        COPY_NODE_FIELD(typename);
+       COPY_LOCATION_FIELD(location);
 
        return newnode;
 }
index 3a25111c60c7f776141634d0e930dd657a771e79..3d130c9524aa6e6b2ba46b7d1d46f1707ce8950d 100644 (file)
  * Currently, in fact, equal() doesn't know how to compare Plan trees
  * either.     This might need to be fixed someday.
  *
+ * NOTE: it is intentional that parse location fields (in nodes that have
+ * one) are not compared.  This is because we want, for example, a variable
+ * "x" to be considered equal() to another reference to "x" in the query.
+ *
  *
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.328 2008/08/22 00:16:03 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.329 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
                        return false; \
        } while (0)
 
+/* Compare a parse location field (this is a no-op, per note above) */
+#define COMPARE_LOCATION_FIELD(fldname) \
+       ((void) 0)
+
 
 /*
  *     Stuff from primnodes.h
@@ -131,6 +139,7 @@ _equalVar(Var *a, Var *b)
        COMPARE_SCALAR_FIELD(varlevelsup);
        COMPARE_SCALAR_FIELD(varnoold);
        COMPARE_SCALAR_FIELD(varoattno);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -143,6 +152,7 @@ _equalConst(Const *a, Const *b)
        COMPARE_SCALAR_FIELD(constlen);
        COMPARE_SCALAR_FIELD(constisnull);
        COMPARE_SCALAR_FIELD(constbyval);
+       COMPARE_LOCATION_FIELD(location);
 
        /*
         * We treat all NULL constants of the same type as equal. Someday this
@@ -161,6 +171,7 @@ _equalParam(Param *a, Param *b)
        COMPARE_SCALAR_FIELD(paramid);
        COMPARE_SCALAR_FIELD(paramtype);
        COMPARE_SCALAR_FIELD(paramtypmod);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -174,6 +185,7 @@ _equalAggref(Aggref *a, Aggref *b)
        COMPARE_SCALAR_FIELD(agglevelsup);
        COMPARE_SCALAR_FIELD(aggstar);
        COMPARE_SCALAR_FIELD(aggdistinct);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -209,6 +221,7 @@ _equalFuncExpr(FuncExpr *a, FuncExpr *b)
                return false;
 
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -232,6 +245,7 @@ _equalOpExpr(OpExpr *a, OpExpr *b)
        COMPARE_SCALAR_FIELD(opresulttype);
        COMPARE_SCALAR_FIELD(opretset);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -255,6 +269,7 @@ _equalDistinctExpr(DistinctExpr *a, DistinctExpr *b)
        COMPARE_SCALAR_FIELD(opresulttype);
        COMPARE_SCALAR_FIELD(opretset);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -277,6 +292,7 @@ _equalScalarArrayOpExpr(ScalarArrayOpExpr *a, ScalarArrayOpExpr *b)
 
        COMPARE_SCALAR_FIELD(useOr);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -286,6 +302,7 @@ _equalBoolExpr(BoolExpr *a, BoolExpr *b)
 {
        COMPARE_SCALAR_FIELD(boolop);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -297,6 +314,7 @@ _equalSubLink(SubLink *a, SubLink *b)
        COMPARE_NODE_FIELD(testexpr);
        COMPARE_NODE_FIELD(operName);
        COMPARE_NODE_FIELD(subselect);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -366,6 +384,8 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
                b->relabelformat != COERCE_DONTCARE)
                return false;
 
+       COMPARE_LOCATION_FIELD(location);
+
        return true;
 }
 
@@ -384,6 +404,8 @@ _equalCoerceViaIO(CoerceViaIO *a, CoerceViaIO *b)
                b->coerceformat != COERCE_DONTCARE)
                return false;
 
+       COMPARE_LOCATION_FIELD(location);
+
        return true;
 }
 
@@ -405,6 +427,8 @@ _equalArrayCoerceExpr(ArrayCoerceExpr *a, ArrayCoerceExpr *b)
                b->coerceformat != COERCE_DONTCARE)
                return false;
 
+       COMPARE_LOCATION_FIELD(location);
+
        return true;
 }
 
@@ -423,6 +447,8 @@ _equalConvertRowtypeExpr(ConvertRowtypeExpr *a, ConvertRowtypeExpr *b)
                b->convertformat != COERCE_DONTCARE)
                return false;
 
+       COMPARE_LOCATION_FIELD(location);
+
        return true;
 }
 
@@ -433,6 +459,7 @@ _equalCaseExpr(CaseExpr *a, CaseExpr *b)
        COMPARE_NODE_FIELD(arg);
        COMPARE_NODE_FIELD(args);
        COMPARE_NODE_FIELD(defresult);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -442,6 +469,7 @@ _equalCaseWhen(CaseWhen *a, CaseWhen *b)
 {
        COMPARE_NODE_FIELD(expr);
        COMPARE_NODE_FIELD(result);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -462,6 +490,7 @@ _equalArrayExpr(ArrayExpr *a, ArrayExpr *b)
        COMPARE_SCALAR_FIELD(element_typeid);
        COMPARE_NODE_FIELD(elements);
        COMPARE_SCALAR_FIELD(multidims);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -481,6 +510,8 @@ _equalRowExpr(RowExpr *a, RowExpr *b)
                b->row_format != COERCE_DONTCARE)
                return false;
 
+       COMPARE_LOCATION_FIELD(location);
+
        return true;
 }
 
@@ -501,6 +532,7 @@ _equalCoalesceExpr(CoalesceExpr *a, CoalesceExpr *b)
 {
        COMPARE_SCALAR_FIELD(coalescetype);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -511,6 +543,7 @@ _equalMinMaxExpr(MinMaxExpr *a, MinMaxExpr *b)
        COMPARE_SCALAR_FIELD(minmaxtype);
        COMPARE_SCALAR_FIELD(op);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -526,6 +559,7 @@ _equalXmlExpr(XmlExpr *a, XmlExpr *b)
        COMPARE_SCALAR_FIELD(xmloption);
        COMPARE_SCALAR_FIELD(type);
        COMPARE_SCALAR_FIELD(typmod);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -549,6 +583,7 @@ _equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
        COMPARE_SCALAR_FIELD(opresulttype);
        COMPARE_SCALAR_FIELD(opretset);
        COMPARE_NODE_FIELD(args);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -587,6 +622,8 @@ _equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b)
                b->coercionformat != COERCE_DONTCARE)
                return false;
 
+       COMPARE_LOCATION_FIELD(location);
+
        return true;
 }
 
@@ -595,6 +632,7 @@ _equalCoerceToDomainValue(CoerceToDomainValue *a, CoerceToDomainValue *b)
 {
        COMPARE_SCALAR_FIELD(typeId);
        COMPARE_SCALAR_FIELD(typeMod);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -604,6 +642,7 @@ _equalSetToDefault(SetToDefault *a, SetToDefault *b)
 {
        COMPARE_SCALAR_FIELD(typeId);
        COMPARE_SCALAR_FIELD(typeMod);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1680,7 +1719,7 @@ _equalAExpr(A_Expr *a, A_Expr *b)
        COMPARE_NODE_FIELD(name);
        COMPARE_NODE_FIELD(lexpr);
        COMPARE_NODE_FIELD(rexpr);
-       COMPARE_SCALAR_FIELD(location);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1689,7 +1728,7 @@ static bool
 _equalColumnRef(ColumnRef *a, ColumnRef *b)
 {
        COMPARE_NODE_FIELD(fields);
-       COMPARE_SCALAR_FIELD(location);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1698,6 +1737,7 @@ static bool
 _equalParamRef(ParamRef *a, ParamRef *b)
 {
        COMPARE_SCALAR_FIELD(number);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1707,6 +1747,7 @@ _equalAConst(A_Const *a, A_Const *b)
 {
        if (!equal(&a->val, &b->val))           /* hack for in-line Value field */
                return false;
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1719,7 +1760,7 @@ _equalFuncCall(FuncCall *a, FuncCall *b)
        COMPARE_SCALAR_FIELD(agg_star);
        COMPARE_SCALAR_FIELD(agg_distinct);
        COMPARE_SCALAR_FIELD(func_variadic);
-       COMPARE_SCALAR_FIELD(location);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1746,6 +1787,7 @@ static bool
 _equalA_ArrayExpr(A_ArrayExpr *a, A_ArrayExpr *b)
 {
        COMPARE_NODE_FIELD(elements);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1756,7 +1798,7 @@ _equalResTarget(ResTarget *a, ResTarget *b)
        COMPARE_STRING_FIELD(name);
        COMPARE_NODE_FIELD(indirection);
        COMPARE_NODE_FIELD(val);
-       COMPARE_SCALAR_FIELD(location);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1771,7 +1813,7 @@ _equalTypeName(TypeName *a, TypeName *b)
        COMPARE_NODE_FIELD(typmods);
        COMPARE_SCALAR_FIELD(typemod);
        COMPARE_NODE_FIELD(arrayBounds);
-       COMPARE_SCALAR_FIELD(location);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1781,6 +1823,7 @@ _equalTypeCast(TypeCast *a, TypeCast *b)
 {
        COMPARE_NODE_FIELD(arg);
        COMPARE_NODE_FIELD(typename);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
@@ -1941,6 +1984,7 @@ _equalXmlSerialize(XmlSerialize *a, XmlSerialize *b)
        COMPARE_SCALAR_FIELD(xmloption);
        COMPARE_NODE_FIELD(expr);
        COMPARE_NODE_FIELD(typename);
+       COMPARE_LOCATION_FIELD(location);
 
        return true;
 }
index 228bf5ea91545c28afa407944c07a6c17ecfd243..5ab853c37bf62f897bba977a399e842e2ccc2f76 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.58 2008/01/01 19:45:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.59 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -84,6 +84,9 @@ makeVar(Index varno,
        var->varnoold = varno;
        var->varoattno = varattno;
 
+       /* Likewise, we just set location to "unknown" here */
+       var->location = -1;
+
        return var;
 }
 
@@ -168,6 +171,7 @@ makeConst(Oid consttype,
        cnst->constvalue = constvalue;
        cnst->constisnull = constisnull;
        cnst->constbyval = constbyval;
+       cnst->location = -1;            /* "unknown" */
 
        return cnst;
 }
@@ -211,12 +215,13 @@ makeBoolConst(bool value, bool isnull)
  *       creates a BoolExpr node
  */
 Expr *
-makeBoolExpr(BoolExprType boolop, List *args)
+makeBoolExpr(BoolExprType boolop, List *args, int location)
 {
        BoolExpr   *b = makeNode(BoolExpr);
 
        b->boolop = boolop;
        b->args = args;
+       b->location = location;
 
        return (Expr *) b;
 }
@@ -251,6 +256,7 @@ makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, CoercionForm rformat)
        r->resulttype = rtype;
        r->resulttypmod = rtypmod;
        r->relabelformat = rformat;
+       r->location = -1;
 
        return r;
 }
@@ -336,6 +342,7 @@ makeFuncExpr(Oid funcid, Oid rettype, List *args, CoercionForm fformat)
        funcexpr->funcretset = false;           /* only allowed case here */
        funcexpr->funcformat = fformat;
        funcexpr->args = args;
+       funcexpr->location = -1;
 
        return funcexpr;
 }
index 7944936ba6edb567f08706ba66b107f624325a31..fa1bb347b903bcbfd7c9d0296d9ab55320c02474 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.30 2008/08/25 22:42:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.31 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 
 
 static bool expression_returns_set_walker(Node *node, void *context);
+static int     leftmostLoc(int loc1, int loc2);
 
 
 /*
@@ -574,6 +575,315 @@ expression_returns_set_walker(Node *node, void *context)
 }
 
 
+/*
+ *     exprLocation -
+ *       returns the parse location of an expression tree, for error reports
+ *
+ * -1 is returned if the location can't be determined.
+ *
+ * For expressions larger than a single token, the intent here is to
+ * return the location of the expression's leftmost token, not necessarily
+ * the topmost Node's location field.  For example, an OpExpr's location
+ * field will point at the operator name, but if it is not a prefix operator
+ * then we should return the location of the left-hand operand instead.
+ * The reason is that we want to reference the entire expression not just
+ * that operator, and pointing to its start seems to be the most natural way.
+ *
+ * The location is not perfect --- for example, since the grammar doesn't
+ * explicitly represent parentheses in the parsetree, given something that
+ * had been written "(a + b) * c" we are going to point at "a" not "(".
+ * But it should be plenty good enough for error reporting purposes.
+ *
+ * You might think that this code is overly general, for instance why check
+ * the operands of a FuncExpr node, when the function name can be expected
+ * to be to the left of them?  There are a couple of reasons.  The grammar
+ * sometimes builds expressions that aren't quite what the user wrote;
+ * for instance x IS NOT BETWEEN ... becomes a NOT-expression whose keyword
+ * pointer is to the right of its leftmost argument.  Also, nodes that were
+ * inserted implicitly by parse analysis (such as FuncExprs for implicit
+ * coercions) will have location -1, and so we can have odd combinations of
+ * known and unknown locations in a tree.
+ */
+int
+exprLocation(Node *expr)
+{
+       int                     loc;
+
+       if (expr == NULL)
+               return -1;
+       switch (nodeTag(expr))
+       {
+               case T_Var:
+                       loc = ((Var *) expr)->location;
+                       break;
+               case T_Const:
+                       loc = ((Const *) expr)->location;
+                       break;
+               case T_Param:
+                       loc = ((Param *) expr)->location;
+                       break;
+               case T_Aggref:
+                       /* function name should always be the first thing */
+                       loc = ((Aggref *) expr)->location;
+                       break;
+               case T_ArrayRef:
+                       /* just use array argument's location */
+                       loc = exprLocation((Node *) ((ArrayRef *) expr)->refexpr);
+                       break;
+               case T_FuncExpr:
+                       {
+                               FuncExpr   *fexpr = (FuncExpr *) expr;
+
+                               /* consider both function name and leftmost arg */
+                               loc = leftmostLoc(fexpr->location,
+                                                                 exprLocation((Node *) fexpr->args));
+                       }
+                       break;
+               case T_OpExpr:
+               case T_DistinctExpr:    /* struct-equivalent to OpExpr */
+               case T_NullIfExpr:              /* struct-equivalent to OpExpr */
+                       {
+                               OpExpr   *opexpr = (OpExpr *) expr;
+
+                               /* consider both operator name and leftmost arg */
+                               loc = leftmostLoc(opexpr->location,
+                                                                 exprLocation((Node *) opexpr->args));
+                       }
+                       break;
+               case T_ScalarArrayOpExpr:
+                       {
+                               ScalarArrayOpExpr *saopexpr = (ScalarArrayOpExpr *) expr;
+
+                               /* consider both operator name and leftmost arg */
+                               loc = leftmostLoc(saopexpr->location,
+                                                                 exprLocation((Node *) saopexpr->args));
+                       }
+                       break;
+               case T_BoolExpr:
+                       {
+                               BoolExpr   *bexpr = (BoolExpr *) expr;
+
+                               /*
+                                * Same as above, to handle either NOT or AND/OR.  We can't
+                                * special-case NOT because of the way that it's used for
+                                * things like IS NOT BETWEEN.
+                                */
+                               loc = leftmostLoc(bexpr->location,
+                                                                 exprLocation((Node *) bexpr->args));
+                       }
+                       break;
+               case T_SubLink:
+                       {
+                               SubLink *sublink = (SubLink *) expr;
+
+                               /* check the testexpr, if any, and the operator/keyword */
+                               loc = leftmostLoc(exprLocation(sublink->testexpr),
+                                                                 sublink->location);
+                       }
+                       break;
+               case T_FieldSelect:
+                       /* just use argument's location */
+                       loc = exprLocation((Node *) ((FieldSelect *) expr)->arg);
+                       break;
+               case T_FieldStore:
+                       /* just use argument's location */
+                       loc = exprLocation((Node *) ((FieldStore *) expr)->arg);
+                       break;
+               case T_RelabelType:
+                       {
+                               RelabelType *rexpr = (RelabelType *) expr;
+
+                               /* Much as above */
+                               loc = leftmostLoc(rexpr->location,
+                                                                 exprLocation((Node *) rexpr->arg));
+                       }
+                       break;
+               case T_CoerceViaIO:
+                       {
+                               CoerceViaIO *cexpr = (CoerceViaIO *) expr;
+
+                               /* Much as above */
+                               loc = leftmostLoc(cexpr->location,
+                                                                 exprLocation((Node *) cexpr->arg));
+                       }
+                       break;
+               case T_ArrayCoerceExpr:
+                       {
+                               ArrayCoerceExpr *cexpr = (ArrayCoerceExpr *) expr;
+
+                               /* Much as above */
+                               loc = leftmostLoc(cexpr->location,
+                                                                 exprLocation((Node *) cexpr->arg));
+                       }
+                       break;
+               case T_ConvertRowtypeExpr:
+                       {
+                               ConvertRowtypeExpr *cexpr = (ConvertRowtypeExpr *) expr;
+
+                               /* Much as above */
+                               loc = leftmostLoc(cexpr->location,
+                                                                 exprLocation((Node *) cexpr->arg));
+                       }
+                       break;
+               case T_CaseExpr:
+                       /* CASE keyword should always be the first thing */
+                       loc = ((CaseExpr *) expr)->location;
+                       break;
+               case T_CaseWhen:
+                       /* WHEN keyword should always be the first thing */
+                       loc = ((CaseWhen *) expr)->location;
+                       break;
+               case T_ArrayExpr:
+                       /* the location points at ARRAY or [, which must be leftmost */
+                       loc = ((ArrayExpr *) expr)->location;
+                       break;
+               case T_RowExpr:
+                       /* the location points at ROW or (, which must be leftmost */
+                       loc = ((RowExpr *) expr)->location;
+                       break;
+               case T_RowCompareExpr:
+                       /* just use leftmost argument's location */
+                       loc = exprLocation((Node *) ((RowCompareExpr *) expr)->largs);
+                       break;
+               case T_CoalesceExpr:
+                       /* COALESCE keyword should always be the first thing */
+                       loc = ((CoalesceExpr *) expr)->location;
+                       break;
+               case T_MinMaxExpr:
+                       /* GREATEST/LEAST keyword should always be the first thing */
+                       loc = ((MinMaxExpr *) expr)->location;
+                       break;
+               case T_XmlExpr:
+                       {
+                               XmlExpr   *xexpr = (XmlExpr *) expr;
+
+                               /* consider both function name and leftmost arg */
+                               loc = leftmostLoc(xexpr->location,
+                                                                 exprLocation((Node *) xexpr->args));
+                       }
+                       break;
+               case T_NullTest:
+                       /* just use argument's location */
+                       loc = exprLocation((Node *) ((NullTest *) expr)->arg);
+                       break;
+               case T_BooleanTest:
+                       /* just use argument's location */
+                       loc = exprLocation((Node *) ((BooleanTest *) expr)->arg);
+                       break;
+               case T_CoerceToDomain:
+                       {
+                               CoerceToDomain *cexpr = (CoerceToDomain *) expr;
+
+                               /* Much as above */
+                               loc = leftmostLoc(cexpr->location,
+                                                                 exprLocation((Node *) cexpr->arg));
+                       }
+                       break;
+               case T_CoerceToDomainValue:
+                       loc = ((CoerceToDomainValue *) expr)->location;
+                       break;
+               case T_SetToDefault:
+                       loc = ((SetToDefault *) expr)->location;
+                       break;
+               case T_TargetEntry:
+                       /* just use argument's location */
+                       loc = exprLocation((Node *) ((TargetEntry *) expr)->expr);
+                       break;
+               case T_List:
+                       {
+                               /* report location of first list member that has a location */
+                               ListCell   *lc;
+
+                               loc = -1;               /* just to suppress compiler warning */
+                               foreach(lc, (List *) expr)
+                               {
+                                       loc = exprLocation((Node *) lfirst(lc));
+                                       if (loc >= 0)
+                                               break;
+                               }
+                       }
+                       break;
+               case T_A_Expr:
+                       {
+                               A_Expr *aexpr = (A_Expr *) expr;
+
+                               /* use leftmost of operator or left operand (if any) */
+                               /* we assume right operand can't be to left of operator */
+                               loc = leftmostLoc(aexpr->location,
+                                                                 exprLocation(aexpr->lexpr));
+                       }
+                       break;
+               case T_ColumnRef:
+                       loc = ((ColumnRef *) expr)->location;
+                       break;
+               case T_ParamRef:
+                       loc = ((ParamRef *) expr)->location;
+                       break;
+               case T_A_Const:
+                       loc = ((A_Const *) expr)->location;
+                       break;
+               case T_FuncCall:
+                       {
+                               FuncCall *fc = (FuncCall *) expr;
+
+                               /* consider both function name and leftmost arg */
+                               loc = leftmostLoc(fc->location,
+                                                                 exprLocation((Node *) fc->args));
+                       }
+                       break;
+               case T_A_ArrayExpr:
+                       /* the location points at ARRAY or [, which must be leftmost */
+                       loc = ((A_ArrayExpr *) expr)->location;
+                       break;
+               case T_ResTarget:
+                       /* we need not examine the contained expression (if any) */
+                       loc = ((ResTarget *) expr)->location;
+                       break;
+               case T_TypeCast:
+                       {
+                               TypeCast *tc = (TypeCast *) expr;
+
+                               /*
+                                * This could represent CAST(), ::, or TypeName 'literal',
+                                * so any of the components might be leftmost.
+                                */
+                               loc = exprLocation(tc->arg);
+                               loc = leftmostLoc(loc, tc->typename->location);
+                               loc = leftmostLoc(loc, tc->location);
+                       }
+                       break;
+               case T_TypeName:
+                       loc = ((TypeName *) expr)->location;
+                       break;
+               case T_XmlSerialize:
+                       /* XMLSERIALIZE keyword should always be the first thing */
+                       loc = ((XmlSerialize *) expr)->location;
+                       break;
+               default:
+                       /* for any other node type it's just unknown... */
+                       loc = -1;
+                       break;
+       }
+       return loc;
+}
+
+/*
+ * leftmostLoc - support for exprLocation
+ *
+ * Take the minimum of two parse location values, but ignore unknowns
+ */
+static int
+leftmostLoc(int loc1, int loc2)
+{
+       if (loc1 < 0)
+               return loc2;
+       else if (loc2 < 0)
+               return loc1;
+       else
+               return Min(loc1, loc2);
+}
+
+
 /*
  * Standard expression-tree walking support
  *
index 76f8da1babe7b5b3421296e5f9f184ddf5a247c3..91fa30ae2326a352db21688591e1f95181891c7d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.335 2008/08/22 00:16:03 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.336 2008/08/28 23:09:46 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
        (appendStringInfo(str, " :" CppAsString(fldname) " "), \
         _outToken(str, node->fldname))
 
+/* Write a parse location field (actually same as INT case) */
+#define WRITE_LOCATION_FIELD(fldname) \
+       appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
+
 /* Write a Node field */
 #define WRITE_NODE_FIELD(fldname) \
        (appendStringInfo(str, " :" CppAsString(fldname) " "), \
@@ -689,6 +693,7 @@ _outVar(StringInfo str, Var *node)
        WRITE_UINT_FIELD(varlevelsup);
        WRITE_UINT_FIELD(varnoold);
        WRITE_INT_FIELD(varoattno);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -701,6 +706,7 @@ _outConst(StringInfo str, Const *node)
        WRITE_INT_FIELD(constlen);
        WRITE_BOOL_FIELD(constbyval);
        WRITE_BOOL_FIELD(constisnull);
+       WRITE_LOCATION_FIELD(location);
 
        appendStringInfo(str, " :constvalue ");
        if (node->constisnull)
@@ -718,6 +724,7 @@ _outParam(StringInfo str, Param *node)
        WRITE_INT_FIELD(paramid);
        WRITE_OID_FIELD(paramtype);
        WRITE_INT_FIELD(paramtypmod);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -731,6 +738,7 @@ _outAggref(StringInfo str, Aggref *node)
        WRITE_UINT_FIELD(agglevelsup);
        WRITE_BOOL_FIELD(aggstar);
        WRITE_BOOL_FIELD(aggdistinct);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -757,6 +765,7 @@ _outFuncExpr(StringInfo str, FuncExpr *node)
        WRITE_BOOL_FIELD(funcretset);
        WRITE_ENUM_FIELD(funcformat, CoercionForm);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -769,6 +778,7 @@ _outOpExpr(StringInfo str, OpExpr *node)
        WRITE_OID_FIELD(opresulttype);
        WRITE_BOOL_FIELD(opretset);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -781,6 +791,7 @@ _outDistinctExpr(StringInfo str, DistinctExpr *node)
        WRITE_OID_FIELD(opresulttype);
        WRITE_BOOL_FIELD(opretset);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -792,6 +803,7 @@ _outScalarArrayOpExpr(StringInfo str, ScalarArrayOpExpr *node)
        WRITE_OID_FIELD(opfuncid);
        WRITE_BOOL_FIELD(useOr);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -818,6 +830,7 @@ _outBoolExpr(StringInfo str, BoolExpr *node)
        _outToken(str, opstr);
 
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -829,6 +842,7 @@ _outSubLink(StringInfo str, SubLink *node)
        WRITE_NODE_FIELD(testexpr);
        WRITE_NODE_FIELD(operName);
        WRITE_NODE_FIELD(subselect);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -889,6 +903,7 @@ _outRelabelType(StringInfo str, RelabelType *node)
        WRITE_OID_FIELD(resulttype);
        WRITE_INT_FIELD(resulttypmod);
        WRITE_ENUM_FIELD(relabelformat, CoercionForm);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -899,6 +914,7 @@ _outCoerceViaIO(StringInfo str, CoerceViaIO *node)
        WRITE_NODE_FIELD(arg);
        WRITE_OID_FIELD(resulttype);
        WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -912,6 +928,7 @@ _outArrayCoerceExpr(StringInfo str, ArrayCoerceExpr *node)
        WRITE_INT_FIELD(resulttypmod);
        WRITE_BOOL_FIELD(isExplicit);
        WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -922,6 +939,7 @@ _outConvertRowtypeExpr(StringInfo str, ConvertRowtypeExpr *node)
        WRITE_NODE_FIELD(arg);
        WRITE_OID_FIELD(resulttype);
        WRITE_ENUM_FIELD(convertformat, CoercionForm);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -933,6 +951,7 @@ _outCaseExpr(StringInfo str, CaseExpr *node)
        WRITE_NODE_FIELD(arg);
        WRITE_NODE_FIELD(args);
        WRITE_NODE_FIELD(defresult);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -942,6 +961,7 @@ _outCaseWhen(StringInfo str, CaseWhen *node)
 
        WRITE_NODE_FIELD(expr);
        WRITE_NODE_FIELD(result);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -962,6 +982,7 @@ _outArrayExpr(StringInfo str, ArrayExpr *node)
        WRITE_OID_FIELD(element_typeid);
        WRITE_NODE_FIELD(elements);
        WRITE_BOOL_FIELD(multidims);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -972,6 +993,7 @@ _outRowExpr(StringInfo str, RowExpr *node)
        WRITE_NODE_FIELD(args);
        WRITE_OID_FIELD(row_typeid);
        WRITE_ENUM_FIELD(row_format, CoercionForm);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -993,6 +1015,7 @@ _outCoalesceExpr(StringInfo str, CoalesceExpr *node)
 
        WRITE_OID_FIELD(coalescetype);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1003,6 +1026,7 @@ _outMinMaxExpr(StringInfo str, MinMaxExpr *node)
        WRITE_OID_FIELD(minmaxtype);
        WRITE_ENUM_FIELD(op, MinMaxOp);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1018,6 +1042,7 @@ _outXmlExpr(StringInfo str, XmlExpr *node)
        WRITE_ENUM_FIELD(xmloption, XmlOptionType);
        WRITE_OID_FIELD(type);
        WRITE_INT_FIELD(typmod);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1030,6 +1055,7 @@ _outNullIfExpr(StringInfo str, NullIfExpr *node)
        WRITE_OID_FIELD(opresulttype);
        WRITE_BOOL_FIELD(opretset);
        WRITE_NODE_FIELD(args);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1059,6 +1085,7 @@ _outCoerceToDomain(StringInfo str, CoerceToDomain *node)
        WRITE_OID_FIELD(resulttype);
        WRITE_INT_FIELD(resulttypmod);
        WRITE_ENUM_FIELD(coercionformat, CoercionForm);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1068,6 +1095,7 @@ _outCoerceToDomainValue(StringInfo str, CoerceToDomainValue *node)
 
        WRITE_OID_FIELD(typeId);
        WRITE_INT_FIELD(typeMod);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1077,6 +1105,7 @@ _outSetToDefault(StringInfo str, SetToDefault *node)
 
        WRITE_OID_FIELD(typeId);
        WRITE_INT_FIELD(typeMod);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1626,7 +1655,7 @@ _outFuncCall(StringInfo str, FuncCall *node)
        WRITE_BOOL_FIELD(agg_star);
        WRITE_BOOL_FIELD(agg_distinct);
        WRITE_BOOL_FIELD(func_variadic);
-       WRITE_INT_FIELD(location);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1656,6 +1685,7 @@ _outXmlSerialize(StringInfo str, XmlSerialize *node)
        WRITE_ENUM_FIELD(xmloption, XmlOptionType);
        WRITE_NODE_FIELD(expr);
        WRITE_NODE_FIELD(typename);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1685,7 +1715,7 @@ _outTypeName(StringInfo str, TypeName *node)
        WRITE_NODE_FIELD(typmods);
        WRITE_INT_FIELD(typemod);
        WRITE_NODE_FIELD(arrayBounds);
-       WRITE_INT_FIELD(location);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1695,6 +1725,7 @@ _outTypeCast(StringInfo str, TypeCast *node)
 
        WRITE_NODE_FIELD(arg);
        WRITE_NODE_FIELD(typename);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1892,7 +1923,7 @@ _outAExpr(StringInfo str, A_Expr *node)
 
        WRITE_NODE_FIELD(lexpr);
        WRITE_NODE_FIELD(rexpr);
-       WRITE_INT_FIELD(location);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1936,7 +1967,7 @@ _outColumnRef(StringInfo str, ColumnRef *node)
        WRITE_NODE_TYPE("COLUMNREF");
 
        WRITE_NODE_FIELD(fields);
-       WRITE_INT_FIELD(location);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1945,6 +1976,7 @@ _outParamRef(StringInfo str, ParamRef *node)
        WRITE_NODE_TYPE("PARAMREF");
 
        WRITE_INT_FIELD(number);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1954,6 +1986,7 @@ _outAConst(StringInfo str, A_Const *node)
 
        appendStringInfo(str, " :val ");
        _outValue(str, &(node->val));
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1980,6 +2013,7 @@ _outA_ArrayExpr(StringInfo str, A_ArrayExpr *node)
        WRITE_NODE_TYPE("A_ARRAYEXPR");
 
        WRITE_NODE_FIELD(elements);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
@@ -1990,7 +2024,7 @@ _outResTarget(StringInfo str, ResTarget *node)
        WRITE_STRING_FIELD(name);
        WRITE_NODE_FIELD(indirection);
        WRITE_NODE_FIELD(val);
-       WRITE_INT_FIELD(location);
+       WRITE_LOCATION_FIELD(location);
 }
 
 static void
index c46593d22c72a7d28219546619ad7718857a61a3..ee363502f69c71ebed50c0e88da19a36ee519490 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.212 2008/08/07 01:11:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.213 2008/08/28 23:09:46 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
  *       claimed to read them, but it was broken as well as unused.)  We
  *       never read executor state trees, either.
  *
+ *       Parse location fields are written out by outfuncs.c, but only for
+ *       possible debugging use.  When reading a location field, we discard
+ *       the stored value and set the location field to -1 (ie, "unknown").
+ *       This is because nodes coming from a stored rule should not be thought
+ *       to have a known location in the current query's text.
+ *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
        token = pg_strtok(&length);             /* get field value */ \
        local_node->fldname = nullable_string(token, length)
 
+/* Read a parse location field (and throw away the value, per notes above) */
+#define READ_LOCATION_FIELD(fldname) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       token = pg_strtok(&length);             /* get field value */ \
+       local_node->fldname = -1                /* set field to "unknown" */
+
 /* Read a Node field */
 #define READ_NODE_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
@@ -299,6 +311,7 @@ _readVar(void)
        READ_UINT_FIELD(varlevelsup);
        READ_UINT_FIELD(varnoold);
        READ_INT_FIELD(varoattno);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -316,6 +329,7 @@ _readConst(void)
        READ_INT_FIELD(constlen);
        READ_BOOL_FIELD(constbyval);
        READ_BOOL_FIELD(constisnull);
+       READ_LOCATION_FIELD(location);
 
        token = pg_strtok(&length); /* skip :constvalue */
        if (local_node->constisnull)
@@ -338,6 +352,7 @@ _readParam(void)
        READ_INT_FIELD(paramid);
        READ_OID_FIELD(paramtype);
        READ_INT_FIELD(paramtypmod);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -356,6 +371,7 @@ _readAggref(void)
        READ_UINT_FIELD(agglevelsup);
        READ_BOOL_FIELD(aggstar);
        READ_BOOL_FIELD(aggdistinct);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -392,6 +408,7 @@ _readFuncExpr(void)
        READ_BOOL_FIELD(funcretset);
        READ_ENUM_FIELD(funcformat, CoercionForm);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -420,6 +437,7 @@ _readOpExpr(void)
        READ_OID_FIELD(opresulttype);
        READ_BOOL_FIELD(opretset);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -448,6 +466,7 @@ _readDistinctExpr(void)
        READ_OID_FIELD(opresulttype);
        READ_BOOL_FIELD(opretset);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -475,6 +494,7 @@ _readScalarArrayOpExpr(void)
 
        READ_BOOL_FIELD(useOr);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -500,6 +520,7 @@ _readBoolExpr(void)
                elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
 
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -516,6 +537,7 @@ _readSubLink(void)
        READ_NODE_FIELD(testexpr);
        READ_NODE_FIELD(operName);
        READ_NODE_FIELD(subselect);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -568,6 +590,7 @@ _readRelabelType(void)
        READ_OID_FIELD(resulttype);
        READ_INT_FIELD(resulttypmod);
        READ_ENUM_FIELD(relabelformat, CoercionForm);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -583,6 +606,7 @@ _readCoerceViaIO(void)
        READ_NODE_FIELD(arg);
        READ_OID_FIELD(resulttype);
        READ_ENUM_FIELD(coerceformat, CoercionForm);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -601,6 +625,7 @@ _readArrayCoerceExpr(void)
        READ_INT_FIELD(resulttypmod);
        READ_BOOL_FIELD(isExplicit);
        READ_ENUM_FIELD(coerceformat, CoercionForm);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -616,6 +641,7 @@ _readConvertRowtypeExpr(void)
        READ_NODE_FIELD(arg);
        READ_OID_FIELD(resulttype);
        READ_ENUM_FIELD(convertformat, CoercionForm);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -632,6 +658,7 @@ _readCaseExpr(void)
        READ_NODE_FIELD(arg);
        READ_NODE_FIELD(args);
        READ_NODE_FIELD(defresult);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -646,6 +673,7 @@ _readCaseWhen(void)
 
        READ_NODE_FIELD(expr);
        READ_NODE_FIELD(result);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -676,6 +704,7 @@ _readArrayExpr(void)
        READ_OID_FIELD(element_typeid);
        READ_NODE_FIELD(elements);
        READ_BOOL_FIELD(multidims);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -691,6 +720,7 @@ _readRowExpr(void)
        READ_NODE_FIELD(args);
        READ_OID_FIELD(row_typeid);
        READ_ENUM_FIELD(row_format, CoercionForm);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -722,6 +752,7 @@ _readCoalesceExpr(void)
 
        READ_OID_FIELD(coalescetype);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -737,6 +768,7 @@ _readMinMaxExpr(void)
        READ_OID_FIELD(minmaxtype);
        READ_ENUM_FIELD(op, MinMaxOp);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -757,6 +789,7 @@ _readXmlExpr(void)
        READ_ENUM_FIELD(xmloption, XmlOptionType);
        READ_OID_FIELD(type);
        READ_INT_FIELD(typmod);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -785,6 +818,7 @@ _readNullIfExpr(void)
        READ_OID_FIELD(opresulttype);
        READ_BOOL_FIELD(opretset);
        READ_NODE_FIELD(args);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -829,6 +863,7 @@ _readCoerceToDomain(void)
        READ_OID_FIELD(resulttype);
        READ_INT_FIELD(resulttypmod);
        READ_ENUM_FIELD(coercionformat, CoercionForm);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -843,6 +878,7 @@ _readCoerceToDomainValue(void)
 
        READ_OID_FIELD(typeId);
        READ_INT_FIELD(typeMod);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
@@ -857,6 +893,7 @@ _readSetToDefault(void)
 
        READ_OID_FIELD(typeId);
        READ_INT_FIELD(typeMod);
+       READ_LOCATION_FIELD(location);
 
        READ_DONE();
 }
index a0ca92bd73dfe96afe8f5401948110b67c15b708..1a79c96dba495aebca1934af4dc0253f0f6b2e5a 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.246 2008/08/25 22:42:33 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.247 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1949,6 +1949,7 @@ get_switched_clauses(List *clauses, Relids outerrelids)
                        temp->opresulttype = clause->opresulttype;
                        temp->opretset = clause->opretset;
                        temp->args = list_copy(clause->args);
+                       temp->location = clause->location;
                        /* Commute it --- note this modifies the temp node in-place. */
                        CommuteOpExpr(temp);
                        t_list = lappend(t_list, temp);
index 42ac74e1a25baf87dea536f489dba327491ae492..fe8be5b1bbb5764ea1f3e55992a347109fdc5650 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.139 2008/08/25 22:42:33 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.140 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -140,6 +140,7 @@ replace_outer_var(PlannerInfo *root, Var *var)
        retval->paramid = i;
        retval->paramtype = var->vartype;
        retval->paramtypmod = var->vartypmod;
+       retval->location = -1;
 
        return retval;
 }
@@ -179,6 +180,7 @@ replace_outer_agg(PlannerInfo *root, Aggref *agg)
        retval->paramid = i;
        retval->paramtype = agg->aggtype;
        retval->paramtypmod = -1;
+       retval->location = -1;
 
        return retval;
 }
@@ -199,6 +201,7 @@ generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod)
        retval->paramid = list_length(root->glob->paramlist);
        retval->paramtype = paramtype;
        retval->paramtypmod = paramtypmod;
+       retval->location = -1;
 
        pitem = makeNode(PlannerParamItem);
        pitem->item = (Node *) retval;
index f7a54056591a4b470eeeb94f5966743faaf21868..c87bb00381ea19cf9bee567d2903418509bdee1f 100644 (file)
@@ -25,7 +25,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.58 2008/01/01 19:45:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.59 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,6 +219,7 @@ push_nots(Expr *qual)
                        newopexpr->opresulttype = opexpr->opresulttype;
                        newopexpr->opretset = opexpr->opretset;
                        newopexpr->args = opexpr->args;
+                       newopexpr->location = opexpr->location;
                        return (Expr *) newopexpr;
                }
                else
@@ -243,6 +244,7 @@ push_nots(Expr *qual)
                        newopexpr->opfuncid = InvalidOid;
                        newopexpr->useOr = !saopexpr->useOr;
                        newopexpr->args = saopexpr->args;
+                       newopexpr->location = saopexpr->location;
                        return (Expr *) newopexpr;
                }
                else
index de0218748d5eb57ab6075a98657ea5c1db3dbce8..08b70c8ee580902d686d97d708d5fae47feb3dde 100644 (file)
@@ -16,7 +16,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.90 2008/06/19 00:46:04 alvherre Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.91 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -292,6 +292,7 @@ expand_targetlist(List *tlist, int command_type,
                                                                                                        InvalidOid, -1,
                                                                                                        atttype,
                                                                                                        COERCE_IMPLICIT_CAST,
+                                                                                                       -1,
                                                                                                        false,
                                                                                                        false);
                                        }
index c07ca4434a30838c606e58c7f55c6926e0a486d6..7dc274797e5cc21b9af557bf86adf118b63f5c31 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.154 2008/08/25 22:42:33 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.155 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1410,6 +1410,7 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
                                                r->arg = (Expr *) var;
                                                r->resulttype = context->parent_reltype;
                                                r->convertformat = COERCE_IMPLICIT_CAST;
+                                               r->location = -1;
                                                /* Make sure the Var node has the right type ID, too */
                                                var->vartype = context->child_reltype;
                                                return (Node *) r;
@@ -1428,6 +1429,8 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
                                        rowexpr->args = fields;
                                        rowexpr->row_typeid = var->vartype;
                                        rowexpr->row_format = COERCE_IMPLICIT_CAST;
+                                       rowexpr->location = -1;
+
                                        return (Node *) rowexpr;
                                }
                        }
index 55bafa2c969f72595e8e8e0b0cbb51f58c3b99e1..254b86e0d9676fd6743232abf97aa851b40950d4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.265 2008/08/26 02:16:31 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.266 2008/08/28 23:09:46 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -135,6 +135,7 @@ make_opclause(Oid opno, Oid opresulttype, bool opretset,
                expr->args = list_make2(leftop, rightop);
        else
                expr->args = list_make1(leftop);
+       expr->location = -1;
        return (Expr *) expr;
 }
 
@@ -201,6 +202,7 @@ make_notclause(Expr *notclause)
 
        expr->boolop = NOT_EXPR;
        expr->args = list_make1(notclause);
+       expr->location = -1;
        return (Expr *) expr;
 }
 
@@ -244,6 +246,7 @@ make_orclause(List *orclauses)
 
        expr->boolop = OR_EXPR;
        expr->args = orclauses;
+       expr->location = -1;
        return (Expr *) expr;
 }
 
@@ -277,6 +280,7 @@ make_andclause(List *andclauses)
 
        expr->boolop = AND_EXPR;
        expr->args = andclauses;
+       expr->location = -1;
        return (Expr *) expr;
 }
 
@@ -2014,6 +2018,7 @@ eval_const_expressions_mutator(Node *node,
                newexpr->funcretset = expr->funcretset;
                newexpr->funcformat = expr->funcformat;
                newexpr->args = args;
+               newexpr->location = expr->location;
                return (Node *) newexpr;
        }
        if (IsA(node, OpExpr))
@@ -2071,6 +2076,7 @@ eval_const_expressions_mutator(Node *node,
                newexpr->opresulttype = expr->opresulttype;
                newexpr->opretset = expr->opretset;
                newexpr->args = args;
+               newexpr->location = expr->location;
                return (Node *) newexpr;
        }
        if (IsA(node, DistinctExpr))
@@ -2162,6 +2168,7 @@ eval_const_expressions_mutator(Node *node,
                newexpr->opresulttype = expr->opresulttype;
                newexpr->opretset = expr->opretset;
                newexpr->args = args;
+               newexpr->location = expr->location;
                return (Node *) newexpr;
        }
        if (IsA(node, BoolExpr))
@@ -2291,6 +2298,7 @@ eval_const_expressions_mutator(Node *node,
                        newrelabel->resulttype = relabel->resulttype;
                        newrelabel->resulttypmod = relabel->resulttypmod;
                        newrelabel->relabelformat = relabel->relabelformat;
+                       newrelabel->location = relabel->location;
                        return (Node *) newrelabel;
                }
        }
@@ -2357,6 +2365,7 @@ eval_const_expressions_mutator(Node *node,
                newexpr->arg = arg;
                newexpr->resulttype = expr->resulttype;
                newexpr->coerceformat = expr->coerceformat;
+               newexpr->location = expr->location;
                return (Node *) newexpr;
        }
        if (IsA(node, ArrayCoerceExpr))
@@ -2379,6 +2388,7 @@ eval_const_expressions_mutator(Node *node,
                newexpr->resulttypmod = expr->resulttypmod;
                newexpr->isExplicit = expr->isExplicit;
                newexpr->coerceformat = expr->coerceformat;
+               newexpr->location = expr->location;
 
                /*
                 * If constant argument and it's a binary-coercible or immutable
@@ -2477,6 +2487,7 @@ eval_const_expressions_mutator(Node *node,
 
                                newcasewhen->expr = (Expr *) casecond;
                                newcasewhen->result = (Expr *) caseresult;
+                               newcasewhen->location = oldcasewhen->location;
                                newargs = lappend(newargs, newcasewhen);
                                continue;
                        }
@@ -2506,6 +2517,7 @@ eval_const_expressions_mutator(Node *node,
                newcase->arg = (Expr *) newarg;
                newcase->args = newargs;
                newcase->defresult = (Expr *) defresult;
+               newcase->location = caseexpr->location;
                return (Node *) newcase;
        }
        if (IsA(node, CaseTestExpr))
@@ -2545,6 +2557,7 @@ eval_const_expressions_mutator(Node *node,
                newarray->element_typeid = arrayexpr->element_typeid;
                newarray->elements = newelems;
                newarray->multidims = arrayexpr->multidims;
+               newarray->location = arrayexpr->location;
 
                if (all_const)
                        return (Node *) evaluate_expr((Expr *) newarray,
@@ -2590,6 +2603,7 @@ eval_const_expressions_mutator(Node *node,
                newcoalesce = makeNode(CoalesceExpr);
                newcoalesce->coalescetype = coalesceexpr->coalescetype;
                newcoalesce->args = newargs;
+               newcoalesce->location = coalesceexpr->location;
                return (Node *) newcoalesce;
        }
        if (IsA(node, FieldSelect))
@@ -3206,6 +3220,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, List *args,
        newexpr->funcretset = false;
        newexpr->funcformat = COERCE_DONTCARE;          /* doesn't matter */
        newexpr->args = args;
+       newexpr->location = -1;
 
        return evaluate_expr((Expr *) newexpr, result_type, result_typmod);
 }
index 85f34e494278420765bcb665682583f7b331798b..e9fd15e6f3fda5eeec92492781442289649f9d34 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.77 2008/08/25 22:42:33 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.78 2008/08/28 23:09:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -624,6 +624,7 @@ flatten_join_alias_vars_mutator(Node *node,
                        rowexpr->args = fields;
                        rowexpr->row_typeid = var->vartype;
                        rowexpr->row_format = COERCE_IMPLICIT_CAST;
+                       rowexpr->location = -1;
 
                        return (Node *) rowexpr;
                }
index 2086c3321f03a6a2ae5e21eef76e4f8fe23a2fd1..b513d61c071691c4833cb99f96666bd8ea872483 100644 (file)
@@ -17,7 +17,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.377 2008/08/25 22:42:33 tgl Exp $
+ *     $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.378 2008/08/28 23:09:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,9 +53,8 @@ static List *transformInsertRow(ParseState *pstate, List *exprlist,
 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
 static Query *transformValuesClause(ParseState *pstate, SelectStmt *stmt);
 static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
-static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
-static void getSetColTypes(ParseState *pstate, Node *node,
-                          List **colTypes, List **colTypmods);
+static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
+                                                                          List **colInfo);
 static void applyColumnNames(List *dst, List *src);
 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
 static List *transformReturningList(ParseState *pstate, List *returningList);
@@ -789,7 +788,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
 {
        Query      *qry = makeNode(Query);
        List       *exprsLists = NIL;
-       List      **coltype_lists = NULL;
+       List      **colexprs = NULL;
        Oid                *coltypes = NULL;
        int                     sublist_length = -1;
        List       *newExprsLists;
@@ -831,8 +830,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
                {
                        /* Remember post-transformation length of first sublist */
                        sublist_length = list_length(sublist);
-                       /* and allocate arrays for column-type info */
-                       coltype_lists = (List **) palloc0(sublist_length * sizeof(List *));
+                       /* and allocate arrays for per-column info */
+                       colexprs = (List **) palloc0(sublist_length * sizeof(List *));
                        coltypes = (Oid *) palloc0(sublist_length * sizeof(Oid));
                }
                else if (sublist_length != list_length(sublist))
@@ -844,6 +843,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
 
                exprsLists = lappend(exprsLists, sublist);
 
+               /* Check for DEFAULT and build per-column expression lists */
                i = 0;
                foreach(lc2, sublist)
                {
@@ -852,8 +852,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
                        if (IsA(col, SetToDefault))
                                ereport(ERROR,
                                                (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("DEFAULT can only appear in a VALUES list within INSERT")));
-                       coltype_lists[i] = lappend_oid(coltype_lists[i], exprType(col));
+                                                errmsg("DEFAULT can only appear in a VALUES list within INSERT"),
+                                                parser_errposition(pstate, exprLocation(col))));
+                       colexprs[i] = lappend(colexprs[i], col);
                        i++;
                }
        }
@@ -864,7 +865,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
         */
        for (i = 0; i < sublist_length; i++)
        {
-               coltypes[i] = select_common_type(coltype_lists[i], "VALUES");
+               coltypes[i] = select_common_type(pstate, colexprs[i], "VALUES", NULL);
        }
 
        newExprsLists = NIL;
@@ -985,6 +986,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
        int                     leftmostRTI;
        Query      *leftmostQuery;
        SetOperationStmt *sostmt;
+       List       *socolinfo;
        List       *intoColNames = NIL;
        List       *sortClause;
        Node       *limitOffset;
@@ -1047,7 +1049,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
        /*
         * Recursively transform the components of the tree.
         */
-       sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt);
+       sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt,
+                                                                                                                       &socolinfo);
        Assert(sostmt && IsA(sostmt, SetOperationStmt));
        qry->setOperations = (Node *) sostmt;
 
@@ -1191,9 +1194,17 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
 /*
  * transformSetOperationTree
  *             Recursively transform leaves and internal nodes of a set-op tree
+ *
+ * In addition to returning the transformed node, we return a list of
+ * expression nodes showing the type, typmod, and location (for error messages)
+ * of each output column of the set-op node.  This is used only during the
+ * internal recursion of this function.  We use SetToDefault nodes for
+ * this purpose, since they carry exactly the fields needed, but any other
+ * expression node type would do as well.
  */
 static Node *
-transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
+transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
+                                                 List **colInfo)
 {
        bool            isLeaf;
 
@@ -1240,6 +1251,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
                char            selectName[32];
                RangeTblEntry *rte;
                RangeTblRef *rtr;
+               ListCell   *tl;
 
                /*
                 * Transform SelectStmt into a Query.
@@ -1264,6 +1276,24 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
                                                 errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level")));
                }
 
+               /*
+                * Extract information about the result columns.
+                */
+               *colInfo = NIL;
+               foreach(tl, selectQuery->targetList)
+               {
+                       TargetEntry *tle = (TargetEntry *) lfirst(tl);
+                       SetToDefault   *cinfo;
+
+                       if (tle->resjunk)
+                               continue;
+                       cinfo = makeNode(SetToDefault);
+                       cinfo->typeId = exprType((Node *) tle->expr);
+                       cinfo->typeMod = exprTypmod((Node *) tle->expr);
+                       cinfo->location = exprLocation((Node *) tle->expr);
+                       *colInfo = lappend(*colInfo, cinfo);
+               }
+
                /*
                 * Make the leaf query be a subquery in the top-level rangetable.
                 */
@@ -1287,14 +1317,10 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
        {
                /* Process an internal node (set operation node) */
                SetOperationStmt *op = makeNode(SetOperationStmt);
-               List       *lcoltypes;
-               List       *rcoltypes;
-               List       *lcoltypmods;
-               List       *rcoltypmods;
-               ListCell   *lct;
-               ListCell   *rct;
-               ListCell   *lcm;
-               ListCell   *rcm;
+               List       *lcolinfo;
+               List       *rcolinfo;
+               ListCell   *lci;
+               ListCell   *rci;
                const char *context;
 
                context = (stmt->op == SETOP_UNION ? "UNION" :
@@ -1307,46 +1333,66 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
                /*
                 * Recursively transform the child nodes.
                 */
-               op->larg = transformSetOperationTree(pstate, stmt->larg);
-               op->rarg = transformSetOperationTree(pstate, stmt->rarg);
+               op->larg = transformSetOperationTree(pstate, stmt->larg,
+                                                                                        &lcolinfo);
+               op->rarg = transformSetOperationTree(pstate, stmt->rarg,
+                                                                                        &rcolinfo);
 
                /*
                 * Verify that the two children have the same number of non-junk
                 * columns, and determine the types of the merged output columns.
                 */
-               getSetColTypes(pstate, op->larg, &lcoltypes, &lcoltypmods);
-               getSetColTypes(pstate, op->rarg, &rcoltypes, &rcoltypmods);
-               if (list_length(lcoltypes) != list_length(rcoltypes))
+               if (list_length(lcolinfo) != list_length(rcolinfo))
                        ereport(ERROR,
                                        (errcode(ERRCODE_SYNTAX_ERROR),
                                 errmsg("each %s query must have the same number of columns",
-                                               context)));
-               Assert(list_length(lcoltypes) == list_length(lcoltypmods));
-               Assert(list_length(rcoltypes) == list_length(rcoltypmods));
+                                               context),
+                                        parser_errposition(pstate,
+                                                                               exprLocation((Node *) rcolinfo))));
 
+               *colInfo = NIL;
                op->colTypes = NIL;
                op->colTypmods = NIL;
                op->groupClauses = NIL;
-               /* don't have a "foreach4", so chase two of the lists by hand */
-               lcm = list_head(lcoltypmods);
-               rcm = list_head(rcoltypmods);
-               forboth(lct, lcoltypes, rct, rcoltypes)
+               forboth(lci, lcolinfo, rci, rcolinfo)
                {
-                       Oid                     lcoltype = lfirst_oid(lct);
-                       Oid                     rcoltype = lfirst_oid(rct);
-                       int32           lcoltypmod = lfirst_int(lcm);
-                       int32           rcoltypmod = lfirst_int(rcm);
+                       SetToDefault *lcolinfo = (SetToDefault *) lfirst(lci);
+                       SetToDefault *rcolinfo = (SetToDefault *) lfirst(rci);
+                       Oid                     lcoltype = lcolinfo->typeId;
+                       Oid                     rcoltype = rcolinfo->typeId;
+                       int32           lcoltypmod = lcolinfo->typeMod;
+                       int32           rcoltypmod = rcolinfo->typeMod;
+                       Node       *bestexpr;
+                       SetToDefault *rescolinfo;
                        Oid                     rescoltype;
                        int32           rescoltypmod;
 
                        /* select common type, same as CASE et al */
-                       rescoltype = select_common_type(list_make2_oid(lcoltype, rcoltype),
-                                                                                       context);
+                       rescoltype = select_common_type(pstate,
+                                                                                       list_make2(lcolinfo, rcolinfo),
+                                                                                       context,
+                                                                                       &bestexpr);
                        /* if same type and same typmod, use typmod; else default */
                        if (lcoltype == rcoltype && lcoltypmod == rcoltypmod)
                                rescoltypmod = lcoltypmod;
                        else
                                rescoltypmod = -1;
+
+                       /* verify the coercions are actually possible */
+                       if (lcoltype != UNKNOWNOID)
+                               (void) coerce_to_common_type(pstate, (Node *) lcolinfo,
+                                                                                        rescoltype, context);
+                       if (rcoltype != UNKNOWNOID)
+                               (void) coerce_to_common_type(pstate, (Node *) rcolinfo,
+                                                                                        rescoltype, context);
+
+                       /* emit results */
+                       rescolinfo = makeNode(SetToDefault);
+                       rescolinfo->typeId = rescoltype;
+                       rescolinfo->typeMod = rescoltypmod;
+                       rescolinfo->location = ((SetToDefault *) bestexpr)->location;
+                       *colInfo = lappend(*colInfo, rescolinfo);
+
                        op->colTypes = lappend_oid(op->colTypes, rescoltype);
                        op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
 
@@ -1374,59 +1420,12 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
 
                                op->groupClauses = lappend(op->groupClauses, grpcl);
                        }
-
-                       lcm = lnext(lcm);
-                       rcm = lnext(rcm);
                }
 
                return (Node *) op;
        }
 }
 
-/*
- * getSetColTypes
- *       Get output column types/typmods of an (already transformed) set-op node
- */
-static void
-getSetColTypes(ParseState *pstate, Node *node,
-                          List **colTypes, List **colTypmods)
-{
-       *colTypes = NIL;
-       *colTypmods = NIL;
-       if (IsA(node, RangeTblRef))
-       {
-               RangeTblRef *rtr = (RangeTblRef *) node;
-               RangeTblEntry *rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
-               Query      *selectQuery = rte->subquery;
-               ListCell   *tl;
-
-               Assert(selectQuery != NULL);
-               /* Get types of non-junk columns */
-               foreach(tl, selectQuery->targetList)
-               {
-                       TargetEntry *tle = (TargetEntry *) lfirst(tl);
-
-                       if (tle->resjunk)
-                               continue;
-                       *colTypes = lappend_oid(*colTypes,
-                                                                       exprType((Node *) tle->expr));
-                       *colTypmods = lappend_int(*colTypmods,
-                                                                         exprTypmod((Node *) tle->expr));
-               }
-       }
-       else if (IsA(node, SetOperationStmt))
-       {
-               SetOperationStmt *op = (SetOperationStmt *) node;
-
-               /* Result already computed during transformation of node */
-               Assert(op->colTypes != NIL);
-               *colTypes = op->colTypes;
-               *colTypmods = op->colTypmods;
-       }
-       else
-               elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
-}
-
 /*
  * Attach column names from a ColumnDef list to a TargetEntry list
  * (for CREATE TABLE AS)
index 39e52099f43f256b06d5469bb17b3cf9252ade3e..e908750f76a996518e472055be271c6624a0308d 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.618 2008/07/18 03:32:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.619 2008/08/28 23:09:47 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -90,15 +90,15 @@ static bool QueryIsRule = FALSE;
 /*#define __YYSCLASS*/
 
 static Node *makeColumnRef(char *relname, List *indirection, int location);
-static Node *makeTypeCast(Node *arg, TypeName *typename);
-static Node *makeStringConst(char *str);
-static Node *makeStringConstCast(char *str, TypeName *typename);
-static Node *makeIntConst(int val);
-static Node *makeFloatConst(char *str);
-static Node *makeBitStringConst(char *str);
-static Node *makeNullAConst(void);
-static Node *makeAConst(Value *v);
-static Node *makeBoolAConst(bool state);
+static Node *makeTypeCast(Node *arg, TypeName *typename, int location);
+static Node *makeStringConst(char *str, int location);
+static Node *makeStringConstCast(char *str, int location, TypeName *typename);
+static Node *makeIntConst(int val, int location);
+static Node *makeFloatConst(char *str, int location);
+static Node *makeBitStringConst(char *str, int location);
+static Node *makeNullAConst(int location);
+static Node *makeAConst(Value *v, int location);
+static Node *makeBoolAConst(bool state, int location);
 static FuncCall *makeOverlaps(List *largs, List *rargs, int location);
 static void check_qualified_name(List *names);
 static List *check_func_name(List *names);
@@ -110,8 +110,9 @@ static void insertSelectOptions(SelectStmt *stmt,
 static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
 static Node *doNegate(Node *n, int location);
 static void doNegateFloat(Value *v);
-static Node *makeAArrayExpr(List *elements);
-static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args);
+static Node *makeAArrayExpr(List *elements, int location);
+static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
+                                                List *args, int location);
 static List *mergeTableFuncParameters(List *func_args, List *columns);
 static TypeName *TableFuncTypeName(List *columns);
 
@@ -1117,7 +1118,7 @@ set_rest: /* Generic SET syntaxes: */
                                        n->kind = VAR_SET_VALUE;
                                        n->name = "client_encoding";
                                        if ($2 != NULL)
-                                               n->args = list_make1(makeStringConst($2));
+                                               n->args = list_make1(makeStringConst($2, @2));
                                        else
                                                n->kind = VAR_SET_DEFAULT;
                                        $$ = n;
@@ -1127,7 +1128,7 @@ set_rest: /* Generic SET syntaxes: */
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->kind = VAR_SET_VALUE;
                                        n->name = "role";
-                                       n->args = list_make1(makeStringConst($2));
+                                       n->args = list_make1(makeStringConst($2, @2));
                                        $$ = n;
                                }
                        | SESSION AUTHORIZATION ColId_or_Sconst
@@ -1135,7 +1136,7 @@ set_rest: /* Generic SET syntaxes: */
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->kind = VAR_SET_VALUE;
                                        n->name = "session_authorization";
-                                       n->args = list_make1(makeStringConst($3));
+                                       n->args = list_make1(makeStringConst($3, @3));
                                        $$ = n;
                                }
                        | SESSION AUTHORIZATION DEFAULT
@@ -1150,7 +1151,7 @@ set_rest: /* Generic SET syntaxes: */
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->kind = VAR_SET_VALUE;
                                        n->name = "xmloption";
-                                       n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT"));
+                                       n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3));
                                        $$ = n;
                                }
                ;
@@ -1168,11 +1169,11 @@ var_list:       var_value                                                               { $$ = list_make1($1); }
                ;
 
 var_value:     opt_boolean
-                               { $$ = makeStringConst($1); }
+                               { $$ = makeStringConst($1, @1); }
                        | ColId_or_Sconst
-                               { $$ = makeStringConst($1); }
+                               { $$ = makeStringConst($1, @1); }
                        | NumericOnly
-                               { $$ = makeAConst($1); }
+                               { $$ = makeAConst($1, @1); }
                ;
 
 iso_level:     READ UNCOMMITTED                                                { $$ = "read uncommitted"; }
@@ -1199,11 +1200,11 @@ opt_boolean:
 zone_value:
                        Sconst
                                {
-                                       $$ = makeStringConst($1);
+                                       $$ = makeStringConst($1, @1);
                                }
                        | IDENT
                                {
-                                       $$ = makeStringConst($1);
+                                       $$ = makeStringConst($1, @1);
                                }
                        | ConstInterval Sconst opt_interval
                                {
@@ -1214,9 +1215,9 @@ zone_value:
                                                        ereport(ERROR,
                                                                        (errcode(ERRCODE_SYNTAX_ERROR),
                                                                         errmsg("time zone interval must be HOUR or HOUR TO MINUTE")));
-                                               t->typmods = list_make1(makeIntConst($3));
+                                               t->typmods = list_make1(makeIntConst($3, @3));
                                        }
-                                       $$ = makeStringConstCast($2, t);
+                                       $$ = makeStringConstCast($2, @2, t);
                                }
                        | ConstInterval '(' Iconst ')' Sconst opt_interval
                                {
@@ -1226,11 +1227,11 @@ zone_value:
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_SYNTAX_ERROR),
                                                                 errmsg("time zone interval must be HOUR or HOUR TO MINUTE")));
-                                       t->typmods = list_make2(makeIntConst($6), 
-                                                                                       makeIntConst($3));
-                                       $$ = makeStringConstCast($5, t);
+                                       t->typmods = list_make2(makeIntConst($6, @6),
+                                                                                       makeIntConst($3, @3));
+                                       $$ = makeStringConstCast($5, @5, t);
                                }
-                       | NumericOnly                                                   { $$ = makeAConst($1); }
+                       | NumericOnly                                                   { $$ = makeAConst($1, @1); }
                        | DEFAULT                                                               { $$ = NULL; }
                        | LOCAL                                                                 { $$ = NULL; }
                ;
@@ -5274,13 +5275,13 @@ opt_transaction:        WORK                                                    {}
 transaction_mode_item:
                        ISOLATION LEVEL iso_level
                                        { $$ = makeDefElem("transaction_isolation",
-                                                                          makeStringConst($3)); }
+                                                                          makeStringConst($3, @3)); }
                        | READ ONLY
                                        { $$ = makeDefElem("transaction_read_only",
-                                                                          makeIntConst(TRUE)); }
+                                                                          makeIntConst(TRUE, @1)); }
                        | READ WRITE
                                        { $$ = makeDefElem("transaction_read_only",
-                                                                          makeIntConst(FALSE)); }
+                                                                          makeIntConst(FALSE, @1)); }
                ;
 
 /* Syntax with commas is SQL-spec, without commas is Postgres historical */
@@ -6461,7 +6462,7 @@ select_limit_value:
                        | ALL
                                {
                                        /* LIMIT ALL is represented as a NULL constant */
-                                       $$ = makeNullAConst();
+                                       $$ = makeNullAConst(@1);
                                }
                ;
 
@@ -6963,13 +6964,13 @@ SimpleTypename:
                                {
                                        $$ = $1;
                                        if ($2 != INTERVAL_FULL_RANGE)
-                                               $$->typmods = list_make1(makeIntConst($2));
+                                               $$->typmods = list_make1(makeIntConst($2, @2));
                                }
                        | ConstInterval '(' Iconst ')' opt_interval
                                {
                                        $$ = $1;
-                                       $$->typmods = list_make2(makeIntConst($5),
-                                                                                        makeIntConst($3));
+                                       $$->typmods = list_make2(makeIntConst($5, @5),
+                                                                                        makeIntConst($3, @3));
                                }
                ;
 
@@ -7155,7 +7156,7 @@ BitWithoutLength:
                                        else
                                        {
                                                $$ = SystemTypeName("bit");
-                                               $$->typmods = list_make1(makeIntConst(1));
+                                               $$->typmods = list_make1(makeIntConst(1, -1));
                                        }
                                        $$->location = @1;
                                }
@@ -7207,7 +7208,7 @@ CharacterWithLength:  character '(' Iconst ')' opt_charset
                                        }
 
                                        $$ = SystemTypeName($1);
-                                       $$->typmods = list_make1(makeIntConst($3));
+                                       $$->typmods = list_make1(makeIntConst($3, @3));
                                        $$->location = @1;
                                }
                ;
@@ -7229,7 +7230,7 @@ CharacterWithoutLength:    character opt_charset
 
                                        /* char defaults to char(1), varchar to no limit */
                                        if (strcmp($1, "bpchar") == 0)
-                                               $$->typmods = list_make1(makeIntConst(1));
+                                               $$->typmods = list_make1(makeIntConst(1, -1));
 
                                        $$->location = @1;
                                }
@@ -7269,7 +7270,7 @@ ConstDatetime:
                                                $$ = SystemTypeName("timestamptz");
                                        else
                                                $$ = SystemTypeName("timestamp");
-                                       $$->typmods = list_make1(makeIntConst($3));
+                                       $$->typmods = list_make1(makeIntConst($3, @3));
                                        $$->location = @1;
                                }
                        | TIMESTAMP opt_timezone
@@ -7286,7 +7287,7 @@ ConstDatetime:
                                                $$ = SystemTypeName("timetz");
                                        else
                                                $$ = SystemTypeName("time");
-                                       $$->typmods = list_make1(makeIntConst($3));
+                                       $$->typmods = list_make1(makeIntConst($3, @3));
                                        $$->location = @1;
                                }
                        | TIME opt_timezone
@@ -7365,7 +7366,7 @@ opt_interval:
  */
 a_expr:                c_expr                                                                  { $$ = $1; }
                        | a_expr TYPECAST Typename
-                                       { $$ = makeTypeCast($1, $3); }
+                                       { $$ = makeTypeCast($1, $3, @2); }
                        | a_expr AT TIME ZONE a_expr
                                {
                                        FuncCall *n = makeNode(FuncCall);
@@ -7480,7 +7481,7 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                {
                                        FuncCall *n = makeNode(FuncCall);
                                        n->funcname = SystemFuncName("similar_escape");
-                                       n->args = list_make2($4, makeNullAConst());
+                                       n->args = list_make2($4, makeNullAConst(-1));
                                        n->agg_star = FALSE;
                                        n->agg_distinct = FALSE;
                                        n->func_variadic = FALSE;
@@ -7502,7 +7503,7 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                {
                                        FuncCall *n = makeNode(FuncCall);
                                        n->funcname = SystemFuncName("similar_escape");
-                                       n->args = list_make2($5, makeNullAConst());
+                                       n->args = list_make2($5, makeNullAConst(-1));
                                        n->agg_star = FALSE;
                                        n->agg_distinct = FALSE;
                                        n->func_variadic = FALSE;
@@ -7674,6 +7675,7 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                                n->subLinkType = ANY_SUBLINK;
                                                n->testexpr = $1;
                                                n->operName = list_make1(makeString("="));
+                                               n->location = @2;
                                                $$ = (Node *)n;
                                        }
                                        else
@@ -7693,6 +7695,7 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                                n->subLinkType = ANY_SUBLINK;
                                                n->testexpr = $1;
                                                n->operName = list_make1(makeString("="));
+                                               n->location = @3;
                                                /* Stick a NOT on top */
                                                $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n, @2);
                                        }
@@ -7709,6 +7712,7 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                        n->testexpr = $1;
                                        n->operName = $2;
                                        n->subselect = $4;
+                                       n->location = @2;
                                        $$ = (Node *)n;
                                }
                        | a_expr subquery_Op sub_type '(' a_expr ')'            %prec Op
@@ -7735,12 +7739,14 @@ a_expr:         c_expr                                                                  { $$ = $1; }
                                }
                        | a_expr IS DOCUMENT_P                                  %prec IS
                                {
-                                       $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1));
+                                       $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL,
+                                                                        list_make1($1), @2);
                                }
                        | a_expr IS NOT DOCUMENT_P                              %prec IS
                                {
                                        $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
-                                                                                        makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1)),
+                                                                                        makeXmlExpr(IS_DOCUMENT, NULL, NIL,
+                                                                                                                list_make1($1), @2),
                                                                                         @2);
                                }
                ;
@@ -7757,7 +7763,7 @@ a_expr:           c_expr                                                                  { $$ = $1; }
 b_expr:                c_expr
                                { $$ = $1; }
                        | b_expr TYPECAST Typename
-                               { $$ = makeTypeCast($1, $3); }
+                               { $$ = makeTypeCast($1, $3, @2); }
                        | '+' b_expr                                    %prec UMINUS
                                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }
                        | '-' b_expr                                    %prec UMINUS
@@ -7805,12 +7811,14 @@ b_expr:         c_expr
                                }
                        | b_expr IS DOCUMENT_P                                  %prec IS
                                {
-                                       $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1));
+                                       $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL,
+                                                                        list_make1($1), @2);
                                }
                        | b_expr IS NOT DOCUMENT_P                              %prec IS
                                {
                                        $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
-                                                                                        makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1)),
+                                                                                        makeXmlExpr(IS_DOCUMENT, NULL, NIL,
+                                                                                                                list_make1($1), @2),
                                                                                         @2);
                                }
                ;
@@ -7829,6 +7837,7 @@ c_expr:           columnref                                                               { $$ = $1; }
                                {
                                        ParamRef *p = makeNode(ParamRef);
                                        p->number = $1;
+                                       p->location = @1;
                                        if ($2)
                                        {
                                                A_Indirection *n = makeNode(A_Indirection);
@@ -7862,6 +7871,7 @@ c_expr:           columnref                                                               { $$ = $1; }
                                        n->testexpr = NULL;
                                        n->operName = NIL;
                                        n->subselect = $1;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | EXISTS select_with_parens
@@ -7871,6 +7881,7 @@ c_expr:           columnref                                                               { $$ = $1; }
                                        n->testexpr = NULL;
                                        n->operName = NIL;
                                        n->subselect = $2;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | ARRAY select_with_parens
@@ -7880,15 +7891,23 @@ c_expr:         columnref                                                               { $$ = $1; }
                                        n->testexpr = NULL;
                                        n->operName = NIL;
                                        n->subselect = $2;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | ARRAY array_expr
-                               {       $$ = $2;        }
+                               {
+                                       A_ArrayExpr *n = (A_ArrayExpr *) $2;
+                                       Assert(IsA(n, A_ArrayExpr));
+                                       /* point outermost A_ArrayExpr to the ARRAY keyword */
+                                       n->location = @1;
+                                       $$ = (Node *)n;
+                               }
                        | row
                                {
                                        RowExpr *r = makeNode(RowExpr);
                                        r->args = $1;
                                        r->row_typeid = InvalidOid;     /* not analyzed yet */
+                                       r->location = @1;
                                        $$ = (Node *)r;
                                }
                ;
@@ -8010,8 +8029,8 @@ func_expr:        func_name '(' ')'
                                         * to rely on it.)
                                         */
                                        Node *n;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
-                                       $$ = makeTypeCast(n, SystemTypeName("date"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
+                                       $$ = makeTypeCast(n, SystemTypeName("date"), -1);
                                }
                        | CURRENT_TIME
                                {
@@ -8020,8 +8039,8 @@ func_expr:        func_name '(' ')'
                                         * See comments for CURRENT_DATE.
                                         */
                                        Node *n;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
-                                       $$ = makeTypeCast(n, SystemTypeName("timetz"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
+                                       $$ = makeTypeCast(n, SystemTypeName("timetz"), -1);
                                }
                        | CURRENT_TIME '(' Iconst ')'
                                {
@@ -8031,10 +8050,10 @@ func_expr:      func_name '(' ')'
                                         */
                                        Node *n;
                                        TypeName *d;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
                                        d = SystemTypeName("timetz");
-                                       d->typmods = list_make1(makeIntConst($3));
-                                       $$ = makeTypeCast(n, d);
+                                       d->typmods = list_make1(makeIntConst($3, @3));
+                                       $$ = makeTypeCast(n, d, -1);
                                }
                        | CURRENT_TIMESTAMP
                                {
@@ -8059,10 +8078,10 @@ func_expr:      func_name '(' ')'
                                         */
                                        Node *n;
                                        TypeName *d;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
                                        d = SystemTypeName("timestamptz");
-                                       d->typmods = list_make1(makeIntConst($3));
-                                       $$ = makeTypeCast(n, d);
+                                       d->typmods = list_make1(makeIntConst($3, @3));
+                                       $$ = makeTypeCast(n, d, -1);
                                }
                        | LOCALTIME
                                {
@@ -8071,8 +8090,8 @@ func_expr:        func_name '(' ')'
                                         * See comments for CURRENT_DATE.
                                         */
                                        Node *n;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
-                                       $$ = makeTypeCast((Node *)n, SystemTypeName("time"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
+                                       $$ = makeTypeCast((Node *)n, SystemTypeName("time"), -1);
                                }
                        | LOCALTIME '(' Iconst ')'
                                {
@@ -8082,10 +8101,10 @@ func_expr:      func_name '(' ')'
                                         */
                                        Node *n;
                                        TypeName *d;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
                                        d = SystemTypeName("time");
-                                       d->typmods = list_make1(makeIntConst($3));
-                                       $$ = makeTypeCast((Node *)n, d);
+                                       d->typmods = list_make1(makeIntConst($3, @3));
+                                       $$ = makeTypeCast((Node *)n, d, -1);
                                }
                        | LOCALTIMESTAMP
                                {
@@ -8094,8 +8113,8 @@ func_expr:        func_name '(' ')'
                                         * See comments for CURRENT_DATE.
                                         */
                                        Node *n;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
-                                       $$ = makeTypeCast(n, SystemTypeName("timestamp"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
+                                       $$ = makeTypeCast(n, SystemTypeName("timestamp"), -1);
                                }
                        | LOCALTIMESTAMP '(' Iconst ')'
                                {
@@ -8105,10 +8124,10 @@ func_expr:      func_name '(' ')'
                                         */
                                        Node *n;
                                        TypeName *d;
-                                       n = makeStringConstCast("now", SystemTypeName("text"));
+                                       n = makeStringConstCast("now", @1, SystemTypeName("text"));
                                        d = SystemTypeName("timestamp");
-                                       d->typmods = list_make1(makeIntConst($3));
-                                       $$ = makeTypeCast(n, d);
+                                       d->typmods = list_make1(makeIntConst($3, @3));
+                                       $$ = makeTypeCast(n, d, -1);
                                }
                        | CURRENT_ROLE
                                {
@@ -8155,7 +8174,7 @@ func_expr:        func_name '(' ')'
                                        $$ = (Node *)n;
                                }
                        | CAST '(' a_expr AS Typename ')'
-                               { $$ = makeTypeCast($3, $5); }
+                               { $$ = makeTypeCast($3, $5, @1); }
                        | EXTRACT '(' extract_list ')'
                                {
                                        FuncCall *n = makeNode(FuncCall);
@@ -8284,6 +8303,7 @@ func_expr:        func_name '(' ')'
                                {
                                        CoalesceExpr *c = makeNode(CoalesceExpr);
                                        c->args = $3;
+                                       c->location = @1;
                                        $$ = (Node *)c;
                                }
                        | GREATEST '(' expr_list ')'
@@ -8291,6 +8311,7 @@ func_expr:        func_name '(' ')'
                                        MinMaxExpr *v = makeNode(MinMaxExpr);
                                        v->args = $3;
                                        v->op = IS_GREATEST;
+                                       v->location = @1;
                                        $$ = (Node *)v;
                                }
                        | LEAST '(' expr_list ')'
@@ -8298,52 +8319,54 @@ func_expr:      func_name '(' ')'
                                        MinMaxExpr *v = makeNode(MinMaxExpr);
                                        v->args = $3;
                                        v->op = IS_LEAST;
+                                       v->location = @1;
                                        $$ = (Node *)v;
                                }
                        | XMLCONCAT '(' expr_list ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3);
+                                       $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3, @1);
                                }
                        | XMLELEMENT '(' NAME_P ColLabel ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, NIL);
+                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, NIL, @1);
                                }
                        | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NIL);
+                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NIL, @1);
                                }
                        | XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, $6);
+                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, $6, @1);
                                }
                        | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8);
+                                       $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8, @1);
                                }
                        | XMLFOREST '(' xml_attribute_list ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL);
+                                       $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL, @1);
                                }
                        | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
                                {
-                                       XmlExpr *x = (XmlExpr *) makeXmlExpr(IS_XMLPARSE, NULL, NIL,
-                                                                                                                list_make2($4,
-                                                                                                                                       makeBoolAConst($5)));
+                                       XmlExpr *x = (XmlExpr *)
+                                               makeXmlExpr(IS_XMLPARSE, NULL, NIL,
+                                                                       list_make2($4, makeBoolAConst($5, -1)),
+                                                                       @1);
                                        x->xmloption = $3;
                                        $$ = (Node *)x;
                                }
                        | XMLPI '(' NAME_P ColLabel ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL);
+                                       $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL, @1);
                                }
                        | XMLPI '(' NAME_P ColLabel ',' a_expr ')'
                                {
-                                       $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6));
+                                       $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6), @1);
                                }
                        | XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'
                                {
                                        $$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
-                                                                        list_make3($3, $5, $6));
+                                                                        list_make3($3, $5, $6), @1);
                                }
                        | XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')'
                                {
@@ -8351,6 +8374,7 @@ func_expr:        func_name '(' ')'
                                        n->xmloption = $3;
                                        n->expr = $4;
                                        n->typename = $6;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                ;
@@ -8361,17 +8385,17 @@ func_expr:      func_name '(' ')'
 xml_root_version: VERSION_P a_expr
                                { $$ = $2; }
                        | VERSION_P NO VALUE_P
-                               { $$ = makeNullAConst(); }
+                               { $$ = makeNullAConst(-1); }
                ;
 
 opt_xml_root_standalone: ',' STANDALONE_P YES_P
-                               { $$ = makeIntConst(XML_STANDALONE_YES); }
+                               { $$ = makeIntConst(XML_STANDALONE_YES, -1); }
                        | ',' STANDALONE_P NO
-                               { $$ = makeIntConst(XML_STANDALONE_NO); }
+                               { $$ = makeIntConst(XML_STANDALONE_NO, -1); }
                        | ',' STANDALONE_P NO VALUE_P
-                               { $$ = makeIntConst(XML_STANDALONE_NO_VALUE); }
+                               { $$ = makeIntConst(XML_STANDALONE_NO_VALUE, -1); }
                        | /*EMPTY*/
-                               { $$ = makeIntConst(XML_STANDALONE_OMITTED); }
+                               { $$ = makeIntConst(XML_STANDALONE_OMITTED, -1); }
                ;
 
 xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')'       { $$ = $3; }
@@ -8495,15 +8519,15 @@ type_list:      Typename                                                                { $$ = list_make1($1); }
 
 array_expr: '[' expr_list ']'
                                {
-                                       $$ = makeAArrayExpr($2);
+                                       $$ = makeAArrayExpr($2, @1);
                                }
                        | '[' array_expr_list ']'
                                {
-                                       $$ = makeAArrayExpr($2);
+                                       $$ = makeAArrayExpr($2, @1);
                                }
                        | '[' ']'
                                {
-                                       $$ = makeAArrayExpr(NIL);
+                                       $$ = makeAArrayExpr(NIL, @1);
                                }
                ;
 
@@ -8515,7 +8539,7 @@ array_expr_list: array_expr                                                       { $$ = list_make1($1); }
 extract_list:
                        extract_arg FROM a_expr
                                {
-                                       $$ = list_make2(makeStringConst($1), $3);
+                                       $$ = list_make2(makeStringConst($1, @1), $3);
                                }
                        | /*EMPTY*/                                                             { $$ = NIL; }
                ;
@@ -8599,8 +8623,9 @@ substr_list:
                                         * which it is likely to do if the second argument
                                         * is unknown or doesn't have an implicit cast to int4.
                                         */
-                                       $$ = list_make3($1, makeIntConst(1),
-                                                                       makeTypeCast($2, SystemTypeName("int4")));
+                                       $$ = list_make3($1, makeIntConst(1, -1),
+                                                                       makeTypeCast($2,
+                                                                                                SystemTypeName("int4"), -1));
                                }
                        | expr_list
                                {
@@ -8646,6 +8671,7 @@ case_expr:        CASE case_arg when_clause_list case_default END_P
                                        c->arg = (Expr *) $2;
                                        c->args = $3;
                                        c->defresult = (Expr *) $4;
+                                       c->location = @1;
                                        $$ = (Node *)c;
                                }
                ;
@@ -8662,6 +8688,7 @@ when_clause:
                                        CaseWhen *w = makeNode(CaseWhen);
                                        w->expr = (Expr *) $2;
                                        w->result = (Expr *) $4;
+                                       w->location = @1;
                                        $$ = (Node *)w;
                                }
                ;
@@ -8738,7 +8765,12 @@ opt_asymmetric: ASYMMETRIC
 
 ctext_expr:
                        a_expr                                  { $$ = (Node *) $1; }
-                       | DEFAULT                               { $$ = (Node *) makeNode(SetToDefault); }
+                       | DEFAULT
+                               {
+                                       SetToDefault *n = makeNode(SetToDefault);
+                                       n->location = @1;
+                                       $$ = (Node *) n;
+                               }
                ;
 
 ctext_expr_list:
@@ -8911,19 +8943,19 @@ func_name:      type_function_name
  */
 AexprConst: Iconst
                                {
-                                       $$ = makeIntConst($1);
+                                       $$ = makeIntConst($1, @1);
                                }
                        | FCONST
                                {
-                                       $$ = makeFloatConst($1);
+                                       $$ = makeFloatConst($1, @1);
                                }
                        | Sconst
                                {
-                                       $$ = makeStringConst($1);
+                                       $$ = makeStringConst($1, @1);
                                }
                        | BCONST
                                {
-                                       $$ = makeBitStringConst($1);
+                                       $$ = makeBitStringConst($1, @1);
                                }
                        | XCONST
                                {
@@ -8932,14 +8964,14 @@ AexprConst: Iconst
                                         * a <general literal> shall not be a
                                         * <bit string literal> or a <hex string literal>.
                                         */
-                                       $$ = makeBitStringConst($1);
+                                       $$ = makeBitStringConst($1, @1);
                                }
                        | func_name Sconst
                                {
                                        /* generic type 'literal' syntax */
                                        TypeName *t = makeTypeNameFromNameList($1);
                                        t->location = @1;
-                                       $$ = makeStringConstCast($2, t);
+                                       $$ = makeStringConstCast($2, @2, t);
                                }
                        | func_name '(' expr_list ')' Sconst
                                {
@@ -8947,38 +8979,38 @@ AexprConst: Iconst
                                        TypeName *t = makeTypeNameFromNameList($1);
                                        t->typmods = $3;
                                        t->location = @1;
-                                       $$ = makeStringConstCast($5, t);
+                                       $$ = makeStringConstCast($5, @5, t);
                                }
                        | ConstTypename Sconst
                                {
-                                       $$ = makeStringConstCast($2, $1);
+                                       $$ = makeStringConstCast($2, @2, $1);
                                }
                        | ConstInterval Sconst opt_interval
                                {
                                        TypeName *t = $1;
                                        /* precision is not specified, but fields may be... */
                                        if ($3 != INTERVAL_FULL_RANGE)
-                                               t->typmods = list_make1(makeIntConst($3));
-                                       $$ = makeStringConstCast($2, t);
+                                               t->typmods = list_make1(makeIntConst($3, @3));
+                                       $$ = makeStringConstCast($2, @2, t);
                                }
                        | ConstInterval '(' Iconst ')' Sconst opt_interval
                                {
                                        TypeName *t = $1;
-                                       t->typmods = list_make2(makeIntConst($6),
-                                                                                   makeIntConst($3));
-                                       $$ = makeStringConstCast($5, t);
+                                       t->typmods = list_make2(makeIntConst($6, @6),
+                                                                                   makeIntConst($3, @3));
+                                       $$ = makeStringConstCast($5, @5, t);
                                }
                        | TRUE_P
                                {
-                                       $$ = makeBoolAConst(TRUE);
+                                       $$ = makeBoolAConst(TRUE, @1);
                                }
                        | FALSE_P
                                {
-                                       $$ = makeBoolAConst(FALSE);
+                                       $$ = makeBoolAConst(FALSE, @1);
                                }
                        | NULL_P
                                {
-                                       $$ = makeNullAConst();
+                                       $$ = makeNullAConst(@1);
                                }
                ;
 
@@ -9522,94 +9554,100 @@ makeColumnRef(char *relname, List *indirection, int location)
 }
 
 static Node *
-makeTypeCast(Node *arg, TypeName *typename)
+makeTypeCast(Node *arg, TypeName *typename, int location)
 {
        TypeCast *n = makeNode(TypeCast);
        n->arg = arg;
        n->typename = typename;
+       n->location = location;
        return (Node *) n;
 }
 
 static Node *
-makeStringConst(char *str)
+makeStringConst(char *str, int location)
 {
        A_Const *n = makeNode(A_Const);
 
        n->val.type = T_String;
        n->val.val.str = str;
+       n->location = location;
 
        return (Node *)n;
 }
 
 static Node *
-makeStringConstCast(char *str, TypeName *typename)
+makeStringConstCast(char *str, int location, TypeName *typename)
 {
-       Node *s = makeStringConst(str);
+       Node *s = makeStringConst(str, location);
 
-       return makeTypeCast(s, typename);
+       return makeTypeCast(s, typename, -1);
 }
 
 static Node *
-makeIntConst(int val)
+makeIntConst(int val, int location)
 {
        A_Const *n = makeNode(A_Const);
 
        n->val.type = T_Integer;
        n->val.val.ival = val;
+       n->location = location;
 
        return (Node *)n;
 }
 
 static Node *
-makeFloatConst(char *str)
+makeFloatConst(char *str, int location)
 {
        A_Const *n = makeNode(A_Const);
 
        n->val.type = T_Float;
        n->val.val.str = str;
+       n->location = location;
 
        return (Node *)n;
 }
 
 static Node *
-makeBitStringConst(char *str)
+makeBitStringConst(char *str, int location)
 {
        A_Const *n = makeNode(A_Const);
 
        n->val.type = T_BitString;
        n->val.val.str = str;
+       n->location = location;
 
        return (Node *)n;
 }
 
 static Node *
-makeNullAConst(void)
+makeNullAConst(int location)
 {
        A_Const *n = makeNode(A_Const);
 
        n->val.type = T_Null;
+       n->location = location;
 
        return (Node *)n;
 }
 
 static Node *
-makeAConst(Value *v)
+makeAConst(Value *v, int location)
 {
        Node *n;
 
        switch (v->type)
        {
                case T_Float:
-                       n = makeFloatConst(v->val.str);
+                       n = makeFloatConst(v->val.str, location);
                        break;
 
                case T_Integer:
-                       n = makeIntConst(v->val.ival);
+                       n = makeIntConst(v->val.ival, location);
                        break;
 
                case T_String:
                default:
-                       n = makeStringConst(v->val.str);
+                       n = makeStringConst(v->val.str, location);
                        break;
        }
 
@@ -9620,14 +9658,15 @@ makeAConst(Value *v)
  * Create an A_Const string node and put it inside a boolean cast.
  */
 static Node *
-makeBoolAConst(bool state)
+makeBoolAConst(bool state, int location)
 {
        A_Const *n = makeNode(A_Const);
 
        n->val.type = T_String;
        n->val.val.str = (state ? "t" : "f");
+       n->location = location;
 
-       return makeTypeCast((Node *)n, SystemTypeName("bool"));
+       return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
 }
 
 /* makeOverlaps()
@@ -9799,6 +9838,7 @@ SystemFuncName(char *name)
  * Build a properly-qualified reference to a built-in type.
  *
  * typmod is defaulted, but may be changed afterwards by caller.
+ * Likewise for the location.
  */
 TypeName *
 SystemTypeName(char *name)
@@ -9827,6 +9867,9 @@ doNegate(Node *n, int location)
        {
                A_Const *con = (A_Const *)n;
 
+               /* report the constant's location as that of the '-' sign */
+               con->location = location;
+
                if (con->val.type == T_Integer)
                {
                        con->va