track_list_boundaries.txt

text/plain

Filename: track_list_boundaries.txt
Type: text/plain
Part: 0
Message: Re: queryId constant squashing does not support prepared statements
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 <node>	stmt toplevel_stmt schema_stmt routine_body_stmt
@@ -523,8 +531,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <defelt>	def_elem reloption_elem old_aggr_elem operator_def_elem
 %type <node>	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 <listwithboundary> in_expr
 %type <list>	opt_column_and_period_list
 %type <list>	rowsfrom_item rowsfrom_list opt_col_def_list
 %type <boolean> 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;
 
 /*