dont_remove_srf_windowfuncs.patch

text/plain

Filename: dont_remove_srf_windowfuncs.patch
Type: text/plain
Part: 0
Message: Re: BUG #17502: View based on window functions returns wrong results when queried

Patch

Format: unified
File+
src/backend/optimizer/path/allpaths.c 52 3
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 7ac116a791..5dab40f6ff 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -3933,6 +3933,44 @@ recurse_push_qual(Node *setOp, Query *topquery,
  *			SIMPLIFYING SUBQUERY TARGETLISTS
  *****************************************************************************/
 
+/*
+ * has_set_returning_window_clauses
+ *		Returns true if 'node' contains any WindowFuncs which reference a
+ *		WindowClause where the PARTITION BY or ORDER BY clause contains any
+ *		set returning functions.
+ */
+static bool
+has_set_returning_window_clauses(Query *subquery, Node *node)
+{
+	WindowFuncLists *wflists;
+
+	wflists = find_window_functions(node,
+									list_length(subquery->windowClause));
+
+	if (wflists->numWindowFuncs == 0)
+		return false;
+
+	for (int i = 1; i <= wflists->maxWinRef; i++)
+	{
+		WindowClause *wclause;
+
+		if (wflists->windowFuncs[i] == NIL)
+			continue;
+
+		wclause = (WindowClause *) list_nth(subquery->windowClause, i - 1);
+
+		if (expression_returns_set((Node *) get_sortgrouplist_exprs(wclause->partitionClause,
+																	subquery->targetList)))
+			return true;
+
+		if (expression_returns_set((Node *) get_sortgrouplist_exprs(wclause->orderClause,
+																   subquery->targetList)))
+			return true;
+	}
+
+	return false;
+}
+
 /*
  * remove_unused_subquery_outputs
  *		Remove subquery targetlist items we don't need
@@ -4028,9 +4066,20 @@ remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel)
 		 * If it contains a set-returning function, we can't remove it since
 		 * that could change the number of rows returned by the subquery.
 		 */
-		if (subquery->hasTargetSRFs &&
-			expression_returns_set(texpr))
-			continue;
+		if (subquery->hasTargetSRFs)
+		{
+			if (expression_returns_set(texpr))
+				continue;
+
+			/*
+			 * Check if the target entry contains any WindowFunc references
+			 * which have a WindowClause where the PARTITION BY or ORDER BY
+			 * clause contain any SRFs
+			 */
+			if (subquery->hasWindowFuncs &&
+				has_set_returning_window_clauses(subquery, (Node *) texpr))
+				continue;
+		}
 
 		/*
 		 * If it contains volatile functions, we daren't remove it for fear