*
*
* 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
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),
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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");
}
transform, exprType(transform),
targettype, targettypmod,
COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST);
+ COERCE_IMPLICIT_CAST,
+ -1);
if (transform == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
defaultexpr, exprType(defaultexpr),
targettype, targettypmod,
COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST);
+ COERCE_IMPLICIT_CAST,
+ -1);
if (defaultexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*
*
* 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
domVal = makeNode(CoerceToDomainValue);
domVal->typeId = baseTypeOid;
domVal->typeMod = typMod;
+ domVal->location = -1; /* will be set when/if used */
pstate->p_value_substitute = (Node *) domVal;
* 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
COPY_SCALAR_FIELD(varlevelsup);
COPY_SCALAR_FIELD(varnoold);
COPY_SCALAR_FIELD(varoattno);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(constisnull);
COPY_SCALAR_FIELD(constbyval);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(paramid);
COPY_SCALAR_FIELD(paramtype);
COPY_SCALAR_FIELD(paramtypmod);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(agglevelsup);
COPY_SCALAR_FIELD(aggstar);
COPY_SCALAR_FIELD(aggdistinct);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(funcretset);
COPY_SCALAR_FIELD(funcformat);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(opresulttype);
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(opresulttype);
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(opfuncid);
COPY_SCALAR_FIELD(useOr);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(boolop);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(testexpr);
COPY_NODE_FIELD(operName);
COPY_NODE_FIELD(subselect);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(resulttype);
COPY_SCALAR_FIELD(resulttypmod);
COPY_SCALAR_FIELD(relabelformat);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(arg);
COPY_SCALAR_FIELD(resulttype);
COPY_SCALAR_FIELD(coerceformat);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(resulttypmod);
COPY_SCALAR_FIELD(isExplicit);
COPY_SCALAR_FIELD(coerceformat);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(arg);
COPY_SCALAR_FIELD(resulttype);
COPY_SCALAR_FIELD(convertformat);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(arg);
COPY_NODE_FIELD(args);
COPY_NODE_FIELD(defresult);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(expr);
COPY_NODE_FIELD(result);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(element_typeid);
COPY_NODE_FIELD(elements);
COPY_SCALAR_FIELD(multidims);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(args);
COPY_SCALAR_FIELD(row_typeid);
COPY_SCALAR_FIELD(row_format);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(coalescetype);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(minmaxtype);
COPY_SCALAR_FIELD(op);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(xmloption);
COPY_SCALAR_FIELD(type);
COPY_SCALAR_FIELD(typmod);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(opresulttype);
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(resulttype);
COPY_SCALAR_FIELD(resulttypmod);
COPY_SCALAR_FIELD(coercionformat);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(typeId);
COPY_SCALAR_FIELD(typeMod);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(typeId);
COPY_SCALAR_FIELD(typeMod);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(name);
COPY_NODE_FIELD(lexpr);
COPY_NODE_FIELD(rexpr);
- COPY_SCALAR_FIELD(location);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
ColumnRef *newnode = makeNode(ColumnRef);
COPY_NODE_FIELD(fields);
- COPY_SCALAR_FIELD(location);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
ParamRef *newnode = makeNode(ParamRef);
COPY_SCALAR_FIELD(number);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
break;
}
+ COPY_LOCATION_FIELD(location);
+
return newnode;
}
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;
}
A_ArrayExpr *newnode = makeNode(A_ArrayExpr);
COPY_NODE_FIELD(elements);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_STRING_FIELD(name);
COPY_NODE_FIELD(indirection);
COPY_NODE_FIELD(val);
- COPY_SCALAR_FIELD(location);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(typmods);
COPY_SCALAR_FIELD(typemod);
COPY_NODE_FIELD(arrayBounds);
- COPY_SCALAR_FIELD(location);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_NODE_FIELD(arg);
COPY_NODE_FIELD(typename);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
COPY_SCALAR_FIELD(xmloption);
COPY_NODE_FIELD(expr);
COPY_NODE_FIELD(typename);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
* 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
COMPARE_SCALAR_FIELD(varlevelsup);
COMPARE_SCALAR_FIELD(varnoold);
COMPARE_SCALAR_FIELD(varoattno);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
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
COMPARE_SCALAR_FIELD(paramid);
COMPARE_SCALAR_FIELD(paramtype);
COMPARE_SCALAR_FIELD(paramtypmod);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(agglevelsup);
COMPARE_SCALAR_FIELD(aggstar);
COMPARE_SCALAR_FIELD(aggdistinct);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
return false;
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(opresulttype);
COMPARE_SCALAR_FIELD(opretset);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(opresulttype);
COMPARE_SCALAR_FIELD(opretset);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(useOr);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
{
COMPARE_SCALAR_FIELD(boolop);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_NODE_FIELD(testexpr);
COMPARE_NODE_FIELD(operName);
COMPARE_NODE_FIELD(subselect);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
b->relabelformat != COERCE_DONTCARE)
return false;
+ COMPARE_LOCATION_FIELD(location);
+
return true;
}
b->coerceformat != COERCE_DONTCARE)
return false;
+ COMPARE_LOCATION_FIELD(location);
+
return true;
}
b->coerceformat != COERCE_DONTCARE)
return false;
+ COMPARE_LOCATION_FIELD(location);
+
return true;
}
b->convertformat != COERCE_DONTCARE)
return false;
+ COMPARE_LOCATION_FIELD(location);
+
return true;
}
COMPARE_NODE_FIELD(arg);
COMPARE_NODE_FIELD(args);
COMPARE_NODE_FIELD(defresult);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
{
COMPARE_NODE_FIELD(expr);
COMPARE_NODE_FIELD(result);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(element_typeid);
COMPARE_NODE_FIELD(elements);
COMPARE_SCALAR_FIELD(multidims);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
b->row_format != COERCE_DONTCARE)
return false;
+ COMPARE_LOCATION_FIELD(location);
+
return true;
}
{
COMPARE_SCALAR_FIELD(coalescetype);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(minmaxtype);
COMPARE_SCALAR_FIELD(op);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(xmloption);
COMPARE_SCALAR_FIELD(type);
COMPARE_SCALAR_FIELD(typmod);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(opresulttype);
COMPARE_SCALAR_FIELD(opretset);
COMPARE_NODE_FIELD(args);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
b->coercionformat != COERCE_DONTCARE)
return false;
+ COMPARE_LOCATION_FIELD(location);
+
return true;
}
{
COMPARE_SCALAR_FIELD(typeId);
COMPARE_SCALAR_FIELD(typeMod);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
{
COMPARE_SCALAR_FIELD(typeId);
COMPARE_SCALAR_FIELD(typeMod);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_NODE_FIELD(name);
COMPARE_NODE_FIELD(lexpr);
COMPARE_NODE_FIELD(rexpr);
- COMPARE_SCALAR_FIELD(location);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
_equalColumnRef(ColumnRef *a, ColumnRef *b)
{
COMPARE_NODE_FIELD(fields);
- COMPARE_SCALAR_FIELD(location);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
_equalParamRef(ParamRef *a, ParamRef *b)
{
COMPARE_SCALAR_FIELD(number);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
{
if (!equal(&a->val, &b->val)) /* hack for in-line Value field */
return false;
+ COMPARE_LOCATION_FIELD(location);
return true;
}
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;
}
_equalA_ArrayExpr(A_ArrayExpr *a, A_ArrayExpr *b)
{
COMPARE_NODE_FIELD(elements);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(indirection);
COMPARE_NODE_FIELD(val);
- COMPARE_SCALAR_FIELD(location);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_NODE_FIELD(typmods);
COMPARE_SCALAR_FIELD(typemod);
COMPARE_NODE_FIELD(arrayBounds);
- COMPARE_SCALAR_FIELD(location);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
{
COMPARE_NODE_FIELD(arg);
COMPARE_NODE_FIELD(typename);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
COMPARE_SCALAR_FIELD(xmloption);
COMPARE_NODE_FIELD(expr);
COMPARE_NODE_FIELD(typename);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
var->varnoold = varno;
var->varoattno = varattno;
+ /* Likewise, we just set location to "unknown" here */
+ var->location = -1;
+
return var;
}
cnst->constvalue = constvalue;
cnst->constisnull = constisnull;
cnst->constbyval = constbyval;
+ cnst->location = -1; /* "unknown" */
return cnst;
}
* 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;
}
r->resulttype = rtype;
r->resulttypmod = rtypmod;
r->relabelformat = rformat;
+ r->location = -1;
return r;
}
funcexpr->funcretset = false; /* only allowed case here */
funcexpr->funcformat = fformat;
funcexpr->args = args;
+ funcexpr->location = -1;
return funcexpr;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
static bool expression_returns_set_walker(Node *node, void *context);
+static int leftmostLoc(int loc1, int loc2);
/*
}
+/*
+ * 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
*
*
*
* 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) " "), \
WRITE_UINT_FIELD(varlevelsup);
WRITE_UINT_FIELD(varnoold);
WRITE_INT_FIELD(varoattno);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_INT_FIELD(constlen);
WRITE_BOOL_FIELD(constbyval);
WRITE_BOOL_FIELD(constisnull);
+ WRITE_LOCATION_FIELD(location);
appendStringInfo(str, " :constvalue ");
if (node->constisnull)
WRITE_INT_FIELD(paramid);
WRITE_OID_FIELD(paramtype);
WRITE_INT_FIELD(paramtypmod);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_UINT_FIELD(agglevelsup);
WRITE_BOOL_FIELD(aggstar);
WRITE_BOOL_FIELD(aggdistinct);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_BOOL_FIELD(funcretset);
WRITE_ENUM_FIELD(funcformat, CoercionForm);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(opresulttype);
WRITE_BOOL_FIELD(opretset);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(opresulttype);
WRITE_BOOL_FIELD(opretset);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(opfuncid);
WRITE_BOOL_FIELD(useOr);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
_outToken(str, opstr);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(testexpr);
WRITE_NODE_FIELD(operName);
WRITE_NODE_FIELD(subselect);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(resulttype);
WRITE_INT_FIELD(resulttypmod);
WRITE_ENUM_FIELD(relabelformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(arg);
WRITE_OID_FIELD(resulttype);
WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_INT_FIELD(resulttypmod);
WRITE_BOOL_FIELD(isExplicit);
WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(arg);
WRITE_OID_FIELD(resulttype);
WRITE_ENUM_FIELD(convertformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(arg);
WRITE_NODE_FIELD(args);
WRITE_NODE_FIELD(defresult);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(expr);
WRITE_NODE_FIELD(result);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(element_typeid);
WRITE_NODE_FIELD(elements);
WRITE_BOOL_FIELD(multidims);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(args);
WRITE_OID_FIELD(row_typeid);
WRITE_ENUM_FIELD(row_format, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(coalescetype);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(minmaxtype);
WRITE_ENUM_FIELD(op, MinMaxOp);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_ENUM_FIELD(xmloption, XmlOptionType);
WRITE_OID_FIELD(type);
WRITE_INT_FIELD(typmod);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(opresulttype);
WRITE_BOOL_FIELD(opretset);
WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(resulttype);
WRITE_INT_FIELD(resulttypmod);
WRITE_ENUM_FIELD(coercionformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(typeId);
WRITE_INT_FIELD(typeMod);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_OID_FIELD(typeId);
WRITE_INT_FIELD(typeMod);
+ WRITE_LOCATION_FIELD(location);
}
static void
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
WRITE_ENUM_FIELD(xmloption, XmlOptionType);
WRITE_NODE_FIELD(expr);
WRITE_NODE_FIELD(typename);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(typmods);
WRITE_INT_FIELD(typemod);
WRITE_NODE_FIELD(arrayBounds);
- WRITE_INT_FIELD(location);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(arg);
WRITE_NODE_FIELD(typename);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_FIELD(lexpr);
WRITE_NODE_FIELD(rexpr);
- WRITE_INT_FIELD(location);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_TYPE("COLUMNREF");
WRITE_NODE_FIELD(fields);
- WRITE_INT_FIELD(location);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_TYPE("PARAMREF");
WRITE_INT_FIELD(number);
+ WRITE_LOCATION_FIELD(location);
}
static void
appendStringInfo(str, " :val ");
_outValue(str, &(node->val));
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_NODE_TYPE("A_ARRAYEXPR");
WRITE_NODE_FIELD(elements);
+ WRITE_LOCATION_FIELD(location);
}
static void
WRITE_STRING_FIELD(name);
WRITE_NODE_FIELD(indirection);
WRITE_NODE_FIELD(val);
- WRITE_INT_FIELD(location);
+ WRITE_LOCATION_FIELD(location);
}
static void
*
*
* 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 */ \
READ_UINT_FIELD(varlevelsup);
READ_UINT_FIELD(varnoold);
READ_INT_FIELD(varoattno);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
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)
READ_INT_FIELD(paramid);
READ_OID_FIELD(paramtype);
READ_INT_FIELD(paramtypmod);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_UINT_FIELD(agglevelsup);
READ_BOOL_FIELD(aggstar);
READ_BOOL_FIELD(aggdistinct);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_BOOL_FIELD(funcretset);
READ_ENUM_FIELD(funcformat, CoercionForm);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_BOOL_FIELD(useOr);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_NODE_FIELD(testexpr);
READ_NODE_FIELD(operName);
READ_NODE_FIELD(subselect);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(resulttype);
READ_INT_FIELD(resulttypmod);
READ_ENUM_FIELD(relabelformat, CoercionForm);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_NODE_FIELD(arg);
READ_OID_FIELD(resulttype);
READ_ENUM_FIELD(coerceformat, CoercionForm);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_INT_FIELD(resulttypmod);
READ_BOOL_FIELD(isExplicit);
READ_ENUM_FIELD(coerceformat, CoercionForm);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_NODE_FIELD(arg);
READ_OID_FIELD(resulttype);
READ_ENUM_FIELD(convertformat, CoercionForm);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_NODE_FIELD(arg);
READ_NODE_FIELD(args);
READ_NODE_FIELD(defresult);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_NODE_FIELD(expr);
READ_NODE_FIELD(result);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(element_typeid);
READ_NODE_FIELD(elements);
READ_BOOL_FIELD(multidims);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_NODE_FIELD(args);
READ_OID_FIELD(row_typeid);
READ_ENUM_FIELD(row_format, CoercionForm);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(coalescetype);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(minmaxtype);
READ_ENUM_FIELD(op, MinMaxOp);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_ENUM_FIELD(xmloption, XmlOptionType);
READ_OID_FIELD(type);
READ_INT_FIELD(typmod);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(opresulttype);
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(resulttype);
READ_INT_FIELD(resulttypmod);
READ_ENUM_FIELD(coercionformat, CoercionForm);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(typeId);
READ_INT_FIELD(typeMod);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
READ_OID_FIELD(typeId);
READ_INT_FIELD(typeMod);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
retval->paramid = i;
retval->paramtype = var->vartype;
retval->paramtypmod = var->vartypmod;
+ retval->location = -1;
return retval;
}
retval->paramid = i;
retval->paramtype = agg->aggtype;
retval->paramtypmod = -1;
+ retval->location = -1;
return retval;
}
retval->paramid = list_length(root->glob->paramlist);
retval->paramtype = paramtype;
retval->paramtypmod = paramtypmod;
+ retval->location = -1;
pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) retval;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
newopexpr->opresulttype = opexpr->opresulttype;
newopexpr->opretset = opexpr->opretset;
newopexpr->args = opexpr->args;
+ newopexpr->location = opexpr->location;
return (Expr *) newopexpr;
}
else
newopexpr->opfuncid = InvalidOid;
newopexpr->useOr = !saopexpr->useOr;
newopexpr->args = saopexpr->args;
+ newopexpr->location = saopexpr->location;
return (Expr *) newopexpr;
}
else
* 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 $
*
*-------------------------------------------------------------------------
*/
InvalidOid, -1,
atttype,
COERCE_IMPLICIT_CAST,
+ -1,
false,
false);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
rowexpr->args = fields;
rowexpr->row_typeid = var->vartype;
rowexpr->row_format = COERCE_IMPLICIT_CAST;
+ rowexpr->location = -1;
+
return (Node *) rowexpr;
}
}
*
*
* 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
expr->args = list_make2(leftop, rightop);
else
expr->args = list_make1(leftop);
+ expr->location = -1;
return (Expr *) expr;
}
expr->boolop = NOT_EXPR;
expr->args = list_make1(notclause);
+ expr->location = -1;
return (Expr *) expr;
}
expr->boolop = OR_EXPR;
expr->args = orclauses;
+ expr->location = -1;
return (Expr *) expr;
}
expr->boolop = AND_EXPR;
expr->args = andclauses;
+ expr->location = -1;
return (Expr *) expr;
}
newexpr->funcretset = expr->funcretset;
newexpr->funcformat = expr->funcformat;
newexpr->args = args;
+ newexpr->location = expr->location;
return (Node *) newexpr;
}
if (IsA(node, OpExpr))
newexpr->opresulttype = expr->opresulttype;
newexpr->opretset = expr->opretset;
newexpr->args = args;
+ newexpr->location = expr->location;
return (Node *) newexpr;
}
if (IsA(node, DistinctExpr))
newexpr->opresulttype = expr->opresulttype;
newexpr->opretset = expr->opretset;
newexpr->args = args;
+ newexpr->location = expr->location;
return (Node *) newexpr;
}
if (IsA(node, BoolExpr))
newrelabel->resulttype = relabel->resulttype;
newrelabel->resulttypmod = relabel->resulttypmod;
newrelabel->relabelformat = relabel->relabelformat;
+ newrelabel->location = relabel->location;
return (Node *) newrelabel;
}
}
newexpr->arg = arg;
newexpr->resulttype = expr->resulttype;
newexpr->coerceformat = expr->coerceformat;
+ newexpr->location = expr->location;
return (Node *) newexpr;
}
if (IsA(node, ArrayCoerceExpr))
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
newcasewhen->expr = (Expr *) casecond;
newcasewhen->result = (Expr *) caseresult;
+ newcasewhen->location = oldcasewhen->location;
newargs = lappend(newargs, newcasewhen);
continue;
}
newcase->arg = (Expr *) newarg;
newcase->args = newargs;
newcase->defresult = (Expr *) defresult;
+ newcase->location = caseexpr->location;
return (Node *) newcase;
}
if (IsA(node, CaseTestExpr))
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,
newcoalesce = makeNode(CoalesceExpr);
newcoalesce->coalescetype = coalesceexpr->coalescetype;
newcoalesce->args = newargs;
+ newcoalesce->location = coalesceexpr->location;
return (Node *) newcoalesce;
}
if (IsA(node, FieldSelect))
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);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
rowexpr->args = fields;
rowexpr->row_typeid = var->vartype;
rowexpr->row_format = COERCE_IMPLICIT_CAST;
+ rowexpr->location = -1;
return (Node *) rowexpr;
}
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
{
Query *qry = makeNode(Query);
List *exprsLists = NIL;
- List **coltype_lists = NULL;
+ List **colexprs = NULL;
Oid *coltypes = NULL;
int sublist_length = -1;
List *newExprsLists;
{
/* 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))
exprsLists = lappend(exprsLists, sublist);
+ /* Check for DEFAULT and build per-column expression lists */
i = 0;
foreach(lc2, sublist)
{
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++;
}
}
*/
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;
int leftmostRTI;
Query *leftmostQuery;
SetOperationStmt *sostmt;
+ List *socolinfo;
List *intoColNames = NIL;
List *sortClause;
Node *limitOffset;
/*
* 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;
/*
* 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;
char selectName[32];
RangeTblEntry *rte;
RangeTblRef *rtr;
+ ListCell *tl;
/*
* Transform SelectStmt into a Query.
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.
*/
{
/* 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" :
/*
* 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);
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)
*
*
* 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
/*#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);
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);
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;
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
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
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;
}
;
;
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"; }
zone_value:
Sconst
{
- $$ = makeStringConst($1);
+ $$ = makeStringConst($1, @1);
}
| IDENT
{
- $$ = makeStringConst($1);
+ $$ = makeStringConst($1, @1);
}
| ConstInterval Sconst opt_interval
{
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
{
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; }
;
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 */
| ALL
{
/* LIMIT ALL is represented as a NULL constant */
- $$ = makeNullAConst();
+ $$ = makeNullAConst(@1);
}
;
{
$$ = $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));
}
;
else
{
$$ = SystemTypeName("bit");
- $$->typmods = list_make1(makeIntConst(1));
+ $$->typmods = list_make1(makeIntConst(1, -1));
}
$$->location = @1;
}
}
$$ = SystemTypeName($1);
- $$->typmods = list_make1(makeIntConst($3));
+ $$->typmods = list_make1(makeIntConst($3, @3));
$$->location = @1;
}
;
/* 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;
}
$$ = SystemTypeName("timestamptz");
else
$$ = SystemTypeName("timestamp");
- $$->typmods = list_make1(makeIntConst($3));
+ $$->typmods = list_make1(makeIntConst($3, @3));
$$->location = @1;
}
| TIMESTAMP opt_timezone
$$ = SystemTypeName("timetz");
else
$$ = SystemTypeName("time");
- $$->typmods = list_make1(makeIntConst($3));
+ $$->typmods = list_make1(makeIntConst($3, @3));
$$->location = @1;
}
| TIME opt_timezone
*/
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);
{
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;
{
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;
n->subLinkType = ANY_SUBLINK;
n->testexpr = $1;
n->operName = list_make1(makeString("="));
+ n->location = @2;
$$ = (Node *)n;
}
else
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);
}
n->testexpr = $1;
n->operName = $2;
n->subselect = $4;
+ n->location = @2;
$$ = (Node *)n;
}
| a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
}
| 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);
}
;
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
}
| 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);
}
;
{
ParamRef *p = makeNode(ParamRef);
p->number = $1;
+ p->location = @1;
if ($2)
{
A_Indirection *n = makeNode(A_Indirection);
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $1;
+ n->location = @1;
$$ = (Node *)n;
}
| EXISTS select_with_parens
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $2;
+ n->location = @1;
$$ = (Node *)n;
}
| ARRAY select_with_parens
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;
}
;
* 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
{
* 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 ')'
{
*/
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
{
*/
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
{
* 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 ')'
{
*/
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
{
* 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 ')'
{
*/
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
{
$$ = (Node *)n;
}
| CAST '(' a_expr AS Typename ')'
- { $$ = makeTypeCast($3, $5); }
+ { $$ = makeTypeCast($3, $5, @1); }
| EXTRACT '(' extract_list ')'
{
FuncCall *n = makeNode(FuncCall);
{
CoalesceExpr *c = makeNode(CoalesceExpr);
c->args = $3;
+ c->location = @1;
$$ = (Node *)c;
}
| GREATEST '(' expr_list ')'
MinMaxExpr *v = makeNode(MinMaxExpr);
v->args = $3;
v->op = IS_GREATEST;
+ v->location = @1;
$$ = (Node *)v;
}
| LEAST '(' expr_list ')'
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 ')'
{
n->xmloption = $3;
n->expr = $4;
n->typename = $6;
+ n->location = @1;
$$ = (Node *)n;
}
;
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; }
array_expr: '[' expr_list ']'
{
- $$ = makeAArrayExpr($2);
+ $$ = makeAArrayExpr($2, @1);
}
| '[' array_expr_list ']'
{
- $$ = makeAArrayExpr($2);
+ $$ = makeAArrayExpr($2, @1);
}
| '[' ']'
{
- $$ = makeAArrayExpr(NIL);
+ $$ = makeAArrayExpr(NIL, @1);
}
;
extract_list:
extract_arg FROM a_expr
{
- $$ = list_make2(makeStringConst($1), $3);
+ $$ = list_make2(makeStringConst($1, @1), $3);
}
| /*EMPTY*/ { $$ = NIL; }
;
* 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
{
c->arg = (Expr *) $2;
c->args = $3;
c->defresult = (Expr *) $4;
+ c->location = @1;
$$ = (Node *)c;
}
;
CaseWhen *w = makeNode(CaseWhen);
w->expr = (Expr *) $2;
w->result = (Expr *) $4;
+ w->location = @1;
$$ = (Node *)w;
}
;
ctext_expr:
a_expr { $$ = (Node *) $1; }
- | DEFAULT { $$ = (Node *) makeNode(SetToDefault); }
+ | DEFAULT
+ {
+ SetToDefault *n = makeNode(SetToDefault);
+ n->location = @1;
+ $$ = (Node *) n;
+ }
;
ctext_expr_list:
*/
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
{
* 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
{
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);
}
;
}
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;
}
* 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()
* 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)
{
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