summaryrefslogtreecommitdiff
path: root/src/include/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/nodes')
-rw-r--r--src/include/nodes/execnodes.h58
-rw-r--r--src/include/nodes/nodes.h5
-rw-r--r--src/include/nodes/parsenodes.h21
-rw-r--r--src/include/nodes/plannodes.h68
-rw-r--r--src/include/nodes/relation.h10
5 files changed, 122 insertions, 40 deletions
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 93d4aa00db..bba9c0370b 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.210 2009/10/12 18:10:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.211 2009/10/26 02:26:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -331,6 +331,7 @@ typedef struct EState
Snapshot es_snapshot; /* time qual to use */
Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
List *es_range_table; /* List of RangeTblEntry */
+ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
JunkFilter *es_junkFilter; /* top-level junk filter, if any */
@@ -375,31 +376,45 @@ typedef struct EState
*/
ExprContext *es_per_tuple_exprcontext;
- /* Below is to re-evaluate plan qual in READ COMMITTED mode */
- PlannedStmt *es_plannedstmt; /* link to top of plan tree */
- struct evalPlanQual *es_evalPlanQual; /* chain of PlanQual states */
- bool *es_evTupleNull; /* local array of EPQ status */
- HeapTuple *es_evTuple; /* shared array of EPQ substitute tuples */
+ /*
+ * These fields are for re-evaluating plan quals when an updated tuple is
+ * substituted in READ COMMITTED mode. es_epqTuple[] contains tuples
+ * that scan plan nodes should return instead of whatever they'd normally
+ * return, or NULL if nothing to return; es_epqTupleSet[] is true 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
+ * list_length(es_range_table) and are indexed by scan node scanrelid - 1.
+ */
+ HeapTuple *es_epqTuple; /* array of EPQ substitute tuples */
+ bool *es_epqTupleSet; /* true if EPQ tuple is provided */
+ bool *es_epqScanDone; /* true if EPQ tuple has been fetched */
} EState;
/*
+ * ExecRowMark -
+ * runtime representation of FOR UPDATE/SHARE clauses
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we should have an
+ * ExecRowMark for each non-target relation in the query (except inheritance
+ * parent RTEs, which can be ignored at runtime). See PlanRowMark for details
+ * about most of the fields.
+ *
* es_rowMarks is a list of these structs. Each LockRows node has its own
* list, which is the subset of locks that it is supposed to enforce; note
* that the per-node lists point to the same structs that are in the global
- * list. See RowMarkClause for details about rti, prti, and rowmarkId.
- * toidAttno is not used in a "plain" (non-inherited) rowmark.
+ * list.
*/
typedef struct ExecRowMark
{
- Relation relation; /* opened and RowShareLock'd relation */
+ Relation relation; /* opened and suitably locked relation */
Index rti; /* its range table index */
Index prti; /* parent range table index, if child */
- Index rowmarkId; /* unique identifier assigned by planner */
- bool forUpdate; /* true = FOR UPDATE, false = FOR SHARE */
+ RowMarkType markType; /* see enum in nodes/plannodes.h */
bool noWait; /* NOWAIT option */
- AttrNumber ctidAttNo; /* resno of its ctid junk attribute */
+ AttrNumber ctidAttNo; /* resno of ctid junk attribute, if any */
AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
+ AttrNumber wholeAttNo; /* resno of whole-row junk attribute, if any */
ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
} ExecRowMark;
@@ -967,6 +982,21 @@ typedef struct PlanState
#define innerPlanState(node) (((PlanState *)(node))->righttree)
#define outerPlanState(node) (((PlanState *)(node))->lefttree)
+/*
+ * 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.
+ */
+typedef struct EPQState
+{
+ EState *estate; /* subsidiary EState */
+ PlanState *planstate; /* plan state tree ready to be executed */
+ TupleTableSlot *origslot; /* original output tuple to be rechecked */
+ Plan *plan; /* plan tree to be executed */
+ List *rowMarks; /* ExecRowMarks (non-locking only) */
+ int epqParam; /* ID of Param to force scan node re-eval */
+} EPQState;
+
/* ----------------
* ResultState information
@@ -991,6 +1021,7 @@ typedef struct ModifyTableState
PlanState **mt_plans; /* subplans (one per target rel) */
int mt_nplans; /* number of plans in the array */
int mt_whichplan; /* which one is being executed (0..n-1) */
+ EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
bool fireBSTriggers; /* do we need to fire stmt triggers? */
} ModifyTableState;
@@ -1651,8 +1682,7 @@ typedef struct LockRowsState
{
PlanState ps; /* its first field is NodeTag */
List *lr_rowMarks; /* List of ExecRowMarks */
- JunkFilter *lr_junkFilter; /* needed for getting ctid columns */
- bool lr_useEvalPlan; /* evaluating EPQ tuples? */
+ EPQState lr_epqstate; /* for evaluating EvalPlanQual rechecks */
} LockRowsState;
/* ----------------
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index c452d53505..f26f5d8d11 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.230 2009/10/12 18:10:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.231 2009/10/26 02:26:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -73,7 +73,8 @@ typedef enum NodeTag
T_SetOp,
T_LockRows,
T_Limit,
- /* this one isn't a subclass of Plan: */
+ /* these aren't subclasses of Plan: */
+ T_PlanRowMark,
T_PlanInvalItem,
/*
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index adc870543b..450a89fe85 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.410 2009/10/14 22:14:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.411 2009/10/26 02:26:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -800,28 +800,17 @@ typedef struct WindowClause
/*
* RowMarkClause -
- * representation of FOR UPDATE/SHARE clauses
- *
- * We create a separate RowMarkClause node for each target relation. In the
- * output of the parser and rewriter, all RowMarkClauses have rti == prti and
- * isParent == false. When the planner discovers that a target relation
- * is the root of an inheritance tree, it sets isParent true, and adds an
- * additional RowMarkClause to the list for each child relation (including
- * the target rel itself in its role as a child). The child entries have
- * rti == child rel's RT index, prti == parent's RT index, and can therefore
- * be recognized as children by the fact that prti != rti.
- * rowmarkId is a unique ID for the RowMarkClause across an entire query,
- * and is assigned during planning; it's always zero upstream of the planner.
+ * parser output representation of FOR UPDATE/SHARE clauses
+ *
+ * Query.rowMarks contains a separate RowMarkClause node for each relation
+ * identified as a FOR UPDATE/SHARE target.
*/
typedef struct RowMarkClause
{
NodeTag type;
Index rti; /* range table index of target relation */
- Index prti; /* range table index of parent relation */
- Index rowmarkId; /* unique identifier assigned by planner */
bool forUpdate; /* true = FOR UPDATE, false = FOR SHARE */
bool noWait; /* NOWAIT option */
- bool isParent; /* set by planner when expanding inheritance */
} RowMarkClause;
/*
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 10177f3d7f..e9c994e4f2 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.112 2009/10/12 18:10:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.113 2009/10/26 02:26:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,7 +59,7 @@ typedef struct PlannedStmt
Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */
- List *rowMarks; /* a list of RowMarkClause's */
+ List *rowMarks; /* a list of PlanRowMark's */
List *relationOids; /* OIDs of relations the plan depends on */
@@ -167,6 +167,8 @@ typedef struct ModifyTable
List *resultRelations; /* integer list of RT indexes */
List *plans; /* plan(s) producing source data */
List *returningLists; /* per-target-table RETURNING tlists */
+ List *rowMarks; /* PlanRowMarks (non-locking only) */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
} ModifyTable;
/* ----------------
@@ -620,12 +622,15 @@ typedef struct SetOp
*
* rowMarks identifies the rels to be locked by this node; it should be
* a subset of the rowMarks listed in the top-level PlannedStmt.
+ * epqParam is a Param that all scan nodes below this one must depend on.
+ * It is used to force re-evaluation of the plan during EvalPlanQual.
* ----------------
*/
typedef struct LockRows
{
Plan plan;
- List *rowMarks; /* a list of RowMarkClause's */
+ List *rowMarks; /* a list of PlanRowMark's */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
} LockRows;
/* ----------------
@@ -644,6 +649,63 @@ typedef struct Limit
/*
+ * RowMarkType -
+ * enums for types of row-marking operations
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we have to uniquely
+ * identify all the source rows, not only those from the target relations, so
+ * that we can perform EvalPlanQual rechecking at need. For plain tables we
+ * can just fetch the TID, the same as for a target relation. Otherwise (for
+ * example for VALUES or FUNCTION scans) we have to copy the whole row value.
+ * The latter is pretty inefficient but fortunately the case is not
+ * performance-critical in practice.
+ */
+typedef enum RowMarkType
+{
+ ROW_MARK_EXCLUSIVE, /* obtain exclusive tuple lock */
+ ROW_MARK_SHARE, /* obtain shared tuple lock */
+ ROW_MARK_REFERENCE, /* just fetch the TID */
+ ROW_MARK_COPY /* physically copy the row value */
+} RowMarkType;
+
+#define RowMarkRequiresRowShareLock(marktype) ((marktype) <= ROW_MARK_SHARE)
+
+/*
+ * PlanRowMark -
+ * plan-time representation of FOR UPDATE/SHARE clauses
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we create a separate
+ * PlanRowMark node for each non-target relation in the query. Relations that
+ * are not specified as FOR UPDATE/SHARE are marked ROW_MARK_REFERENCE (if
+ * real tables) or ROW_MARK_COPY (if not).
+ *
+ * Initially all PlanRowMarks have rti == prti and isParent == false.
+ * When the planner discovers that a relation is the root of an inheritance
+ * tree, it sets isParent true, and adds an additional PlanRowMark to the
+ * list for each child relation (including the target rel itself in its role
+ * as a child). The child entries have rti == child rel's RT index and
+ * prti == parent's RT index, and can therefore be recognized as children by
+ * the fact that prti != rti.
+ *
+ * The AttrNumbers are filled in during preprocess_targetlist. We use
+ * different subsets of them for plain relations, inheritance children,
+ * and non-table relations.
+ */
+typedef struct PlanRowMark
+{
+ NodeTag type;
+ Index rti; /* range table index of markable relation */
+ Index prti; /* range table index of parent relation */
+ RowMarkType markType; /* see enum above */
+ bool noWait; /* NOWAIT option */
+ bool isParent; /* true if this is a "dummy" parent entry */
+ AttrNumber ctidAttNo; /* resno of ctid junk attribute, if any */
+ AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
+ AttrNumber wholeAttNo; /* resno of whole-row junk attribute, if any */
+} PlanRowMark;
+
+
+/*
* Plan invalidation info
*
* We track the objects on which a PlannedStmt depends in two ways:
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 8edb58727c..59f83e8562 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.177 2009/10/12 18:10:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.178 2009/10/26 02:26:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -68,13 +68,13 @@ typedef struct PlannerGlobal
List *subrtables; /* Rangetables for SubPlan nodes */
- List *subrowmarks; /* RowMarkClauses for SubPlan nodes */
+ List *subrowmarks; /* PlanRowMarks for SubPlan nodes */
Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */
List *finalrtable; /* "flat" rangetable for executor */
- List *finalrowmarks; /* "flat" list of RowMarkClauses */
+ List *finalrowmarks; /* "flat" list of PlanRowMarks */
List *relationOids; /* OIDs of relations the plan depends on */
@@ -82,8 +82,6 @@ typedef struct PlannerGlobal
Index lastPHId; /* highest PlaceHolderVar ID assigned */
- Index lastRowmarkId; /* highest RowMarkClause ID assigned */
-
bool transientPlan; /* redo plan when TransactionXmin changes? */
} PlannerGlobal;
@@ -169,6 +167,8 @@ typedef struct PlannerInfo
List *append_rel_list; /* list of AppendRelInfos */
+ List *rowMarks; /* list of PlanRowMarks */
+
List *placeholder_list; /* list of PlaceHolderInfos */
List *query_pathkeys; /* desired pathkeys for query_planner(), and