postgresql/src/include/nodes/execnodes.h
Tom Lane 6543d81d65 Restructure handling of inheritance queries so that they work with outer
joins, and clean things up a good deal at the same time.  Append plan node
no longer hacks on rangetable at runtime --- instead, all child tables are
given their own RT entries during planning.  Concept of multiple target
tables pushed up into execMain, replacing bug-prone implementation within
nodeAppend.  Planner now supports generating Append plans for inheritance
sets either at the top of the plan (the old way) or at the bottom.  Expanding
at the bottom is appropriate for tables used as sources, since they may
appear inside an outer join; but we must still expand at the top when the
target of an UPDATE or DELETE is an inheritance set, because we actually need
a different targetlist and junkfilter for each target table in that case.
Fortunately a target table can't be inside an outer join...  Bizarre mutual
recursion between union_planner and prepunion.c is gone --- in fact,
union_planner doesn't really have much to do with union queries anymore,
so I renamed it grouping_planner.
2000-11-12 00:37:02 +00:00

735 lines
24 KiB
C

/*-------------------------------------------------------------------------
*
* execnodes.h
* definitions for executor state nodes
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: execnodes.h,v 1.53 2000/11/12 00:37:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef EXECNODES_H
#define EXECNODES_H
#include "access/relscan.h"
#include "access/sdir.h"
#include "executor/hashjoin.h"
#include "executor/tuptable.h"
#include "fmgr.h"
#include "nodes/params.h"
#include "nodes/primnodes.h"
/* ----------------
* IndexInfo information
*
* this class holds the information needed to construct new index
* entries for a particular index. Used for both index_build and
* retail creation of index entries.
*
* NumIndexAttrs number of columns in this index
* (1 if a func. index, else same as NumKeyAttrs)
* NumKeyAttrs number of key attributes for this index
* (ie, number of attrs from underlying relation)
* KeyAttrNumbers underlying-rel attribute numbers used as keys
* Predicate partial-index predicate, or NULL if none
* FuncOid OID of function, or InvalidOid if not f. index
* FuncInfo fmgr lookup data for function, if FuncOid valid
* Unique is it a unique index?
* ----------------
*/
typedef struct IndexInfo
{
NodeTag type;
int ii_NumIndexAttrs;
int ii_NumKeyAttrs;
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS];
Node *ii_Predicate;
Oid ii_FuncOid;
FmgrInfo ii_FuncInfo;
bool ii_Unique;
} IndexInfo;
/* ----------------
* ExprContext
*
* This class holds the "current context" information
* needed to evaluate expressions for doing tuple qualifications
* and tuple projections. For example, if an expression refers
* to an attribute in the current inner tuple then we need to know
* what the current inner tuple is and so we look at the expression
* context.
*
* There are two memory contexts associated with an ExprContext:
* * ecxt_per_query_memory is a relatively long-lived context (such as
* TransactionCommandContext); typically it's the same context the
* ExprContext node itself is allocated in. This context can be
* used for purposes such as storing operator/function fcache nodes.
* * ecxt_per_tuple_memory is a short-term context for expression results.
* As the name suggests, it will typically be reset once per tuple,
* before we begin to evaluate expressions for that tuple. Each
* ExprContext normally has its very own per-tuple memory context.
* CurrentMemoryContext should be set to ecxt_per_tuple_memory before
* calling ExecEvalExpr() --- see ExecEvalExprSwitchContext().
* ----------------
*/
typedef struct ExprContext
{
NodeTag type;
/* Tuples that Var nodes in expression may refer to */
TupleTableSlot *ecxt_scantuple;
TupleTableSlot *ecxt_innertuple;
TupleTableSlot *ecxt_outertuple;
/* Memory contexts for expression evaluation --- see notes above */
MemoryContext ecxt_per_query_memory;
MemoryContext ecxt_per_tuple_memory;
/* Values to substitute for Param nodes in expression */
ParamExecData *ecxt_param_exec_vals; /* for PARAM_EXEC params */
ParamListInfo ecxt_param_list_info; /* for other param types */
/* Values to substitute for Aggref nodes in expression */
Datum *ecxt_aggvalues; /* precomputed values for Aggref nodes */
bool *ecxt_aggnulls; /* null flags for Aggref nodes */
} ExprContext;
/*
* Set-result status returned by ExecEvalExpr()
*/
typedef enum
{
ExprSingleResult, /* expression does not return a set */
ExprMultipleResult, /* this result is an element of a set */
ExprEndResult /* there are no more elements in the set */
} ExprDoneCond;
/*
* When calling a function that might return a set (multiple rows),
* a node of this type is passed as fcinfo->resultinfo to allow
* return status to be passed back. A function returning set should
* raise an error if no such resultinfo is provided.
*
* XXX this mechanism is a quick hack and probably needs to be redesigned.
*/
typedef struct ReturnSetInfo
{
NodeTag type;
ExprDoneCond isDone;
} ReturnSetInfo;
/* ----------------
* ProjectionInfo node information
*
* This is all the information needed to perform projections
* on a tuple. Nodes which need to do projections create one
* of these. In theory, when a node wants to perform a projection
* it should just update this information as necessary and then
* call ExecProject(). -cim 6/3/91
*
* targetlist target list for projection
* len length of target list
* tupValue array of pointers to projection results
* exprContext expression context for ExecTargetList
* slot slot to place projection result in
* ----------------
*/
typedef struct ProjectionInfo
{
NodeTag type;
List *pi_targetlist;
int pi_len;
Datum *pi_tupValue;
ExprContext *pi_exprContext;
TupleTableSlot *pi_slot;
} ProjectionInfo;
/* ----------------
* JunkFilter
*
* This class is used to store information regarding junk attributes.
* A junk attribute is an attribute in a tuple that is needed only for
* storing intermediate information in the executor, and does not belong
* in emitted tuples. For example, when we do an UPDATE query,
* the planner adds a "junk" entry to the targetlist so that the tuples
* returned to ExecutePlan() contain an extra attribute: the ctid of
* the tuple to be updated. This is needed to do the update, but we
* don't want the ctid to be part of the stored new tuple! So, we
* apply a "junk filter" to remove the junk attributes and form the
* real output tuple.
*
* targetList: the original target list (including junk attributes).
* length: the length of 'targetList'.
* tupType: the tuple descriptor for the "original" tuple
* (including the junk attributes).
* cleanTargetList: the "clean" target list (junk attributes removed).
* cleanLength: the length of 'cleanTargetList'
* cleanTupTyp: the tuple descriptor of the "clean" tuple (with
* junk attributes removed).
* cleanMap: A map with the correspondance between the non junk
* attributes of the "original" tuple and the
* attributes of the "clean" tuple.
* ----------------
*/
typedef struct JunkFilter
{
NodeTag type;
List *jf_targetList;
int jf_length;
TupleDesc jf_tupType;
List *jf_cleanTargetList;
int jf_cleanLength;
TupleDesc jf_cleanTupType;
AttrNumber *jf_cleanMap;
} JunkFilter;
/* ----------------
* ResultRelInfo information
*
* whenever we update an existing relation, we have to
* update indices on the relation. The ResultRelInfo class
* is used to hold all the information on result relations,
* including indices.. -cim 10/15/89
*
* RangeTableIndex result relation's range table index
* RelationDesc relation descriptor for result relation
* NumIndices # of indices existing on result relation
* IndexRelationDescs array of relation descriptors for indices
* IndexRelationInfo array of key/attr info for indices
* ConstraintExprs array of constraint-checking expressions
* junkFilter for removing junk attributes from tuples
* ----------------
*/
typedef struct ResultRelInfo
{
NodeTag type;
Index ri_RangeTableIndex;
Relation ri_RelationDesc;
int ri_NumIndices;
RelationPtr ri_IndexRelationDescs;
IndexInfo **ri_IndexRelationInfo;
List **ri_ConstraintExprs;
JunkFilter *ri_junkFilter;
} ResultRelInfo;
/* ----------------
* EState information
*
* direction direction of the scan
*
* range_table array of scan relation information
*
* result_relation information for insert/update/delete queries
*
* into_relation_descriptor relation being retrieved "into"
*
* param_list_info information needed to transform
* Param nodes into Const nodes
*
* tupleTable this is a pointer to an array
* of pointers to tuples used by
* the executor at any given moment.
* ----------------
*/
typedef struct EState
{
NodeTag type;
ScanDirection es_direction;
Snapshot es_snapshot;
List *es_range_table;
ResultRelInfo *es_result_relations; /* array of ResultRelInfos */
int es_num_result_relations; /* length of array */
ResultRelInfo *es_result_relation_info; /* currently active array elt */
JunkFilter *es_junkFilter; /* currently active junk filter */
Relation es_into_relation_descriptor;
ParamListInfo es_param_list_info;
ParamExecData *es_param_exec_vals; /* this is for subselects */
TupleTable es_tupleTable;
uint32 es_processed; /* # of tuples processed */
Oid es_lastoid; /* last oid processed (by INSERT) */
List *es_rowMark; /* not good place, but there is no other */
MemoryContext es_query_cxt; /* per-query context in which EState lives */
/*
* this ExprContext is for per-output-tuple operations, such as
* constraint checks and index-value computations. It can be reset
* for each output tuple. Note that it will be created only if needed.
*/
ExprContext *es_per_tuple_exprcontext;
/* Below is to re-evaluate plan qual in READ COMMITTED mode */
struct Plan *es_origPlan;
Pointer es_evalPlanQual;
bool *es_evTupleNull;
HeapTuple *es_evTuple;
bool es_useEvalPlan;
} EState;
/* ----------------
* Executor Type information needed by plannodes.h
*
*| Note: the bogus classes CommonState and CommonScanState exist only
*| because our inheritance system only allows single inheritance
*| and we have to have unique slot names. Hence two or more
*| classes which want to have a common slot must ALL inherit
*| the slot from some other class. (This is a big hack to
*| allow our classes to share slot names..)
*|
*| Example:
*| the class Result and the class NestLoop nodes both want
*| a slot called "OuterTuple" so they both have to inherit
*| it from some other class. In this case they inherit
*| it from CommonState. "CommonState" and "CommonScanState" are
*| the best names I could come up with for this sort of
*| stuff.
*|
*| As a result, many classes have extra slots which they
*| don't use. These slots are denoted (unused) in the
*| comment preceeding the class definition. If you
*| comes up with a better idea of a way of doing things
*| along these lines, then feel free to make your idea
*| known to me.. -cim 10/15/89
* ----------------
*/
/* ----------------------------------------------------------------
* Common Executor State Information
* ----------------------------------------------------------------
*/
/* ----------------
* CommonState information
*
* Superclass for all executor node-state object types.
*
* OuterTupleSlot pointer to slot containing current "outer" tuple
* ResultTupleSlot pointer to slot in tuple table for projected tuple
* ExprContext node's expression-evaluation context
* ProjInfo info this node uses to form tuple projections
* TupFromTlist state flag used by some node types (why kept here?)
* ----------------
*/
typedef struct CommonState
{
NodeTag type; /* its first field is NodeTag */
TupleTableSlot *cs_OuterTupleSlot;
TupleTableSlot *cs_ResultTupleSlot;
ExprContext *cs_ExprContext;
ProjectionInfo *cs_ProjInfo;
bool cs_TupFromTlist;
} CommonState;
/* ----------------------------------------------------------------
* Control Node State Information
* ----------------------------------------------------------------
*/
/* ----------------
* ResultState information
*
* done flag which tells us to quit when we
* have already returned a constant tuple.
* ----------------
*/
typedef struct ResultState
{
CommonState cstate; /* its first field is NodeTag */
bool rs_done;
bool rs_checkqual;
} ResultState;
/* ----------------
* AppendState information
*
* whichplan which plan is being executed (0 .. n-1)
* nplans how many plans are in the list
* initialized array of ExecInitNode() results
* ----------------
*/
typedef struct AppendState
{
CommonState cstate; /* its first field is NodeTag */
int as_whichplan;
int as_nplans;
bool *as_initialized;
} AppendState;
/* ----------------------------------------------------------------
* Scan State Information
* ----------------------------------------------------------------
*/
/* ----------------
* CommonScanState information
*
* CommonScanState extends CommonState for node types that represent
* scans of an underlying relation. It can also be used for nodes
* that scan the output of an underlying plan node --- in that case,
* only ScanTupleSlot is actually useful, and it refers to the tuple
* retrieved from the subplan.
*
* currentRelation relation being scanned (NULL if none)
* currentScanDesc current scan descriptor for scan (NULL if none)
* ScanTupleSlot pointer to slot in tuple table holding scan tuple
* ----------------
*/
typedef struct CommonScanState
{
CommonState cstate; /* its first field is NodeTag */
Relation css_currentRelation;
HeapScanDesc css_currentScanDesc;
TupleTableSlot *css_ScanTupleSlot;
} CommonScanState;
/*
* SeqScan uses a bare CommonScanState as its state item, since it needs
* no additional fields.
*/
/* ----------------
* IndexScanState information
*
* Note that an IndexScan node *also* has a CommonScanState state item.
* IndexScanState stores the info needed specifically for indexing.
* There's probably no good reason why this is a separate node type
* rather than an extension of CommonScanState.
*
* NumIndices number of indices in this scan
* IndexPtr current index in use
* ScanKeys Skey structures to scan index rels
* NumScanKeys array of no of keys in each Skey struct
* RuntimeKeyInfo array of array of flags for Skeys evaled at runtime
* RuntimeContext expr context for evaling runtime Skeys
* RuntimeKeysReady true if runtime Skeys have been computed
* RelationDescs ptr to array of relation descriptors
* ScanDescs ptr to array of scan descriptors
* ----------------
*/
typedef struct IndexScanState
{
NodeTag type;
int iss_NumIndices;
int iss_IndexPtr;
int iss_MarkIndexPtr;
ScanKey *iss_ScanKeys;
int *iss_NumScanKeys;
int **iss_RuntimeKeyInfo;
ExprContext *iss_RuntimeContext;
bool iss_RuntimeKeysReady;
RelationPtr iss_RelationDescs;
IndexScanDescPtr iss_ScanDescs;
HeapTupleData iss_htup;
} IndexScanState;
/* ----------------
* TidScanState information
*
* Note that a TidScan node *also* has a CommonScanState state item.
* There's probably no good reason why this is a separate node type
* rather than an extension of CommonScanState.
*
* NumTids number of tids in this scan
* TidPtr current tid in use
* TidList evaluated item pointers
* ----------------
*/
typedef struct TidScanState
{
NodeTag type;
int tss_NumTids;
int tss_TidPtr;
int tss_MarkTidPtr;
ItemPointer *tss_TidList;
HeapTupleData tss_htup;
} TidScanState;
/* ----------------
* SubqueryScanState information
*
* SubqueryScanState is used for scanning a sub-query in the range table.
* The sub-query will have its own EState, which we save here.
* ScanTupleSlot references the current output tuple of the sub-query.
*
* SubEState exec state for sub-query
* ----------------
*/
typedef struct SubqueryScanState
{
CommonScanState csstate; /* its first field is NodeTag */
EState *sss_SubEState;
} SubqueryScanState;
/* ----------------------------------------------------------------
* Join State Information
* ----------------------------------------------------------------
*/
/* ----------------
* JoinState information
*
* Superclass for state items of join nodes.
* Currently this is the same as CommonState.
* ----------------
*/
typedef CommonState JoinState;
/* ----------------
* NestLoopState information
*
* NeedNewOuter true if need new outer tuple on next call
* MatchedOuter true if found a join match for current outer tuple
* NullInnerTupleSlot prepared null tuple for left outer joins
* ----------------
*/
typedef struct NestLoopState
{
JoinState jstate; /* its first field is NodeTag */
bool nl_NeedNewOuter;
bool nl_MatchedOuter;
TupleTableSlot *nl_NullInnerTupleSlot;
} NestLoopState;
/* ----------------
* MergeJoinState information
*
* OuterSkipQual outerKey1 < innerKey1 ...
* InnerSkipQual outerKey1 > innerKey1 ...
* JoinState current "state" of join. see executor.h
* MatchedOuter true if found a join match for current outer tuple
* MatchedInner true if found a join match for current inner tuple
* OuterTupleSlot pointer to slot in tuple table for cur outer tuple
* InnerTupleSlot pointer to slot in tuple table for cur inner tuple
* MarkedTupleSlot pointer to slot in tuple table for marked tuple
* NullOuterTupleSlot prepared null tuple for right outer joins
* NullInnerTupleSlot prepared null tuple for left outer joins
* ----------------
*/
typedef struct MergeJoinState
{
JoinState jstate; /* its first field is NodeTag */
List *mj_OuterSkipQual;
List *mj_InnerSkipQual;
int mj_JoinState;
bool mj_MatchedOuter;
bool mj_MatchedInner;
TupleTableSlot *mj_OuterTupleSlot;
TupleTableSlot *mj_InnerTupleSlot;
TupleTableSlot *mj_MarkedTupleSlot;
TupleTableSlot *mj_NullOuterTupleSlot;
TupleTableSlot *mj_NullInnerTupleSlot;
} MergeJoinState;
/* ----------------
* HashJoinState information
*
* hj_HashTable hash table for the hashjoin
* hj_CurBucketNo bucket# for current outer tuple
* hj_CurTuple last inner tuple matched to current outer
* tuple, or NULL if starting search
* (CurBucketNo and CurTuple are meaningless
* unless OuterTupleSlot is nonempty!)
* hj_InnerHashKey the inner hash key in the hashjoin condition
* hj_OuterTupleSlot tuple slot for outer tuples
* hj_HashTupleSlot tuple slot for hashed tuples
* hj_NullInnerTupleSlot prepared null tuple for left outer joins
* hj_NeedNewOuter true if need new outer tuple on next call
* hj_MatchedOuter true if found a join match for current outer
* hj_hashdone true if hash-table-build phase is done
* ----------------
*/
typedef struct HashJoinState
{
JoinState jstate; /* its first field is NodeTag */
HashJoinTable hj_HashTable;
int hj_CurBucketNo;
HashJoinTuple hj_CurTuple;
Node *hj_InnerHashKey;
TupleTableSlot *hj_OuterTupleSlot;
TupleTableSlot *hj_HashTupleSlot;
TupleTableSlot *hj_NullInnerTupleSlot;
bool hj_NeedNewOuter;
bool hj_MatchedOuter;
bool hj_hashdone;
} HashJoinState;
/* ----------------------------------------------------------------
* Materialization State Information
* ----------------------------------------------------------------
*/
/* ----------------
* MaterialState information
*
* materialize nodes are used to materialize the results
* of a subplan into a temporary file.
*
* csstate.css_ScanTupleSlot refers to output of underlying plan.
*
* tuplestorestate private state of tuplestore.c
* ----------------
*/
typedef struct MaterialState
{
CommonScanState csstate; /* its first field is NodeTag */
void *tuplestorestate;
} MaterialState;
/* ---------------------
* AggregateState information
*
* csstate.css_ScanTupleSlot refers to output of underlying plan.
*
* Note: the associated ExprContext contains ecxt_aggvalues and ecxt_aggnulls
* arrays, which hold the computed agg values for the current input group
* during evaluation of an Agg node's output tuple(s).
* -------------------------
*/
typedef struct AggStatePerAggData *AggStatePerAgg; /* private in nodeAgg.c */
typedef struct AggState
{
CommonScanState csstate; /* its first field is NodeTag */
List *aggs; /* all Aggref nodes in targetlist & quals */
int numaggs; /* length of list (could be zero!) */
AggStatePerAgg peragg; /* per-Aggref working state */
MemoryContext tup_cxt; /* context for per-output-tuple expressions */
MemoryContext agg_cxt[2]; /* pair of expression eval memory contexts */
int which_cxt; /* 0 or 1, indicates current agg_cxt */
bool agg_done; /* indicates completion of Agg scan */
} AggState;
/* ---------------------
* GroupState information
* -------------------------
*/
typedef struct GroupState
{
CommonScanState csstate; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
bool grp_useFirstTuple; /* first tuple not processed yet */
bool grp_done;
HeapTuple grp_firstTuple;
} GroupState;
/* ----------------
* SortState information
*
* sort_Done indicates whether sort has been performed yet
* sort_Keys scan key structures describing the sort keys
* tuplesortstate private state of tuplesort.c
* ----------------
*/
typedef struct SortState
{
CommonScanState csstate; /* its first field is NodeTag */
bool sort_Done;
ScanKey sort_Keys;
void *tuplesortstate;
} SortState;
/* ----------------
* UniqueState information
*
* Unique nodes are used "on top of" sort nodes to discard
* duplicate tuples returned from the sort phase. Basically
* all it does is compare the current tuple from the subplan
* with the previously fetched tuple stored in priorTuple.
* If the two are identical in all interesting fields, then
* we just fetch another tuple from the sort and try again.
* ----------------
*/
typedef struct UniqueState
{
CommonState cstate; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
HeapTuple priorTuple; /* most recently returned tuple, or NULL */
MemoryContext tempContext; /* short-term context for comparisons */
} UniqueState;
/* ----------------
* SetOpState information
*
* SetOp nodes are used "on top of" sort nodes to discard
* duplicate tuples returned from the sort phase. These are
* more complex than a simple Unique since we have to count
* how many duplicates to return.
* ----------------
*/
typedef struct SetOpState
{
CommonState cstate; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
bool subplan_done; /* has subplan returned EOF? */
long numLeft; /* number of left-input dups of cur group */
long numRight; /* number of right-input dups of cur group */
long numOutput; /* number of dups left to output */
MemoryContext tempContext; /* short-term context for comparisons */
} SetOpState;
/* ----------------
* LimitState information
*
* Limit nodes are used to enforce LIMIT/OFFSET clauses.
* They just select the desired subrange of their subplan's output.
*
* offset is the number of initial tuples to skip (0 does nothing).
* count is the number of tuples to return after skipping the offset tuples.
* If no limit count was specified, count is undefined and noCount is true.
* ----------------
*/
typedef struct LimitState
{
CommonState cstate; /* its first field is NodeTag */
long offset; /* current OFFSET value */
long count; /* current COUNT, if any */
long position; /* 1-based index of last tuple fetched */
bool parmsSet; /* have we calculated offset/limit yet? */
bool noCount; /* if true, ignore count */
bool atEnd; /* if true, we've reached EOF of subplan */
} LimitState;
/* ----------------
* HashState information
*
* hashtable hash table for the hashjoin
* ----------------
*/
typedef struct HashState
{
CommonState cstate; /* its first field is NodeTag */
HashJoinTable hashtable;
} HashState;
#ifdef NOT_USED
/* -----------------------
* TeeState information
* leftPlace : next item in the queue unseen by the left parent
* rightPlace : next item in the queue unseen by the right parent
* lastPlace : last item in the queue
* bufferRelname : name of the relation used as the buffer queue
* bufferRel : the relation used as the buffer queue
* mcxt : for now, tee's have their own memory context
* may be cleaned up later if portals are cleaned up
*
* initially, a Tee starts with [left/right]Place variables set to -1.
* on cleanup, queue is free'd when both leftPlace and rightPlace = -1
* -------------------------
*/
typedef struct TeeState
{
CommonState cstate; /* its first field is NodeTag */
int tee_leftPlace,
tee_rightPlace,
tee_lastPlace;
char *tee_bufferRelname;
Relation tee_bufferRel;
MemoryContext tee_mcxt;
HeapScanDesc tee_leftScanDesc,
tee_rightScanDesc;
} TeeState;
#endif
#endif /* EXECNODES_H */