aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/nodes/nodeFuncs.c6
-rw-r--r--src/backend/optimizer/path/equivclass.c4
-rw-r--r--src/backend/optimizer/util/tlist.c11
-rw-r--r--src/include/optimizer/optimizer.h5
4 files changed, 19 insertions, 7 deletions
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index cbf15aa48d6..585b0046f4f 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -742,6 +742,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 7da261c0312..159bb7e6531 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1002,7 +1002,7 @@ find_em_expr_usable_for_sorting_rel(PlannerInfo *root, EquivalenceClass *ec,
* 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;
/*
@@ -1030,7 +1030,7 @@ find_em_expr_usable_for_sorting_rel(PlannerInfo *root, EquivalenceClass *ec,
* 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 NULL;
return em->em_expr;
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 01cea102eab..2c58bd0d6fb 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -22,6 +22,17 @@
/*
+ * 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
* not just bare expressions but expressions plus their sortgroupref indexes.
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 3c588def885..4729cd01c89 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -24,11 +24,6 @@
#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.