diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 0b5652071d1..bec24aab720 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -136,6 +136,13 @@ typedef struct KeyActions KeyAction *deleteAction; } KeyActions; +typedef struct ListWithBoundary +{ + Node *expr; + ParseLoc start; + ParseLoc end; +} ListWithBoundary; + /* ConstraintAttributeSpec yields an integer bitmask of these flags: */ #define CAS_NOT_DEFERRABLE 0x01 #define CAS_DEFERRABLE 0x02 @@ -269,6 +276,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); struct KeyAction *keyaction; ReturningClause *retclause; ReturningOptionKind retoptionkind; + struct ListWithBoundary *listwithboundary; } %type stmt toplevel_stmt schema_stmt routine_body_stmt @@ -523,8 +531,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type def_elem reloption_elem old_aggr_elem operator_def_elem %type def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound - columnref in_expr having_clause func_table xmltable array_expr + columnref having_clause func_table xmltable array_expr OptWhereClause operator_def_arg +%type in_expr %type opt_column_and_period_list %type rowsfrom_item rowsfrom_list opt_col_def_list %type opt_ordinality opt_without_overlaps @@ -15289,46 +15298,58 @@ a_expr: c_expr { $$ = $1; } } | a_expr IN_P in_expr { + ListWithBoundary *n = $3; + /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($3, SubLink)) + if (IsA(n->expr, SubLink)) { /* generate foo = ANY (subquery) */ - SubLink *n = (SubLink *) $3; - - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - $$ = (Node *) n; + SubLink *n2 = (SubLink *) $3; + + n2->subLinkType = ANY_SUBLINK; + n2->subLinkId = 0; + n2->testexpr = $1; + n2->operName = NIL; /* show it's IN not = ANY */ + n2->location = @2; + $$ = (Node *) n2; } else { /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); + A_Expr *n2 = makeSimpleA_Expr(AEXPR_IN, "=", $1, n->expr, @2); + + n2->location_start = $3->start; + n2->location_end = $3->end; + $$ = (Node *) n2; } } | a_expr NOT_LA IN_P in_expr %prec NOT_LA { + ListWithBoundary *n = $4; + /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($4, SubLink)) + if (IsA(n->expr, SubLink)) { /* generate NOT (foo = ANY (subquery)) */ /* Make an = ANY node */ - SubLink *n = (SubLink *) $4; + SubLink *n2 = (SubLink *) $4; - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; + n2->subLinkType = ANY_SUBLINK; + n2->subLinkId = 0; + n2->testexpr = $1; + n2->operName = NIL; /* show it's IN not = ANY */ + n2->location = @2; /* Stick a NOT on top; must have same parse location */ - $$ = makeNotExpr((Node *) n, @2); + $$ = makeNotExpr((Node *) n2, @2); } else { /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); + A_Expr *n2 = makeSimpleA_Expr(AEXPR_IN, "<>", $1, n->expr, @2); + + n2->location_start = $4->start; + n2->location_end = $4->end; + $$ = (Node *) n2; } } | a_expr subquery_Op sub_type select_with_parens %prec Op @@ -16897,12 +16918,25 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } in_expr: select_with_parens { SubLink *n = makeNode(SubLink); + ListWithBoundary *n2 = palloc(sizeof(ListWithBoundary)); n->subselect = $1; /* other fields will be filled later */ - $$ = (Node *) n; + + n2->expr = (Node *) n; + n2->start = -1; + n2->end = -1; + $$ = n2; + } + | '(' expr_list ')' + { + ListWithBoundary *n = palloc(sizeof(ListWithBoundary)); + + n->expr = (Node *) $2; + n->start = @1; + n->end = @3; + $$ = n; } - | '(' expr_list ')' { $$ = (Node *) $2; } ; /* diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 4610fc61293..c32cb0673d6 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -347,6 +347,8 @@ typedef struct A_Expr Node *lexpr; /* left argument, or NULL if none */ Node *rexpr; /* right argument, or NULL if none */ ParseLoc location; /* token location, or -1 if unknown */ + ParseLoc location_start; + ParseLoc location_end; } A_Expr; /* @@ -502,6 +504,8 @@ typedef struct A_ArrayExpr NodeTag type; List *elements; /* array element expressions */ ParseLoc location; /* token location, or -1 if unknown */ + ParseLoc location_start; + ParseLoc location_end; } A_ArrayExpr; /*