v2-0003-Disallow-SRFs-in-proactive-sort.patch

text/x-patch

Filename: v2-0003-Disallow-SRFs-in-proactive-sort.patch
Type: text/x-patch
Part: 1
Message: Re: Fix generate_useful_gather_paths for parallel unsafe pathkeys

Patch

Format: format-patch
Series: patch v2-0003
Subject: Disallow SRFs in proactive sort
File+
src/backend/optimizer/path/equivclass.c 8 0
src/backend/optimizer/util/tlist.c 0 5
src/include/optimizer/optimizer.h 5 0
src/test/regress/expected/incremental_sort.out 12 0
src/test/regress/sql/incremental_sort.sql 2 0
From 1dd54123ec95cfc2df66ccf1189bff1df70d15e7 Mon Sep 17 00:00:00 2001
From: jcoleman <jtc331@gmail.com>
Date: Wed, 25 Nov 2020 15:46:00 -0500
Subject: [PATCH v2 3/5] Disallow SRFs in proactive sort

So they can be evaluated at the proper time as determiend by
make_sort_input_target.
---
 src/backend/optimizer/path/equivclass.c        |  8 ++++++++
 src/backend/optimizer/util/tlist.c             |  5 -----
 src/include/optimizer/optimizer.h              |  5 +++++
 src/test/regress/expected/incremental_sort.out | 12 ++++++++++++
 src/test/regress/sql/incremental_sort.sql      |  2 ++
 5 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index e47a16827d..ac2ed7aff1 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -838,6 +838,14 @@ find_em_expr_usable_for_sorting_rel(PlannerInfo *root, EquivalenceClass *ec, Rel
 
 		if (parallel && !is_parallel_safe(root, (Node *) em_expr))
 			continue;
+
+		/*
+		 * Disallow SRFs so that all of them can be evaluated at the correct
+		 * time as determined by make_sort_input_target.
+		 */
+		if (IS_SRF_CALL((Node *) em_expr))
+			continue;
+
 		/*
 		 * As long as the expression isn't volatile then
 		 * prepare_sort_from_pathkeys is able to generate a new target entry,
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 02a3c6b165..01cea102ea 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -21,11 +21,6 @@
 #include "optimizer/tlist.h"
 
 
-/* Test if an expression node represents a SRF call.  Beware multiple eval! */
-#define IS_SRF_CALL(node) \
-	((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
-	 (IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
-
 /*
  * Data structures for split_pathtarget_at_srfs().  To preserve the identity
  * of sortgroupref items even if they are textually equal(), what we track is
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 3e4171056e..1e135652b9 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -24,6 +24,11 @@
 
 #include "nodes/parsenodes.h"
 
+/* Test if an expression node represents a SRF call.  Beware multiple eval! */
+#define IS_SRF_CALL(node) \
+	((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
+	 (IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
+
 /*
  * We don't want to include nodes/pathnodes.h here, because non-planner
  * code should generally treat PlannerInfo as an opaque typedef.
diff --git a/src/test/regress/expected/incremental_sort.out b/src/test/regress/expected/incremental_sort.out
index d316a7c4b9..a8cbfd9f5f 100644
--- a/src/test/regress/expected/incremental_sort.out
+++ b/src/test/regress/expected/incremental_sort.out
@@ -1620,3 +1620,15 @@ order by 1, 2;
                ->  Function Scan on generate_series
 (7 rows)
 
+-- Disallow pushing down sort when pathkey is an SRF.
+explain (costs off) select unique1 from tenk1 order by unnest('{1,2}'::int[]);
+                               QUERY PLAN                                
+-------------------------------------------------------------------------
+ Sort
+   Sort Key: (unnest('{1,2}'::integer[]))
+   ->  Gather
+         Workers Planned: 2
+         ->  ProjectSet
+               ->  Parallel Index Only Scan using tenk1_unique1 on tenk1
+(6 rows)
+
diff --git a/src/test/regress/sql/incremental_sort.sql b/src/test/regress/sql/incremental_sort.sql
index ff3af0fd16..62a037b0cf 100644
--- a/src/test/regress/sql/incremental_sort.sql
+++ b/src/test/regress/sql/incremental_sort.sql
@@ -267,3 +267,5 @@ from tenk1, lateral (select tenk1.unique1 from generate_series(1, 1000)) as sub;
 explain (costs off) select sub.unique1, stringu1 || random()::text
 from tenk1, lateral (select tenk1.unique1 from generate_series(1, 1000)) as sub
 order by 1, 2;
+-- Disallow pushing down sort when pathkey is an SRF.
+explain (costs off) select unique1 from tenk1 order by unnest('{1,2}'::int[]);
-- 
2.17.1