aboutsummaryrefslogtreecommitdiff
path: root/src/include/nodes/execnodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/nodes/execnodes.h')
-rw-r--r--src/include/nodes/execnodes.h83
1 files changed, 67 insertions, 16 deletions
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f42189d2bf6..b593d22c48a 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -571,17 +571,12 @@ typedef struct EState
ExprContext *es_per_tuple_exprcontext;
/*
- * These fields are for re-evaluating plan quals when an updated tuple is
- * substituted in READ COMMITTED mode. es_epqTupleSlot[] contains test
- * tuples that scan plan nodes should return instead of whatever they'd
- * normally return, or an empty slot if there is nothing to return; if
- * es_epqTupleSlot[] is not NULL if a particular array entry is valid; and
- * es_epqScanDone[] is state to remember if the tuple has been returned
- * already. Arrays are of size es_range_table_size and are indexed by
- * scan node scanrelid - 1.
+ * If not NULL, this is an EPQState's EState. This is a field in EState
+ * both to allow EvalPlanQual aware executor nodes to detect that they
+ * need to perform EPQ related work, and to provide necessary information
+ * to do so.
*/
- TupleTableSlot **es_epqTupleSlot; /* array of EPQ substitute tuples */
- bool *es_epqScanDone; /* true if EPQ tuple has been fetched */
+ struct EPQState *es_epq_active;
bool es_use_parallel_mode; /* can we use parallel workers? */
@@ -1057,17 +1052,73 @@ typedef struct PlanState
/*
* EPQState is state for executing an EvalPlanQual recheck on a candidate
- * tuple in ModifyTable or LockRows. The estate and planstate fields are
- * NULL if inactive.
+ * tuples e.g. in ModifyTable or LockRows.
+ *
+ * To execute EPQ a separate EState is created (stored in ->recheckestate),
+ * which shares some resources, like the rangetable, with the main query's
+ * EState (stored in ->parentestate). The (sub-)tree of the plan that needs to
+ * be rechecked (in ->plan), is separately initialized (into
+ * ->recheckplanstate), but shares plan nodes with the corresponding nodes in
+ * the main query. The scan nodes in that separate executor tree are changed
+ * to return only the current tuple of interest for the respective
+ * table. Those tuples are either provided by the caller (using
+ * EvalPlanQualSlot), and/or found using the rowmark mechanism (non-locking
+ * rowmarks by the EPQ machinery itself, locking ones by the caller).
+ *
+ * While the plan to be checked may be changed using EvalPlanQualSetPlan() -
+ * e.g. so all source plans for a ModifyTable node can be processed - all such
+ * plans need to share the same EState.
*/
typedef struct EPQState
{
- EState *estate; /* subsidiary EState */
- PlanState *planstate; /* plan state tree ready to be executed */
- TupleTableSlot *origslot; /* original output tuple to be rechecked */
+ /* Initialized at EvalPlanQualInit() time: */
+
+ EState *parentestate; /* main query's EState */
+ int epqParam; /* ID of Param to force scan node re-eval */
+
+ /*
+ * Tuples to be substituted by scan nodes. They need to set up, before
+ * calling EvalPlanQual()/EvalPlanQualNext(), into the slot returned by
+ * EvalPlanQualSlot(scanrelid). The array is indexed by scanrelid - 1.
+ */
+ List *tuple_table; /* tuple table for relsubs_slot */
+ TupleTableSlot **relsubs_slot;
+
+ /*
+ * Initialized by EvalPlanQualInit(), may be changed later with
+ * EvalPlanQualSetPlan():
+ */
+
Plan *plan; /* plan tree to be executed */
List *arowMarks; /* ExecAuxRowMarks (non-locking only) */
- int epqParam; /* ID of Param to force scan node re-eval */
+
+
+ /*
+ * The original output tuple to be rechecked. Set by
+ * EvalPlanQualSetSlot(), before EvalPlanQualNext() or EvalPlanQual() may
+ * be called.
+ */
+ TupleTableSlot *origslot;
+
+
+ /* Initialized or reset by EvalPlanQualBegin(): */
+
+ EState *recheckestate; /* EState for EPQ execution, see above */
+
+ /*
+ * Rowmarks that can be fetched on-demand using
+ * EvalPlanQualFetchRowMark(), indexed by scanrelid - 1. Only non-locking
+ * rowmarks.
+ */
+ ExecAuxRowMark **relsubs_rowmark;
+
+ /*
+ * True if a relation's EPQ tuple has been fetched for relation, indexed
+ * by scanrelid - 1.
+ */
+ bool *relsubs_done;
+
+ PlanState *recheckplanstate; /* EPQ specific exec nodes, for ->plan */
} EPQState;