summaryrefslogtreecommitdiff
path: root/src/backend/executor/execProcnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execProcnode.c')
-rw-r--r--src/backend/executor/execProcnode.c82
1 files changed, 59 insertions, 23 deletions
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 3f2ebff173..b7ac08eead 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -77,6 +77,7 @@
*/
#include "postgres.h"
+#include "executor/execAsync.h"
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
@@ -368,24 +369,14 @@ ExecInitNode(Plan *node, EState *estate, PlanState *parent, int eflags)
/* ----------------------------------------------------------------
- * ExecProcNode
+ * ExecDispatchNode
*
- * Execute the given node to return a(nother) tuple.
+ * Invoke the given node's dispatch function.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecProcNode(PlanState *node)
+void
+ExecDispatchNode(PlanState *node)
{
- TupleTableSlot *result;
-
- CHECK_FOR_INTERRUPTS();
-
- /* mark any previous result as having been consumed */
- node->result_ready = false;
-
- if (node->chgParam != NULL) /* something changed */
- ExecReScan(node); /* let ReScan handle this */
-
if (node->instrument)
InstrStartNode(node->instrument);
@@ -539,22 +530,67 @@ ExecProcNode(PlanState *node)
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
- result = NULL;
break;
}
- /* We don't support asynchronous execution yet. */
- Assert(node->result_ready);
+ if (node->instrument)
+ {
+ double nTuples = 0.0;
- /* Result should be a TupleTableSlot, unless it's NULL. */
- Assert(node->result == NULL || IsA(node->result, TupleTableSlot));
+ if (node->result_ready && node->result != NULL &&
+ IsA(node->result, TupleTableSlot))
+ nTuples = 1.0;
- result = (TupleTableSlot *) node->result;
+ InstrStopNode(node->instrument, nTuples);
+ }
+}
- if (node->instrument)
- InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
- return result;
+/* ----------------------------------------------------------------
+ * ExecExecuteNode
+ *
+ * Request the next tuple from the given node. Note that
+ * if the node supports asynchrony, result_ready may not be
+ * set on return (use ExecProcNode if you need that, or call
+ * ExecAsyncWaitForNode).
+ * ----------------------------------------------------------------
+ */
+void
+ExecExecuteNode(PlanState *node)
+{
+ node->result_ready = false;
+ ExecDispatchNode(node);
+}
+
+
+/* ----------------------------------------------------------------
+ * ExecProcNode
+ *
+ * Get the next tuple from the given node. If the node is
+ * asynchronous, wait for a tuple to be ready before
+ * returning.
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecProcNode(PlanState *node)
+{
+ CHECK_FOR_INTERRUPTS();
+
+ /* mark any previous result as having been consumed */
+ node->result_ready = false;
+
+ if (node->chgParam != NULL) /* something changed */
+ ExecReScan(node); /* let ReScan handle this */
+
+ ExecDispatchNode(node);
+
+ if (!node->result_ready)
+ ExecAsyncWaitForNode(node);
+
+ /* Result should be a TupleTableSlot, unless it's NULL. */
+ Assert(node->result == NULL || IsA(node->result, TupleTableSlot));
+
+ return (TupleTableSlot *) node->result;
}