summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 4cb1744da6..c334daae39 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -760,6 +760,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 60c0e3f108..7991295548 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -986,7 +986,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;
/*
@@ -1014,7 +1014,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 fe9a9d7d89..784a1af82d 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 7be1e5906b..409005bae9 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.