hi.

while working on it, I guess I found another bug,  below JumbleQuery will return
the same result:

SELECT FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
SELECT a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
SELECT a, b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;

so I think TargetEntry.resjunk should not be marked as query_jumble_ignore.

addRangeTableEntryForGroup
will make RangeTblEntry(RTE_GROUP) have a newly copied original groupexprs.
Query->targetList also has the original groupexprs.

but after parseCheckAggregates->substitute_grouped_columns.
Query->targetList Var node will point to the offset of the RTE_GROUP,
not the RTE_RELATION.
see src/backend/parser/parse_agg.c line 1543.

After parseCheckAggregates, JumbleQuery(Query->targetList) will produce the same
result as long as the grouping columns have the same list of data types.
JumbleQuery(Query->groupClause) will also produce the same result
as long as the grouping columns have the same list of data types.

Since only the RangeTblEntry(RTE_GROUP) have the original grouping expressions,
we can not mark the RangeTblEntry->groupexprs as query_jumble_ignore.

looking at, transformUpdateTargetList->transformTargetList
so i think it's OK to remove query_jumble_ignore from TargetEntry.resjunk for
INSERT/UPDATE/DELETE.


--
jian
https://www.enterprisedb.com/
From 15623f1bea4b7ed6bf778113ad627765ef2f86a9 Mon Sep 17 00:00:00 2001
From: jian he <[email protected]>
Date: Mon, 12 Jan 2026 16:17:37 +0800
Subject: [PATCH v1 1/1] Remove query_jumble_ignore from the fields in
 RangeTblEntry and TargetEntry

discussion: https://postgr.es/m/CACJufxEy2W+tCqC7XuJ94r3ivWsM=onkjp94krfx3hoarjb...@mail.gmail.com
---
 .../pg_stat_statements/expected/select.out    | 112 +++++++++++++++++-
 contrib/pg_stat_statements/sql/select.sql     |  18 +++
 src/include/nodes/parsenodes.h                |   2 +-
 src/include/nodes/primnodes.h                 |   2 +-
 4 files changed, 130 insertions(+), 4 deletions(-)

diff --git a/contrib/pg_stat_statements/expected/select.out b/contrib/pg_stat_statements/expected/select.out
index 75c896f3885..eafc54964dc 100644
--- a/contrib/pg_stat_statements/expected/select.out
+++ b/contrib/pg_stat_statements/expected/select.out
@@ -99,6 +99,22 @@ SELECT 2 AS "int" ORDER BY 1;
    2
 (1 row)
 
+SELECT FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
+--
+(1 row)
+
+SELECT a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
+ a 
+---
+ 1
+(1 row)
+
+SELECT a, b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
+ a | b 
+---+---
+ 1 | 2
+(1 row)
+
 /* this comment should not appear in the output */
 SELECT 'hello'
   -- but this one will appear
@@ -223,6 +239,9 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
      1 |    2 | SELECT $1 AS i UNION SELECT $2 ORDER BY i
      1 |    1 | SELECT $1 || $2
      2 |    2 | SELECT DISTINCT $1 AS "int"
+     1 |    1 | SELECT FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) ORDER BY a, b
+     1 |    1 | SELECT a FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) ORDER BY a, b
+     1 |    1 | SELECT a, b FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) ORDER BY a, b
      0 |    0 | SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"
      1 |    1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t
      1 |    2 | WITH t(f) AS (                                                              +
@@ -230,7 +249,7 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
        |      | )                                                                           +
        |      |   SELECT f FROM t ORDER BY f
      1 |    1 | select $1::jsonb ? $2
-(17 rows)
+(20 rows)
 
 SELECT pg_stat_statements_reset() IS NOT NULL AS t;
  t 
@@ -459,6 +478,95 @@ SELECT COUNT(*) FROM pg_stat_statements WHERE query LIKE '%FETCH FIRST%';
      2
 (1 row)
 
+-- GROUP BY, HAVING, GROUPING
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a;
+ count 
+-------
+     1
+(1 row)
+
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b;
+ count 
+-------
+     1
+(1 row)
+
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY GROUPING SETS(a, ());
+ count 
+-------
+     1
+     1
+(2 rows)
+
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY GROUPING SETS(b, ());
+ count 
+-------
+     1
+     1
+(2 rows)
+
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a HAVING a = 1;
+ count 
+-------
+     1
+(1 row)
+
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b HAVING b = 1;
+ count 
+-------
+(0 rows)
+
+SELECT COUNT(*), a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a HAVING a = 1;
+ count | a 
+-------+---
+     1 | 1
+(1 row)
+
+SELECT COUNT(*), b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b HAVING b = 1;
+ count | b 
+-------+---
+(0 rows)
+
+SELECT COUNT(*), a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a HAVING a = 1 ORDER BY a;
+ count | a 
+-------+---
+     1 | 1
+(1 row)
+
+SELECT COUNT(*), b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b HAVING b = 1 ORDER BY b;
+ count | b 
+-------+---
+(0 rows)
+
+SELECT GROUPING(a) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a;
+ grouping 
+----------
+        0
+(1 row)
+
+SELECT GROUPING(b) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b;
+ grouping 
+----------
+        0
+(1 row)
+
+SELECT calls, query FROM pg_stat_statements WHERE query LIKE '%GROUP BY%' ORDER BY query COLLATE "C";
+ calls |                                               query                                                
+-------+----------------------------------------------------------------------------------------------------
+     1 | SELECT COUNT(*) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY GROUPING SETS(a, ())
+     1 | SELECT COUNT(*) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY GROUPING SETS(b, ())
+     1 | SELECT COUNT(*) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY a
+     1 | SELECT COUNT(*) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY a HAVING a = $3
+     1 | SELECT COUNT(*) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY b
+     1 | SELECT COUNT(*) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY b HAVING b = $3
+     1 | SELECT COUNT(*), a FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY a HAVING a = $3
+     1 | SELECT COUNT(*), a FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY a HAVING a = $3 ORDER BY a
+     1 | SELECT COUNT(*), b FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY b HAVING b = $3
+     1 | SELECT COUNT(*), b FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY b HAVING b = $3 ORDER BY b
+     1 | SELECT GROUPING(a) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY a
+     1 | SELECT GROUPING(b) FROM (VALUES ($1::INT, $2::INT)) AS t(a, b) GROUP BY b
+(12 rows)
+
 -- GROUP BY [DISTINCT]
 SELECT a, b, c
 FROM (VALUES (1, 2, 3), (4, NULL, 6), (7, 8, 9)) AS t (a, b, c)
@@ -548,7 +656,7 @@ SELECT (
 SELECT COUNT(*) FROM pg_stat_statements WHERE query LIKE '%SELECT GROUPING%';
  count 
 -------
-     2
+     4
 (1 row)
 
 SELECT pg_stat_statements_reset() IS NOT NULL AS t;
diff --git a/contrib/pg_stat_statements/sql/select.sql b/contrib/pg_stat_statements/sql/select.sql
index 11662cde08c..33e0e63cd1e 100644
--- a/contrib/pg_stat_statements/sql/select.sql
+++ b/contrib/pg_stat_statements/sql/select.sql
@@ -31,6 +31,9 @@ SELECT DISTINCT 1 AS "int";
 SELECT DISTINCT 2 AS "int";
 SELECT 1 AS "int" ORDER BY 1;
 SELECT 2 AS "int" ORDER BY 1;
+SELECT FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
+SELECT a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
+SELECT a, b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) ORDER BY a, b;
 
 /* this comment should not appear in the output */
 SELECT 'hello'
@@ -158,6 +161,21 @@ FETCH FIRST 2 ROW ONLY;
 
 SELECT COUNT(*) FROM pg_stat_statements WHERE query LIKE '%FETCH FIRST%';
 
+-- GROUP BY, HAVING, GROUPING
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a;
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b;
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY GROUPING SETS(a, ());
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY GROUPING SETS(b, ());
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a HAVING a = 1;
+SELECT COUNT(*) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b HAVING b = 1;
+SELECT COUNT(*), a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a HAVING a = 1;
+SELECT COUNT(*), b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b HAVING b = 1;
+SELECT COUNT(*), a FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a HAVING a = 1 ORDER BY a;
+SELECT COUNT(*), b FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b HAVING b = 1 ORDER BY b;
+SELECT GROUPING(a) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY a;
+SELECT GROUPING(b) FROM (VALUES (1::INT, 2::INT)) AS t(a, b) GROUP BY b;
+SELECT calls, query FROM pg_stat_statements WHERE query LIKE '%GROUP BY%' ORDER BY query COLLATE "C";
+
 -- GROUP BY [DISTINCT]
 SELECT a, b, c
 FROM (VALUES (1, 2, 3), (4, NULL, 6), (7, 8, 9)) AS t (a, b, c)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index aac4bfc70d9..646d6ced763 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1294,7 +1294,7 @@ typedef struct RangeTblEntry
 	 * Fields valid for a GROUP RTE (else NIL):
 	 */
 	/* list of grouping expressions */
-	List	   *groupexprs pg_node_attr(query_jumble_ignore);
+	List	   *groupexprs;
 
 	/*
 	 * Fields valid in all RTEs:
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 5211cadc258..174ebe92939 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -2248,7 +2248,7 @@ typedef struct TargetEntry
 	/* column's number in source table */
 	AttrNumber	resorigcol pg_node_attr(query_jumble_ignore);
 	/* set to true to eliminate the attribute from final target list */
-	bool		resjunk pg_node_attr(query_jumble_ignore);
+	bool		resjunk;
 } TargetEntry;
 
 
-- 
2.34.1

Reply via email to