From c063da1769229efa8d8d21f0d068b3199ea3a6b3 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 22 Feb 2015 14:40:27 -0500 Subject: [PATCH] Add parse location fields to NullTest and BooleanTest structs. We did not need a location tag on NullTest or BooleanTest before, because no error messages referred directly to their locations. That's planned to change though, so add these fields in a separate housekeeping commit. Catversion bump because stored rules may change. --- src/backend/nodes/copyfuncs.c | 2 ++ src/backend/nodes/equalfuncs.c | 2 ++ src/backend/nodes/nodeFuncs.c | 18 ++++++++++++++---- src/backend/nodes/outfuncs.c | 2 ++ src/backend/nodes/readfuncs.c | 2 ++ src/backend/optimizer/plan/planagg.c | 1 + src/backend/optimizer/prep/prepqual.c | 2 ++ src/backend/optimizer/util/clauses.c | 3 +++ src/backend/optimizer/util/plancat.c | 1 + src/backend/parser/gram.y | 10 ++++++++++ src/backend/parser/parse_expr.c | 1 + src/backend/rewrite/rewriteManip.c | 1 + src/include/catalog/catversion.h | 2 +- src/include/nodes/primnodes.h | 2 ++ 14 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 8798cbe43d..5282a4fec2 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1693,6 +1693,7 @@ _copyNullTest(const NullTest *from) COPY_NODE_FIELD(arg); COPY_SCALAR_FIELD(nulltesttype); COPY_SCALAR_FIELD(argisrow); + COPY_LOCATION_FIELD(location); return newnode; } @@ -1707,6 +1708,7 @@ _copyBooleanTest(const BooleanTest *from) COPY_NODE_FIELD(arg); COPY_SCALAR_FIELD(booltesttype); + COPY_LOCATION_FIELD(location); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index a90386b800..fe509b0ad1 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -622,6 +622,7 @@ _equalNullTest(const NullTest *a, const NullTest *b) COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(nulltesttype); COMPARE_SCALAR_FIELD(argisrow); + COMPARE_LOCATION_FIELD(location); return true; } @@ -631,6 +632,7 @@ _equalBooleanTest(const BooleanTest *a, const BooleanTest *b) { COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(booltesttype); + COMPARE_LOCATION_FIELD(location); return true; } diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 21dfda7f79..d6f1f5bb6d 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -1346,12 +1346,22 @@ exprLocation(const Node *expr) } break; case T_NullTest: - /* just use argument's location */ - loc = exprLocation((Node *) ((const NullTest *) expr)->arg); + { + const NullTest *nexpr = (const NullTest *) expr; + + /* Much as above */ + loc = leftmostLoc(nexpr->location, + exprLocation((Node *) nexpr->arg)); + } break; case T_BooleanTest: - /* just use argument's location */ - loc = exprLocation((Node *) ((const BooleanTest *) expr)->arg); + { + const BooleanTest *bexpr = (const BooleanTest *) expr; + + /* Much as above */ + loc = leftmostLoc(bexpr->location, + exprLocation((Node *) bexpr->arg)); + } break; case T_CoerceToDomain: { diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 67b7d40406..98aa5f0310 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1370,6 +1370,7 @@ _outNullTest(StringInfo str, const NullTest *node) WRITE_NODE_FIELD(arg); WRITE_ENUM_FIELD(nulltesttype, NullTestType); WRITE_BOOL_FIELD(argisrow); + WRITE_LOCATION_FIELD(location); } static void @@ -1379,6 +1380,7 @@ _outBooleanTest(StringInfo str, const BooleanTest *node) WRITE_NODE_FIELD(arg); WRITE_ENUM_FIELD(booltesttype, BoolTestType); + WRITE_LOCATION_FIELD(location); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index ae24d0514f..563209c561 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1044,6 +1044,7 @@ _readNullTest(void) READ_NODE_FIELD(arg); READ_ENUM_FIELD(nulltesttype, NullTestType); READ_BOOL_FIELD(argisrow); + READ_LOCATION_FIELD(location); READ_DONE(); } @@ -1058,6 +1059,7 @@ _readBooleanTest(void) READ_NODE_FIELD(arg); READ_ENUM_FIELD(booltesttype, BoolTestType); + READ_LOCATION_FIELD(location); READ_DONE(); } diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index b90c2ef48c..af772a2c99 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -449,6 +449,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, ntest->arg = copyObject(mminfo->target); /* we checked it wasn't a rowtype in find_minmax_aggs_walker */ ntest->argisrow = false; + ntest->location = -1; /* User might have had that in WHERE already */ if (!list_member((List *) parse->jointree->quals, ntest)) diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c index bd50926b13..1176e819dd 100644 --- a/src/backend/optimizer/prep/prepqual.c +++ b/src/backend/optimizer/prep/prepqual.c @@ -212,6 +212,7 @@ negate_clause(Node *node) newexpr->nulltesttype = (expr->nulltesttype == IS_NULL ? IS_NOT_NULL : IS_NULL); newexpr->argisrow = expr->argisrow; + newexpr->location = expr->location; return (Node *) newexpr; } } @@ -247,6 +248,7 @@ negate_clause(Node *node) (int) expr->booltesttype); break; } + newexpr->location = expr->location; return (Node *) newexpr; } break; diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index b340b01715..84d58ae595 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -3305,6 +3305,7 @@ eval_const_expressions_mutator(Node *node, newntest->arg = (Expr *) relem; newntest->nulltesttype = ntest->nulltesttype; newntest->argisrow = type_is_rowtype(exprType(relem)); + newntest->location = ntest->location; newargs = lappend(newargs, newntest); } /* If all the inputs were constants, result is TRUE */ @@ -3343,6 +3344,7 @@ eval_const_expressions_mutator(Node *node, newntest->arg = (Expr *) arg; newntest->nulltesttype = ntest->nulltesttype; newntest->argisrow = ntest->argisrow; + newntest->location = ntest->location; return (Node *) newntest; } case T_BooleanTest: @@ -3395,6 +3397,7 @@ eval_const_expressions_mutator(Node *node, newbtest = makeNode(BooleanTest); newbtest->arg = (Expr *) arg; newbtest->booltesttype = btest->booltesttype; + newbtest->location = btest->location; return (Node *) newbtest; } case T_PlaceHolderVar: diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 5cbd6a98f2..313a5c1ab2 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -720,6 +720,7 @@ get_relation_constraints(PlannerInfo *root, 0); ntest->nulltesttype = IS_NOT_NULL; ntest->argisrow = type_is_rowtype(att->atttypid); + ntest->location = -1; result = lappend(result, ntest); } } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index b8af296397..76b0affff0 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11299,6 +11299,7 @@ a_expr: c_expr { $$ = $1; } NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; n->nulltesttype = IS_NULL; + n->location = @2; $$ = (Node *)n; } | a_expr ISNULL @@ -11306,6 +11307,7 @@ a_expr: c_expr { $$ = $1; } NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; n->nulltesttype = IS_NULL; + n->location = @2; $$ = (Node *)n; } | a_expr IS NOT NULL_P %prec IS @@ -11313,6 +11315,7 @@ a_expr: c_expr { $$ = $1; } NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; n->nulltesttype = IS_NOT_NULL; + n->location = @2; $$ = (Node *)n; } | a_expr NOTNULL @@ -11320,6 +11323,7 @@ a_expr: c_expr { $$ = $1; } NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; n->nulltesttype = IS_NOT_NULL; + n->location = @2; $$ = (Node *)n; } | row OVERLAPS row @@ -11343,6 +11347,7 @@ a_expr: c_expr { $$ = $1; } BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_TRUE; + b->location = @2; $$ = (Node *)b; } | a_expr IS NOT TRUE_P %prec IS @@ -11350,6 +11355,7 @@ a_expr: c_expr { $$ = $1; } BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_TRUE; + b->location = @2; $$ = (Node *)b; } | a_expr IS FALSE_P %prec IS @@ -11357,6 +11363,7 @@ a_expr: c_expr { $$ = $1; } BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_FALSE; + b->location = @2; $$ = (Node *)b; } | a_expr IS NOT FALSE_P %prec IS @@ -11364,6 +11371,7 @@ a_expr: c_expr { $$ = $1; } BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_FALSE; + b->location = @2; $$ = (Node *)b; } | a_expr IS UNKNOWN %prec IS @@ -11371,6 +11379,7 @@ a_expr: c_expr { $$ = $1; } BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_UNKNOWN; + b->location = @2; $$ = (Node *)b; } | a_expr IS NOT UNKNOWN %prec IS @@ -11378,6 +11387,7 @@ a_expr: c_expr { $$ = $1; } BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_UNKNOWN; + b->location = @2; $$ = (Node *)b; } | a_expr IS DISTINCT FROM a_expr %prec IS diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 791639a7db..f314745818 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -789,6 +789,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a) NullTest *n = makeNode(NullTest); n->nulltesttype = IS_NULL; + n->location = a->location; if (exprIsNullConstant(lexpr)) n->arg = (Expr *) rexpr; diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 75dd41eab6..df457080fe 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -1023,6 +1023,7 @@ AddInvertedQual(Query *parsetree, Node *qual) invqual = makeNode(BooleanTest); invqual->arg = (Expr *) qual; invqual->booltesttype = IS_NOT_TRUE; + invqual->location = -1; AddQual(parsetree, (Node *) invqual); } diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 7133b96151..7ed743df97 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201502191 +#define CATALOG_VERSION_NO 201502221 #endif diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 1d06f426be..b004da6dc4 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1050,6 +1050,7 @@ typedef struct NullTest Expr *arg; /* input expression */ NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ bool argisrow; /* T if input is of a composite type */ + int location; /* token location, or -1 if unknown */ } NullTest; /* @@ -1071,6 +1072,7 @@ typedef struct BooleanTest Expr xpr; Expr *arg; /* input expression */ BoolTestType booltesttype; /* test type */ + int location; /* token location, or -1 if unknown */ } BooleanTest; /*