From 46361b13a73d13d95149560c97eca29dcc1c2786 Mon Sep 17 00:00:00 2001
From: "Sami Imseih (AWS)"
 <simseih@dev-dsk-simseih-1d-3940b79e.us-east-1.amazon.com>
Date: Mon, 10 Mar 2025 17:06:02 +0000
Subject: [PATCH v1 1/1] Fix QueryId collision for LIMIT and OFFSET

This patch fixes the inability of Query jumble to
differentiate between LIMIT and OFFSET due to both
of these clauses being a int8 expr and being jumbled
one after the other.

By changing the order of the limitCount and limitOffset
and placing LimitOptions between them, this naturally
changes the ordering of the jumble append and a different
queryId.

Added additional test cases in pg_stat_statements.

Author: Bykov Ivan
---
 .../pg_stat_statements/expected/select.out    | 25 ++++++++++++++++++-
 contrib/pg_stat_statements/sql/select.sql     | 13 ++++++++++
 src/include/nodes/parsenodes.h                |  7 +++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/contrib/pg_stat_statements/expected/select.out b/contrib/pg_stat_statements/expected/select.out
index 37a30af034a..8742e8200f3 100644
--- a/contrib/pg_stat_statements/expected/select.out
+++ b/contrib/pg_stat_statements/expected/select.out
@@ -309,10 +309,33 @@ FETCH FIRST 2 ROW ONLY;
    0
 (2 rows)
 
+SELECT *
+FROM limitoption
+WHERE val < 2
+ORDER BY val
+LIMIT 2;
+ val 
+-----
+   0
+   0
+(2 rows)
+
+SELECT *
+FROM limitoption
+WHERE val < 2
+ORDER BY val
+OFFSET 2
+FETCH FIRST 2 ROW ONLY;
+ val 
+-----
+   0
+   0
+(2 rows)
+
 SELECT COUNT(*) FROM pg_stat_statements WHERE query LIKE '%FETCH FIRST%';
  count 
 -------
-     2
+     3
 (1 row)
 
 -- GROUP BY [DISTINCT]
diff --git a/contrib/pg_stat_statements/sql/select.sql b/contrib/pg_stat_statements/sql/select.sql
index e0be58d5e24..88943bd151c 100644
--- a/contrib/pg_stat_statements/sql/select.sql
+++ b/contrib/pg_stat_statements/sql/select.sql
@@ -120,6 +120,19 @@ WHERE val < 2
 ORDER BY val
 FETCH FIRST 2 ROW ONLY;
 
+SELECT *
+FROM limitoption
+WHERE val < 2
+ORDER BY val
+LIMIT 2;
+
+SELECT *
+FROM limitoption
+WHERE val < 2
+ORDER BY val
+OFFSET 2
+FETCH FIRST 2 ROW ONLY;
+
 SELECT COUNT(*) FROM pg_stat_statements WHERE query LIKE '%FETCH FIRST%';
 
 -- GROUP BY [DISTINCT]
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 23c9e3c5abf..d2f4f36e4c9 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -221,9 +221,14 @@ typedef struct Query
 
 	List	   *sortClause;		/* a list of SortGroupClause's */
 
+	/*
+	 * It is necessary to define limitOption between limitOffset
+	 * and limitCount to be able to differentiate between OFFSET
+	 * and LIMIT for query jumbling purposes.
+	 */
 	Node	   *limitOffset;	/* # of result tuples to skip (int8 expr) */
-	Node	   *limitCount;		/* # of result tuples to return (int8 expr) */
 	LimitOption limitOption;	/* limit type */
+	Node	   *limitCount;		/* # of result tuples to return (int8 expr) */
 
 	List	   *rowMarks;		/* a list of RowMarkClause's */
 
-- 
2.47.1

