]> granicus.if.org Git - postgresql/blob - src/include/nodes/plannodes.h
e9c994e4f279a7fedeb4e79cd057a8626eb28332
[postgresql] / src / include / nodes / plannodes.h
1 /*-------------------------------------------------------------------------
2  *
3  * plannodes.h
4  *        definitions for query plan nodes
5  *
6  *
7  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.113 2009/10/26 02:26:42 tgl Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #ifndef PLANNODES_H
15 #define PLANNODES_H
16
17 #include "access/sdir.h"
18 #include "nodes/bitmapset.h"
19 #include "nodes/primnodes.h"
20 #include "storage/itemptr.h"
21
22
23 /* ----------------------------------------------------------------
24  *                                              node definitions
25  * ----------------------------------------------------------------
26  */
27
28 /* ----------------
29  *              PlannedStmt node
30  *
31  * The output of the planner is a Plan tree headed by a PlannedStmt node.
32  * PlannedStmt holds the "one time" information needed by the executor.
33  * ----------------
34  */
35 typedef struct PlannedStmt
36 {
37         NodeTag         type;
38
39         CmdType         commandType;    /* select|insert|update|delete */
40
41         bool            hasReturning;   /* is it insert|update|delete RETURNING? */
42
43         bool            canSetTag;              /* do I set the command result tag? */
44
45         bool            transientPlan;  /* redo plan when TransactionXmin changes? */
46
47         struct Plan *planTree;          /* tree of Plan nodes */
48
49         List       *rtable;                     /* list of RangeTblEntry nodes */
50
51         /* rtable indexes of target relations for INSERT/UPDATE/DELETE */
52         List       *resultRelations;    /* integer list of RT indexes, or NIL */
53
54         Node       *utilityStmt;        /* non-null if this is DECLARE CURSOR */
55
56         IntoClause *intoClause;         /* target for SELECT INTO / CREATE TABLE AS */
57
58         List       *subplans;           /* Plan trees for SubPlan expressions */
59
60         Bitmapset  *rewindPlanIDs;      /* indices of subplans that require REWIND */
61
62         List       *rowMarks;           /* a list of PlanRowMark's */
63
64         List       *relationOids;       /* OIDs of relations the plan depends on */
65
66         List       *invalItems;         /* other dependencies, as PlanInvalItems */
67
68         int                     nParamExec;             /* number of PARAM_EXEC Params used */
69 } PlannedStmt;
70
71 /* macro for fetching the Plan associated with a SubPlan node */
72 #define exec_subplan_get_plan(plannedstmt, subplan) \
73         ((Plan *) list_nth((plannedstmt)->subplans, (subplan)->plan_id - 1))
74
75
76 /* ----------------
77  *              Plan node
78  *
79  * All plan nodes "derive" from the Plan structure by having the
80  * Plan structure as the first field.  This ensures that everything works
81  * when nodes are cast to Plan's.  (node pointers are frequently cast to Plan*
82  * when passed around generically in the executor)
83  *
84  * We never actually instantiate any Plan nodes; this is just the common
85  * abstract superclass for all Plan-type nodes.
86  * ----------------
87  */
88 typedef struct Plan
89 {
90         NodeTag         type;
91
92         /*
93          * estimated execution costs for plan (see costsize.c for more info)
94          */
95         Cost            startup_cost;   /* cost expended before fetching any tuples */
96         Cost            total_cost;             /* total cost (assuming all tuples fetched) */
97
98         /*
99          * planner's estimate of result size of this plan step
100          */
101         double          plan_rows;              /* number of rows plan is expected to emit */
102         int                     plan_width;             /* average row width in bytes */
103
104         /*
105          * Common structural data for all Plan types.
106          */
107         List       *targetlist;         /* target list to be computed at this node */
108         List       *qual;                       /* implicitly-ANDed qual conditions */
109         struct Plan *lefttree;          /* input plan tree(s) */
110         struct Plan *righttree;
111         List       *initPlan;           /* Init Plan nodes (un-correlated expr
112                                                                  * subselects) */
113
114         /*
115          * Information for management of parameter-change-driven rescanning
116          *
117          * extParam includes the paramIDs of all external PARAM_EXEC params
118          * affecting this plan node or its children.  setParam params from the
119          * node's initPlans are not included, but their extParams are.
120          *
121          * allParam includes all the extParam paramIDs, plus the IDs of local
122          * params that affect the node (i.e., the setParams of its initplans).
123          * These are _all_ the PARAM_EXEC params that affect this node.
124          */
125         Bitmapset  *extParam;
126         Bitmapset  *allParam;
127 } Plan;
128
129 /* ----------------
130  *      these are are defined to avoid confusion problems with "left"
131  *      and "right" and "inner" and "outer".  The convention is that
132  *      the "left" plan is the "outer" plan and the "right" plan is
133  *      the inner plan, but these make the code more readable.
134  * ----------------
135  */
136 #define innerPlan(node)                 (((Plan *)(node))->righttree)
137 #define outerPlan(node)                 (((Plan *)(node))->lefttree)
138
139
140 /* ----------------
141  *       Result node -
142  *              If no outer plan, evaluate a variable-free targetlist.
143  *              If outer plan, return tuples from outer plan (after a level of
144  *              projection as shown by targetlist).
145  *
146  * If resconstantqual isn't NULL, it represents a one-time qualification
147  * test (i.e., one that doesn't depend on any variables from the outer plan,
148  * so needs to be evaluated only once).
149  * ----------------
150  */
151 typedef struct Result
152 {
153         Plan            plan;
154         Node       *resconstantqual;
155 } Result;
156
157 /* ----------------
158  *       ModifyTable node -
159  *              Apply rows produced by subplan(s) to result table(s),
160  *              by inserting, updating, or deleting.
161  * ----------------
162  */
163 typedef struct ModifyTable
164 {
165         Plan            plan;
166         CmdType         operation;                      /* INSERT, UPDATE, or DELETE */
167         List       *resultRelations;    /* integer list of RT indexes */
168         List       *plans;                              /* plan(s) producing source data */
169         List       *returningLists;             /* per-target-table RETURNING tlists */
170         List       *rowMarks;                   /* PlanRowMarks (non-locking only) */
171         int                     epqParam;                       /* ID of Param for EvalPlanQual re-eval */
172 } ModifyTable;
173
174 /* ----------------
175  *       Append node -
176  *              Generate the concatenation of the results of sub-plans.
177  * ----------------
178  */
179 typedef struct Append
180 {
181         Plan            plan;
182         List       *appendplans;
183 } Append;
184
185 /* ----------------
186  *      RecursiveUnion node -
187  *              Generate a recursive union of two subplans.
188  *
189  * The "outer" subplan is always the non-recursive term, and the "inner"
190  * subplan is the recursive term.
191  * ----------------
192  */
193 typedef struct RecursiveUnion
194 {
195         Plan            plan;
196         int                     wtParam;                /* ID of Param representing work table */
197         /* Remaining fields are zero/null in UNION ALL case */
198         int                     numCols;                /* number of columns to check for
199                                                                  * duplicate-ness */
200         AttrNumber *dupColIdx;          /* their indexes in the target list */
201         Oid                *dupOperators;       /* equality operators to compare with */
202         long            numGroups;              /* estimated number of groups in input */
203 } RecursiveUnion;
204
205 /* ----------------
206  *       BitmapAnd node -
207  *              Generate the intersection of the results of sub-plans.
208  *
209  * The subplans must be of types that yield tuple bitmaps.      The targetlist
210  * and qual fields of the plan are unused and are always NIL.
211  * ----------------
212  */
213 typedef struct BitmapAnd
214 {
215         Plan            plan;
216         List       *bitmapplans;
217 } BitmapAnd;
218
219 /* ----------------
220  *       BitmapOr node -
221  *              Generate the union of the results of sub-plans.
222  *
223  * The subplans must be of types that yield tuple bitmaps.      The targetlist
224  * and qual fields of the plan are unused and are always NIL.
225  * ----------------
226  */
227 typedef struct BitmapOr
228 {
229         Plan            plan;
230         List       *bitmapplans;
231 } BitmapOr;
232
233 /*
234  * ==========
235  * Scan nodes
236  * ==========
237  */
238 typedef struct Scan
239 {
240         Plan            plan;
241         Index           scanrelid;              /* relid is index into the range table */
242 } Scan;
243
244 /* ----------------
245  *              sequential scan node
246  * ----------------
247  */
248 typedef Scan SeqScan;
249
250 /* ----------------
251  *              index scan node
252  *
253  * indexqualorig is an implicitly-ANDed list of index qual expressions, each
254  * in the same form it appeared in the query WHERE condition.  Each should
255  * be of the form (indexkey OP comparisonval) or (comparisonval OP indexkey).
256  * The indexkey is a Var or expression referencing column(s) of the index's
257  * base table.  The comparisonval might be any expression, but it won't use
258  * any columns of the base table.
259  *
260  * indexqual has the same form, but the expressions have been commuted if
261  * necessary to put the indexkeys on the left, and the indexkeys are replaced
262  * by Var nodes identifying the index columns (varattno is the index column
263  * position, not the base table's column, even though varno is for the base
264  * table).      This is a bit hokey ... would be cleaner to use a special-purpose
265  * node type that could not be mistaken for a regular Var.      But it will do
266  * for now.
267  * ----------------
268  */
269 typedef struct IndexScan
270 {
271         Scan            scan;
272         Oid                     indexid;                /* OID of index to scan */
273         List       *indexqual;          /* list of index quals (OpExprs) */
274         List       *indexqualorig;      /* the same in original form */
275         ScanDirection indexorderdir;    /* forward or backward or don't care */
276 } IndexScan;
277
278 /* ----------------
279  *              bitmap index scan node
280  *
281  * BitmapIndexScan delivers a bitmap of potential tuple locations;
282  * it does not access the heap itself.  The bitmap is used by an
283  * ancestor BitmapHeapScan node, possibly after passing through
284  * intermediate BitmapAnd and/or BitmapOr nodes to combine it with
285  * the results of other BitmapIndexScans.
286  *
287  * The fields have the same meanings as for IndexScan, except we don't
288  * store a direction flag because direction is uninteresting.
289  *
290  * In a BitmapIndexScan plan node, the targetlist and qual fields are
291  * not used and are always NIL.  The indexqualorig field is unused at
292  * run time too, but is saved for the benefit of EXPLAIN.
293  * ----------------
294  */
295 typedef struct BitmapIndexScan
296 {
297         Scan            scan;
298         Oid                     indexid;                /* OID of index to scan */
299         List       *indexqual;          /* list of index quals (OpExprs) */
300         List       *indexqualorig;      /* the same in original form */
301 } BitmapIndexScan;
302
303 /* ----------------
304  *              bitmap sequential scan node
305  *
306  * This needs a copy of the qual conditions being used by the input index
307  * scans because there are various cases where we need to recheck the quals;
308  * for example, when the bitmap is lossy about the specific rows on a page
309  * that meet the index condition.
310  * ----------------
311  */
312 typedef struct BitmapHeapScan
313 {
314         Scan            scan;
315         List       *bitmapqualorig; /* index quals, in standard expr form */
316 } BitmapHeapScan;
317
318 /* ----------------
319  *              tid scan node
320  *
321  * tidquals is an implicitly OR'ed list of qual expressions of the form
322  * "CTID = pseudoconstant" or "CTID = ANY(pseudoconstant_array)".
323  * ----------------
324  */
325 typedef struct TidScan
326 {
327         Scan            scan;
328         List       *tidquals;           /* qual(s) involving CTID = something */
329 } TidScan;
330
331 /* ----------------
332  *              subquery scan node
333  *
334  * SubqueryScan is for scanning the output of a sub-query in the range table.
335  * We often need an extra plan node above the sub-query's plan to perform
336  * expression evaluations (which we can't push into the sub-query without
337  * risking changing its semantics).  Although we are not scanning a physical
338  * relation, we make this a descendant of Scan anyway for code-sharing
339  * purposes.
340  *
341  * Note: we store the sub-plan in the type-specific subplan field, not in
342  * the generic lefttree field as you might expect.      This is because we do
343  * not want plan-tree-traversal routines to recurse into the subplan without
344  * knowing that they are changing Query contexts.
345  *
346  * Note: subrtable is used just to carry the subquery rangetable from
347  * createplan.c to setrefs.c; it should always be NIL by the time the
348  * executor sees the plan.  Similarly for subrowmark.
349  * ----------------
350  */
351 typedef struct SubqueryScan
352 {
353         Scan            scan;
354         Plan       *subplan;
355         List       *subrtable;          /* temporary workspace for planner */
356         List       *subrowmark;         /* temporary workspace for planner */
357 } SubqueryScan;
358
359 /* ----------------
360  *              FunctionScan node
361  * ----------------
362  */
363 typedef struct FunctionScan
364 {
365         Scan            scan;
366         Node       *funcexpr;           /* expression tree for func call */
367         List       *funccolnames;       /* output column names (string Value nodes) */
368         List       *funccoltypes;       /* OID list of column type OIDs */
369         List       *funccoltypmods; /* integer list of column typmods */
370 } FunctionScan;
371
372 /* ----------------
373  *              ValuesScan node
374  * ----------------
375  */
376 typedef struct ValuesScan
377 {
378         Scan            scan;
379         List       *values_lists;       /* list of expression lists */
380 } ValuesScan;
381
382 /* ----------------
383  *              CteScan node
384  * ----------------
385  */
386 typedef struct CteScan
387 {
388         Scan            scan;
389         int                     ctePlanId;              /* ID of init SubPlan for CTE */
390         int                     cteParam;               /* ID of Param representing CTE output */
391 } CteScan;
392
393 /* ----------------
394  *              WorkTableScan node
395  * ----------------
396  */
397 typedef struct WorkTableScan
398 {
399         Scan            scan;
400         int                     wtParam;                /* ID of Param representing work table */
401 } WorkTableScan;
402
403
404 /*
405  * ==========
406  * Join nodes
407  * ==========
408  */
409
410 /* ----------------
411  *              Join node
412  *
413  * jointype:    rule for joining tuples from left and right subtrees
414  * joinqual:    qual conditions that came from JOIN/ON or JOIN/USING
415  *                              (plan.qual contains conditions that came from WHERE)
416  *
417  * When jointype is INNER, joinqual and plan.qual are semantically
418  * interchangeable.  For OUTER jointypes, the two are *not* interchangeable;
419  * only joinqual is used to determine whether a match has been found for
420  * the purpose of deciding whether to generate null-extended tuples.
421  * (But plan.qual is still applied before actually returning a tuple.)
422  * For an outer join, only joinquals are allowed to be used as the merge
423  * or hash condition of a merge or hash join.
424  * ----------------
425  */
426 typedef struct Join
427 {
428         Plan            plan;
429         JoinType        jointype;
430         List       *joinqual;           /* JOIN quals (in addition to plan.qual) */
431 } Join;
432
433 /* ----------------
434  *              nest loop join node
435  * ----------------
436  */
437 typedef struct NestLoop
438 {
439         Join            join;
440 } NestLoop;
441
442 /* ----------------
443  *              merge join node
444  *
445  * The expected ordering of each mergeable column is described by a btree
446  * opfamily OID, a direction (BTLessStrategyNumber or BTGreaterStrategyNumber)
447  * and a nulls-first flag.      Note that the two sides of each mergeclause may
448  * be of different datatypes, but they are ordered the same way according to
449  * the common opfamily.  The operator in each mergeclause must be an equality
450  * operator of the indicated opfamily.
451  * ----------------
452  */
453 typedef struct MergeJoin
454 {
455         Join            join;
456         List       *mergeclauses;       /* mergeclauses as expression trees */
457         /* these are arrays, but have the same length as the mergeclauses list: */
458         Oid                *mergeFamilies;      /* per-clause OIDs of btree opfamilies */
459         int                *mergeStrategies;    /* per-clause ordering (ASC or DESC) */
460         bool       *mergeNullsFirst;    /* per-clause nulls ordering */
461 } MergeJoin;
462
463 /* ----------------
464  *              hash join node
465  * ----------------
466  */
467 typedef struct HashJoin
468 {
469         Join            join;
470         List       *hashclauses;
471 } HashJoin;
472
473 /* ----------------
474  *              materialization node
475  * ----------------
476  */
477 typedef struct Material
478 {
479         Plan            plan;
480 } Material;
481
482 /* ----------------
483  *              sort node
484  * ----------------
485  */
486 typedef struct Sort
487 {
488         Plan            plan;
489         int                     numCols;                /* number of sort-key columns */
490         AttrNumber *sortColIdx;         /* their indexes in the target list */
491         Oid                *sortOperators;      /* OIDs of operators to sort them by */
492         bool       *nullsFirst;         /* NULLS FIRST/LAST directions */
493 } Sort;
494
495 /* ---------------
496  *       group node -
497  *              Used for queries with GROUP BY (but no aggregates) specified.
498  *              The input must be presorted according to the grouping columns.
499  * ---------------
500  */
501 typedef struct Group
502 {
503         Plan            plan;
504         int                     numCols;                /* number of grouping columns */
505         AttrNumber *grpColIdx;          /* their indexes in the target list */
506         Oid                *grpOperators;       /* equality operators to compare with */
507 } Group;
508
509 /* ---------------
510  *              aggregate node
511  *
512  * An Agg node implements plain or grouped aggregation.  For grouped
513  * aggregation, we can work with presorted input or unsorted input;
514  * the latter strategy uses an internal hashtable.
515  *
516  * Notice the lack of any direct info about the aggregate functions to be
517  * computed.  They are found by scanning the node's tlist and quals during
518  * executor startup.  (It is possible that there are no aggregate functions;
519  * this could happen if they get optimized away by constant-folding, or if
520  * we are using the Agg node to implement hash-based grouping.)
521  * ---------------
522  */
523 typedef enum AggStrategy
524 {
525         AGG_PLAIN,                                      /* simple agg across all input rows */
526         AGG_SORTED,                                     /* grouped agg, input must be sorted */
527         AGG_HASHED                                      /* grouped agg, use internal hashtable */
528 } AggStrategy;
529
530 typedef struct Agg
531 {
532         Plan            plan;
533         AggStrategy aggstrategy;
534         int                     numCols;                /* number of grouping columns */
535         AttrNumber *grpColIdx;          /* their indexes in the target list */
536         Oid                *grpOperators;       /* equality operators to compare with */
537         long            numGroups;              /* estimated number of groups in input */
538 } Agg;
539
540 /* ----------------
541  *              window aggregate node
542  * ----------------
543  */
544 typedef struct WindowAgg
545 {
546         Plan            plan;
547         Index           winref;                 /* ID referenced by window functions */
548         int                     partNumCols;    /* number of columns in partition clause */
549         AttrNumber *partColIdx;         /* their indexes in the target list */
550         Oid                *partOperators;      /* equality operators for partition columns */
551         int                     ordNumCols;             /* number of columns in ordering clause */
552         AttrNumber *ordColIdx;          /* their indexes in the target list */
553         Oid                *ordOperators;       /* equality operators for ordering columns */
554         int                     frameOptions;   /* frame_clause options, see WindowDef */
555 } WindowAgg;
556
557 /* ----------------
558  *              unique node
559  * ----------------
560  */
561 typedef struct Unique
562 {
563         Plan            plan;
564         int                     numCols;                /* number of columns to check for uniqueness */
565         AttrNumber *uniqColIdx;         /* their indexes in the target list */
566         Oid                *uniqOperators;      /* equality operators to compare with */
567 } Unique;
568
569 /* ----------------
570  *              hash build node
571  *
572  * If the executor is supposed to try to apply skew join optimization, then
573  * skewTable/skewColumn identify the outer relation's join key column, from
574  * which the relevant MCV statistics can be fetched.  Also, its type
575  * information is provided to save a lookup.
576  * ----------------
577  */
578 typedef struct Hash
579 {
580         Plan            plan;
581         Oid                     skewTable;              /* outer join key's table OID, or InvalidOid */
582         AttrNumber      skewColumn;             /* outer join key's column #, or zero */
583         Oid                     skewColType;    /* datatype of the outer key column */
584         int32           skewColTypmod;  /* typmod of the outer key column */
585         /* all other info is in the parent HashJoin node */
586 } Hash;
587
588 /* ----------------
589  *              setop node
590  * ----------------
591  */
592 typedef enum SetOpCmd
593 {
594         SETOPCMD_INTERSECT,
595         SETOPCMD_INTERSECT_ALL,
596         SETOPCMD_EXCEPT,
597         SETOPCMD_EXCEPT_ALL
598 } SetOpCmd;
599
600 typedef enum SetOpStrategy
601 {
602         SETOP_SORTED,                           /* input must be sorted */
603         SETOP_HASHED                            /* use internal hashtable */
604 } SetOpStrategy;
605
606 typedef struct SetOp
607 {
608         Plan            plan;
609         SetOpCmd        cmd;                    /* what to do */
610         SetOpStrategy strategy;         /* how to do it */
611         int                     numCols;                /* number of columns to check for
612                                                                  * duplicate-ness */
613         AttrNumber *dupColIdx;          /* their indexes in the target list */
614         Oid                *dupOperators;       /* equality operators to compare with */
615         AttrNumber      flagColIdx;             /* where is the flag column, if any */
616         int                     firstFlag;              /* flag value for first input relation */
617         long            numGroups;              /* estimated number of groups in input */
618 } SetOp;
619
620 /* ----------------
621  *              lock-rows node
622  *
623  * rowMarks identifies the rels to be locked by this node; it should be
624  * a subset of the rowMarks listed in the top-level PlannedStmt.
625  * epqParam is a Param that all scan nodes below this one must depend on.
626  * It is used to force re-evaluation of the plan during EvalPlanQual.
627  * ----------------
628  */
629 typedef struct LockRows
630 {
631         Plan            plan;
632         List       *rowMarks;           /* a list of PlanRowMark's */
633         int                     epqParam;               /* ID of Param for EvalPlanQual re-eval */
634 } LockRows;
635
636 /* ----------------
637  *              limit node
638  *
639  * Note: as of Postgres 8.2, the offset and count expressions are expected
640  * to yield int8, rather than int4 as before.
641  * ----------------
642  */
643 typedef struct Limit
644 {
645         Plan            plan;
646         Node       *limitOffset;        /* OFFSET parameter, or NULL if none */
647         Node       *limitCount;         /* COUNT parameter, or NULL if none */
648 } Limit;
649
650
651 /*
652  * RowMarkType -
653  *        enums for types of row-marking operations
654  *
655  * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we have to uniquely
656  * identify all the source rows, not only those from the target relations, so
657  * that we can perform EvalPlanQual rechecking at need.  For plain tables we
658  * can just fetch the TID, the same as for a target relation.  Otherwise (for
659  * example for VALUES or FUNCTION scans) we have to copy the whole row value.
660  * The latter is pretty inefficient but fortunately the case is not
661  * performance-critical in practice.
662  */
663 typedef enum RowMarkType
664 {
665         ROW_MARK_EXCLUSIVE,                     /* obtain exclusive tuple lock */
666         ROW_MARK_SHARE,                         /* obtain shared tuple lock */
667         ROW_MARK_REFERENCE,                     /* just fetch the TID */
668         ROW_MARK_COPY                           /* physically copy the row value */
669 } RowMarkType;
670
671 #define RowMarkRequiresRowShareLock(marktype)  ((marktype) <= ROW_MARK_SHARE)
672
673 /*
674  * PlanRowMark -
675  *         plan-time representation of FOR UPDATE/SHARE clauses
676  *
677  * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we create a separate
678  * PlanRowMark node for each non-target relation in the query.  Relations that
679  * are not specified as FOR UPDATE/SHARE are marked ROW_MARK_REFERENCE (if
680  * real tables) or ROW_MARK_COPY (if not).
681  *
682  * Initially all PlanRowMarks have rti == prti and isParent == false.
683  * When the planner discovers that a relation is the root of an inheritance
684  * tree, it sets isParent true, and adds an additional PlanRowMark to the
685  * list for each child relation (including the target rel itself in its role
686  * as a child).  The child entries have rti == child rel's RT index and
687  * prti == parent's RT index, and can therefore be recognized as children by
688  * the fact that prti != rti.
689  *
690  * The AttrNumbers are filled in during preprocess_targetlist.  We use
691  * different subsets of them for plain relations, inheritance children,
692  * and non-table relations.
693  */
694 typedef struct PlanRowMark
695 {
696         NodeTag         type;
697         Index           rti;                    /* range table index of markable relation */
698         Index           prti;                   /* range table index of parent relation */
699         RowMarkType     markType;               /* see enum above */
700         bool            noWait;                 /* NOWAIT option */
701         bool            isParent;               /* true if this is a "dummy" parent entry */
702         AttrNumber      ctidAttNo;              /* resno of ctid junk attribute, if any */
703         AttrNumber      toidAttNo;              /* resno of tableoid junk attribute, if any */
704         AttrNumber      wholeAttNo;             /* resno of whole-row junk attribute, if any */
705 } PlanRowMark;
706
707
708 /*
709  * Plan invalidation info
710  *
711  * We track the objects on which a PlannedStmt depends in two ways:
712  * relations are recorded as a simple list of OIDs, and everything else
713  * is represented as a list of PlanInvalItems.  A PlanInvalItem is designed
714  * to be used with the syscache invalidation mechanism, so it identifies a
715  * system catalog entry by cache ID and tuple TID.
716  */
717 typedef struct PlanInvalItem
718 {
719         NodeTag         type;
720         int                     cacheId;                /* a syscache ID, see utils/syscache.h */
721         ItemPointerData tupleId;        /* TID of the object's catalog tuple */
722 } PlanInvalItem;
723
724 #endif   /* PLANNODES_H */