This is an automated email from the ASF dual-hosted git repository.

reshke pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 34f970ab1206bbea71db1a5a178667655c76941a
Author: Tom Lane <[email protected]>
AuthorDate: Wed Aug 3 17:33:42 2022 -0400

    Fix incorrect tests for SRFs in relation_can_be_sorted_early().
    
    Commit fac1b470a thought we could check for set-returning functions
    by testing only the top-level node in an expression tree.  This is
    wrong in itself, and to make matters worse it encouraged others
    to make the same mistake, by exporting tlist.c's special-purpose
    IS_SRF_CALL() as a widely-visible macro.  I can't find any evidence
    that anyone's taken the bait, but it was only a matter of time.
    
    Use expression_returns_set() instead, and stuff the IS_SRF_CALL()
    genie back in its bottle, this time with a warning label.  I also
    added a couple of cross-reference comments.
    
    After a fair amount of fooling around, I've despaired of making
    a robust test case that exposes the bug reliably, so no test case
    here.  (Note that the test case added by fac1b470a is itself
    broken, in that it doesn't notice if you remove the code change.
    The repro given by the bug submitter currently doesn't fail either
    in v15 or HEAD, though I suspect that may indicate an unrelated bug.)
    
    Per bug #17564 from Martijn van Oosterhout.  Back-patch to v13,
    as the faulty patch was.
    
    Discussion: https://postgr.es/m/[email protected]
---
 src/backend/nodes/nodeFuncs.c           |  6 ++++++
 src/backend/optimizer/path/equivclass.c |  4 ++--
 src/backend/optimizer/util/tlist.c      | 11 +++++++++++
 src/include/optimizer/optimizer.h       |  5 -----
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 8e2b9230cb3..6c45d349524 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -754,6 +754,12 @@ expression_returns_set_walker(Node *node, void *context)
                /* else fall through to check args */
        }
 
+       /*
+        * If you add any more cases that return sets, also fix
+        * expression_returns_set_rows() in clauses.c and IS_SRF_CALL() in
+        * tlist.c.
+        */
+
        /* Avoid recursion for some cases that parser checks not to return a 
set */
        if (IsA(node, Aggref))
                return false;
diff --git a/src/backend/optimizer/path/equivclass.c 
b/src/backend/optimizer/path/equivclass.c
index 547b2550917..6a941c662c7 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1005,7 +1005,7 @@ relation_can_be_sorted_early(PlannerInfo *root, 
RelOptInfo *rel,
                 * one are effectively checking properties of targetexpr, so 
there's
                 * no point in asking whether some other EC member would be 
better.)
                 */
-               if (IS_SRF_CALL((Node *) em->em_expr))
+               if (expression_returns_set((Node *) em->em_expr))
                        continue;
 
                /*
@@ -1033,7 +1033,7 @@ relation_can_be_sorted_early(PlannerInfo *root, 
RelOptInfo *rel,
         * member in this case; since SRFs can't appear in WHERE, they cannot
         * belong to multi-member ECs.)
         */
-       if (IS_SRF_CALL((Node *) em->em_expr))
+       if (expression_returns_set((Node *) em->em_expr))
                return false;
 
        return true;
diff --git a/src/backend/optimizer/util/tlist.c 
b/src/backend/optimizer/util/tlist.c
index 9d0f3274dbe..bb16a8d2c38 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -32,6 +32,17 @@ typedef struct maxSortGroupRef_context
 static
 bool maxSortGroupRef_walker(Node *node, maxSortGroupRef_context *cxt);
 
+/*
+ * Test if an expression node represents a SRF call.  Beware multiple eval!
+ *
+ * Please note that this is only meant for use in split_pathtarget_at_srfs();
+ * if you use it anywhere else, your code is almost certainly wrong for SRFs
+ * nested within expressions.  Use expression_returns_set() instead.
+ */
+#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 f8400206288..c2553891186 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -25,11 +25,6 @@
 #include "nodes/parsenodes.h"
 #include "nodes/plannodes.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.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to