greenplumn cdbplan 源码
greenplumn cdbplan 代码
文件路径:/src/backend/cdb/cdbplan.c
/*-------------------------------------------------------------------------
*
* cdbplan.c
* Provides routines supporting plan tree manipulation.
*
* Portions Copyright (c) 2004-2008, Greenplum inc
* Portions Copyright (c) 2012-Present VMware, Inc. or its affiliates.
*
*
* IDENTIFICATION
* src/backend/cdb/cdbplan.c
*
* NOTES
* See src/backend/optimizer/util/clauses.c for background information
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "cdb/cdbgroup.h"
#include "cdb/cdbplan.h"
#include "cdb/cdbsetop.h"
#include "miscadmin.h"
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "optimizer/clauses.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
static void mutate_plan_fields(Plan *newplan, Plan *oldplan, Node *(*mutator) (), void *context);
static void mutate_join_fields(Join *newplan, Join *oldplan, Node *(*mutator) (), void *context);
/* ----------------------------------------------------------------------- *
* Plan Tree Mutator Framework
* ----------------------------------------------------------------------- *
*/
/*--------------------
* expression_tree_mutator() is designed to support routines that make a
* modified copy of an expression tree, with some nodes being added,
* removed, or replaced by new subtrees. The original tree is (normally)
* not changed. Each recursion level is responsible for returning a copy of
* (or appropriately modified substitute for) the subtree it is handed.
* A mutator routine should look like this:
*
* Node * my_mutator (Node *node, my_struct *context)
* {
* if (node == NULL)
* return NULL;
* // check for nodes that special work is required for, eg:
* if (IsA(node, Var))
* {
* ... create and return modified copy of Var node
* }
* else if (IsA(node, ...))
* {
* ... do special transformations of other node types
* }
* // for any node type not specially processed, do:
* return expression_tree_mutator(node, my_mutator, (void *) context);
* }
*
* The "context" argument points to a struct that holds whatever context
* information the mutator routine needs --- it can be used to return extra
* data gathered by the mutator, too. This argument is not touched by
* expression_tree_mutator, but it is passed down to recursive sub-invocations
* of my_mutator. The tree walk is started from a setup routine that
* fills in the appropriate context struct, calls my_mutator with the
* top-level node of the tree, and does any required post-processing.
*
* Each level of recursion must return an appropriately modified Node.
* If expression_tree_mutator() is called, it will make an exact copy
* of the given Node, but invoke my_mutator() to copy the sub-node(s)
* of that Node. In this way, my_mutator() has full control over the
* copying process but need not directly deal with expression trees
* that it has no interest in.
*
* Just as for expression_tree_walker, the node types handled by
* expression_tree_mutator include all those normally found in target lists
* and qualifier clauses during the planning stage.
*
* expression_tree_mutator will handle SubLink nodes by recursing normally
* into the "lefthand" arguments (which are expressions belonging to the outer
* plan). It will also call the mutator on the sub-Query node; however, when
* expression_tree_mutator itself is called on a Query node, it does nothing
* and returns the unmodified Query node. The net effect is that unless the
* mutator does something special at a Query node, sub-selects will not be
* visited or modified; the original sub-select will be linked to by the new
* SubLink node. Mutators that want to descend into sub-selects will usually
* do so by recognizing Query nodes and calling query_tree_mutator (below).
*
* expression_tree_mutator will handle a SubPlan node by recursing into
* the "exprs" and "args" lists (which belong to the outer plan), but it
* will simply copy the link to the inner plan, since that's typically what
* expression tree mutators want. A mutator that wants to modify the subplan
* can force appropriate behavior by recognizing SubPlan expression nodes
* and doing the right thing.
*--------------------
*/
Node *
plan_tree_mutator(Node *node,
Node *(*mutator) (),
void *context,
bool recurse_into_subplans)
{
/*
* The mutator has already decided not to modify the current node, but we
* must call the mutator for any sub-nodes.
*/
#define FLATCOPY(newnode, node, nodetype) \
( (newnode) = makeNode(nodetype), \
memcpy((newnode), (node), sizeof(nodetype)) )
#define CHECKFLATCOPY(newnode, node, nodetype) \
( AssertMacro(IsA((node), nodetype)), \
(newnode) = makeNode(nodetype), \
memcpy((newnode), (node), sizeof(nodetype)) )
#define MUTATE(newfield, oldfield, fieldtype) \
( (newfield) = (fieldtype) mutator((Node *) (oldfield), context) )
#define PLANMUTATE(newplan, oldplan) \
mutate_plan_fields((Plan*)(newplan), (Plan*)(oldplan), mutator, context)
/* This is just like PLANMUTATE because Scan adds only scalar fields. */
#define SCANMUTATE(newplan, oldplan) \
mutate_plan_fields((Plan*)(newplan), (Plan*)(oldplan), mutator, context)
#define JOINMUTATE(newplan, oldplan) \
mutate_join_fields((Join*)(newplan), (Join*)(oldplan), mutator, context)
#define COPYARRAY(dest,src,lenfld,datfld) \
do { \
(dest)->lenfld = (src)->lenfld; \
if ( (src)->lenfld > 0 && \
(src)->datfld != NULL) \
{ \
Size _size = ((src)->lenfld*sizeof(*((src)->datfld))); \
(dest)->datfld = palloc(_size); \
memcpy((dest)->datfld, (src)->datfld, _size); \
} \
else \
{ \
(dest)->datfld = NULL; \
} \
} while (0)
if (node == NULL)
return NULL;
/* Guard against stack overflow due to overly complex expressions */
check_stack_depth();
switch (nodeTag(node))
{
/*
* Plan nodes aren't handled by expression_tree_walker, so we need
* to do them here.
*/
case T_Plan:
/* Abstract: Should see only subclasses. */
elog(ERROR, "abstract node type not allowed: T_Plan");
break;
case T_Result:
{
Result *result = (Result *) node;
Result *newresult;
FLATCOPY(newresult, result, Result);
PLANMUTATE(newresult, result);
MUTATE(newresult->resconstantqual, result->resconstantqual, Node *);
return (Node *) newresult;
}
break;
case T_ProjectSet:
{
ProjectSet *ps = (ProjectSet *) node;
ProjectSet *newps;
FLATCOPY(newps, ps, ProjectSet);
PLANMUTATE(newps, ps);
return (Node *) newps;
}
break;
case T_ModifyTable:
{
ModifyTable *mt = (ModifyTable *) node;
ModifyTable *newmt;
FLATCOPY(newmt, mt, ModifyTable);
PLANMUTATE(newmt, mt);
MUTATE(newmt->plans, mt->plans, List *);
MUTATE(newmt->onConflictSet, mt->onConflictSet, List *);
MUTATE(newmt->onConflictWhere, mt->onConflictWhere , Node *);
MUTATE(newmt->withCheckOptionLists, mt->withCheckOptionLists, List *);
MUTATE(newmt->returningLists, mt->returningLists, List *);
return (Node *) newmt;
}
break;
case T_LockRows:
{
LockRows *lockrows = (LockRows *) node;
LockRows *newlockrows;
FLATCOPY(newlockrows, lockrows, LockRows);
PLANMUTATE(newlockrows, lockrows);
return (Node *) newlockrows;
}
break;
case T_Append:
{
Append *append = (Append *) node;
Append *newappend;
FLATCOPY(newappend, append, Append);
PLANMUTATE(newappend, append);
MUTATE(newappend->appendplans, append->appendplans, List *);
return (Node *) newappend;
}
break;
case T_MergeAppend:
{
MergeAppend *merge = (MergeAppend *) node;
MergeAppend *newmerge;
FLATCOPY(newmerge, merge, MergeAppend);
PLANMUTATE(newmerge, merge);
MUTATE(newmerge->mergeplans, merge->mergeplans, List *);
return (Node *) newmerge;
}
break;
case T_RecursiveUnion:
{
RecursiveUnion *ru = (RecursiveUnion *) node;
RecursiveUnion *newru;
FLATCOPY(newru, ru, RecursiveUnion);
PLANMUTATE(newru, ru);
return (Node *) newru;
}
case T_Sequence:
{
Sequence *sequence = (Sequence *) node;
Sequence *newSequence = NULL;
FLATCOPY(newSequence, sequence, Sequence);
PLANMUTATE(newSequence, sequence);
MUTATE(newSequence->subplans, sequence->subplans, List *);
return (Node *) newSequence;
}
case T_AssertOp:
{
AssertOp *assert = (AssertOp *) node;
AssertOp *newAssert = NULL;
FLATCOPY(newAssert, assert, AssertOp);
PLANMUTATE(newAssert, assert);
return (Node *) newAssert;
}
case T_PartitionSelector:
{
PartitionSelector *partsel = (PartitionSelector *) node;
PartitionSelector *newPartsel = NULL;
FLATCOPY(newPartsel, partsel, PartitionSelector);
PLANMUTATE(newPartsel, partsel);
return (Node *) newPartsel;
}
case T_BitmapAnd:
{
BitmapAnd *old = (BitmapAnd *) node;
BitmapAnd *mut;
FLATCOPY(mut, old, BitmapAnd);
PLANMUTATE(mut, old);
MUTATE(mut->bitmapplans, old->bitmapplans, List *);
return (Node *) mut;
}
break;
case T_BitmapOr:
{
BitmapOr *old = (BitmapOr *) node;
BitmapOr *mut;
FLATCOPY(mut, old, BitmapOr);
PLANMUTATE(mut, old);
MUTATE(mut->bitmapplans, old->bitmapplans, List *);
return (Node *) mut;
}
break;
case T_Scan:
/* Abstract: Should see only subclasses. */
elog(ERROR, "abstract node type not allowed: T_Scan");
break;
case T_SampleScan:
{
SampleScan *samplescan = (SampleScan *) node;
SampleScan *newsamplescan;
FLATCOPY(newsamplescan, samplescan, SampleScan);
SCANMUTATE(newsamplescan, samplescan);
return (Node *) newsamplescan;
}
break;
case T_CustomScan:
{
CustomScan *cscan = (CustomScan *) node;
CustomScan *newcscan;
FLATCOPY(newcscan, cscan, CustomScan);
SCANMUTATE(newcscan, cscan);
return (Node *) newcscan;
}
break;
case T_SeqScan:
{
SeqScan *seqscan = (SeqScan *) node;
SeqScan *newseqscan;
FLATCOPY(newseqscan, seqscan, SeqScan);
SCANMUTATE(newseqscan, seqscan);
/* A SeqScan is really just a Scan, so we're done. */
return (Node *) newseqscan;
}
break;
case T_DynamicSeqScan:
{
DynamicSeqScan *dynamicSeqScan = (DynamicSeqScan *) node;
DynamicSeqScan *newDynamicSeqScan = NULL;
FLATCOPY(newDynamicSeqScan, dynamicSeqScan, DynamicSeqScan);
SCANMUTATE(newDynamicSeqScan, dynamicSeqScan);
return (Node *) newDynamicSeqScan;
}
break;
case T_IndexScan:
case T_DynamicIndexScan:
{
IndexScan *idxscan = (IndexScan *) node;
IndexScan *newidxscan;
if (IsA(node, DynamicIndexScan))
{
/*
* A DynamicIndexScan is identical to IndexScan, except for
* additional fields. This convoluted coding is to avoid
* copy-pasting this code and risking bugs of omission if
* new fields are added to IndexScan in upstream.
*/
DynamicIndexScan *newdiscan;
FLATCOPY(newdiscan, idxscan, DynamicIndexScan);
newidxscan = (IndexScan *) newdiscan;
}
else
FLATCOPY(newidxscan, idxscan, IndexScan);
SCANMUTATE(newidxscan, idxscan);
newidxscan->indexid = idxscan->indexid;
/* MUTATE(newidxscan->indexid, idxscan->indexid, List *); */
MUTATE(newidxscan->indexqual, idxscan->indexqual, List *);
MUTATE(newidxscan->indexqualorig, idxscan->indexqualorig, List *);
/* indxorderdir is scalar */
return (Node *) newidxscan;
}
break;
case T_IndexOnlyScan:
{
IndexOnlyScan *idxonlyscan = (IndexOnlyScan *) node;
IndexOnlyScan *newidxonlyscan;
FLATCOPY(newidxonlyscan, idxonlyscan, IndexOnlyScan);
SCANMUTATE(newidxonlyscan, idxonlyscan);
newidxonlyscan->indexid = idxonlyscan->indexid;
/* MUTATE(newidxonlyscan->indexid, idxonlyscan->indexid, List *); */
MUTATE(newidxonlyscan->indexqual, idxonlyscan->indexqual, List *);
MUTATE(newidxonlyscan->indextlist, idxonlyscan->indextlist, List *);
/* indxorderdir is scalar */
return (Node *) newidxonlyscan;
}
break;
case T_BitmapIndexScan:
case T_DynamicBitmapIndexScan:
{
BitmapIndexScan *idxscan = (BitmapIndexScan *) node;
BitmapIndexScan *newidxscan;
if (IsA(node, DynamicBitmapIndexScan))
{
/* see comment above on DynamicIndexScan */
DynamicBitmapIndexScan *newdbiscan;
FLATCOPY(newdbiscan, idxscan, DynamicBitmapIndexScan);
newidxscan = (BitmapIndexScan *) newdbiscan;
}
else
FLATCOPY(newidxscan, idxscan, BitmapIndexScan);
SCANMUTATE(newidxscan, idxscan);
newidxscan->indexid = idxscan->indexid;
MUTATE(newidxscan->indexqual, idxscan->indexqual, List *);
MUTATE(newidxscan->indexqualorig, idxscan->indexqualorig, List *);
return (Node *) newidxscan;
}
break;
case T_BitmapHeapScan:
case T_DynamicBitmapHeapScan:
{
BitmapHeapScan *bmheapscan = (BitmapHeapScan *) node;
BitmapHeapScan *newbmheapscan;
if (IsA(node, DynamicBitmapHeapScan))
{
/* see comment above on DynamicIndexScan */
DynamicBitmapHeapScan *newdbhscan;
FLATCOPY(newdbhscan, bmheapscan, DynamicBitmapHeapScan);
newbmheapscan = (BitmapHeapScan *) newdbhscan;
}
else
FLATCOPY(newbmheapscan, bmheapscan, BitmapHeapScan);
SCANMUTATE(newbmheapscan, bmheapscan);
MUTATE(newbmheapscan->bitmapqualorig, bmheapscan->bitmapqualorig, List *);
return (Node *) newbmheapscan;
}
break;
case T_TidScan:
{
TidScan *tidscan = (TidScan *) node;
TidScan *newtidscan;
FLATCOPY(newtidscan, tidscan, TidScan);
SCANMUTATE(newtidscan, tidscan);
MUTATE(newtidscan->tidquals, tidscan->tidquals, List *);
/* isTarget is scalar. */
return (Node *) newtidscan;
}
break;
case T_SubqueryScan:
{
SubqueryScan *sqscan = (SubqueryScan *) node;
SubqueryScan *newsqscan;
FLATCOPY(newsqscan, sqscan, SubqueryScan);
SCANMUTATE(newsqscan, sqscan);
MUTATE(newsqscan->subplan, sqscan->subplan, Plan *);
return (Node *) newsqscan;
}
break;
case T_FunctionScan:
{
FunctionScan *fnscan = (FunctionScan *) node;
FunctionScan *newfnscan;
FLATCOPY(newfnscan, fnscan, FunctionScan);
SCANMUTATE(newfnscan, fnscan);
/* A FunctionScan is really just a Scan, so we're done. */
return (Node *) newfnscan;
}
break;
case T_ValuesScan:
{
ValuesScan *scan = (ValuesScan *) node;
ValuesScan *newscan;
FLATCOPY(newscan, scan, ValuesScan);
MUTATE(newscan->values_lists, scan->values_lists, List *);
SCANMUTATE(newscan, scan);
return (Node *) newscan;
}
break;
case T_TableFuncScan:
{
TableFuncScan *scan = (TableFuncScan *) node;
TableFuncScan *newscan;
FLATCOPY(newscan, scan, TableFuncScan);
MUTATE(newscan->tablefunc, scan->tablefunc, TableFunc *);
SCANMUTATE(newscan, scan);
return (Node *) newscan;
}
break;
case T_WorkTableScan:
{
WorkTableScan *wts = (WorkTableScan *) node;
WorkTableScan *newwts;
FLATCOPY(newwts, wts, WorkTableScan);
SCANMUTATE(newwts, wts);
return (Node *) newwts;
}
case T_NamedTuplestoreScan:
{
NamedTuplestoreScan *ntscan = (NamedTuplestoreScan *) node;
NamedTuplestoreScan *newntscan;
FLATCOPY(newntscan, ntscan, NamedTuplestoreScan);
SCANMUTATE(newntscan, ntscan);
return (Node *) newntscan;
}
break;
case T_Join:
/* Abstract: Should see only subclasses. */
elog(ERROR, "abstract node type not allowed: T_Join");
break;
case T_NestLoop:
{
NestLoop *loopscan = (NestLoop *) node;
NestLoop *newloopscan;
FLATCOPY(newloopscan, loopscan, NestLoop);
JOINMUTATE(newloopscan, loopscan);
/* A NestLoop is really just a Join. */
return (Node *) newloopscan;
}
break;
case T_MergeJoin:
{
MergeJoin *merge = (MergeJoin *) node;
MergeJoin *newmerge;
FLATCOPY(newmerge, merge, MergeJoin);
JOINMUTATE(newmerge, merge);
MUTATE(newmerge->mergeclauses, merge->mergeclauses, List *);
return (Node *) newmerge;
}
break;
case T_HashJoin:
{
HashJoin *hjoin = (HashJoin *) node;
HashJoin *newhjoin;
FLATCOPY(newhjoin, hjoin, HashJoin);
JOINMUTATE(newhjoin, hjoin);
MUTATE(newhjoin->hashclauses, hjoin->hashclauses, List *);
MUTATE(newhjoin->hashqualclauses, hjoin->hashqualclauses, List *);
return (Node *) newhjoin;
}
break;
case T_ShareInputScan:
{
ShareInputScan *sis = (ShareInputScan *) node;
ShareInputScan *newsis;
FLATCOPY(newsis, sis, ShareInputScan);
PLANMUTATE(newsis, sis);
return (Node *) newsis;
}
break;
case T_Material:
{
Material *material = (Material *) node;
Material *newmaterial;
FLATCOPY(newmaterial, material, Material);
PLANMUTATE(newmaterial, material);
return (Node *) newmaterial;
}
break;
case T_Sort:
{
Sort *sort = (Sort *) node;
Sort *newsort;
FLATCOPY(newsort, sort, Sort);
PLANMUTATE(newsort, sort);
COPYARRAY(newsort, sort, numCols, sortColIdx);
COPYARRAY(newsort, sort, numCols, sortOperators);
COPYARRAY(newsort, sort, numCols, nullsFirst);
return (Node *) newsort;
}
break;
case T_Agg:
{
Agg *agg = (Agg *) node;
Agg *newagg;
FLATCOPY(newagg, agg, Agg);
PLANMUTATE(newagg, agg);
COPYARRAY(newagg, agg, numCols, grpColIdx);
return (Node *) newagg;
}
break;
case T_TupleSplit:
{
TupleSplit *tup_split = (TupleSplit *) node;
TupleSplit *new_tup_split;
FLATCOPY(new_tup_split, tup_split, TupleSplit);
PLANMUTATE(new_tup_split, tup_split);
COPYARRAY(new_tup_split, tup_split, numCols, grpColIdx);
MUTATE(new_tup_split->dqa_expr_lst, tup_split->dqa_expr_lst, List *);
return (Node *) new_tup_split;
}
break;
case T_TableFunctionScan:
{
TableFunctionScan *tabfunc = (TableFunctionScan *) node;
TableFunctionScan *newtabfunc;
FLATCOPY(newtabfunc, tabfunc, TableFunctionScan);
PLANMUTATE(newtabfunc, tabfunc);
return (Node *) newtabfunc;
}
break;
case T_WindowAgg:
{
WindowAgg *window = (WindowAgg *) node;
WindowAgg *newwindow;
FLATCOPY(newwindow, window, WindowAgg);
PLANMUTATE(newwindow, window);
COPYARRAY(newwindow, window, partNumCols, partColIdx);
COPYARRAY(newwindow, window, partNumCols, partOperators);
COPYARRAY(newwindow, window, ordNumCols, ordColIdx);
COPYARRAY(newwindow, window, ordNumCols, ordOperators);
MUTATE(newwindow->startOffset, window->startOffset, Node *);
MUTATE(newwindow->endOffset, window->endOffset, Node *);
return (Node *) newwindow;
}
break;
case T_Unique:
{
Unique *uniq = (Unique *) node;
Unique *newuniq;
FLATCOPY(newuniq, uniq, Unique);
PLANMUTATE(newuniq, uniq);
COPYARRAY(newuniq, uniq, numCols, uniqColIdx);
return (Node *) newuniq;
}
break;
case T_Gather:
{
Gather *gather = (Gather *) node;
Gather *newgather;
FLATCOPY(newgather, gather, Gather);
PLANMUTATE(newgather, gather);
return (Node *) newgather;
}
break;
case T_Hash:
{
Hash *hash = (Hash *) node;
Hash *newhash;
FLATCOPY(newhash, hash, Hash);
PLANMUTATE(newhash, hash);
return (Node *) newhash;
}
break;
case T_SetOp:
{
SetOp *setop = (SetOp *) node;
SetOp *newsetop;
FLATCOPY(newsetop, setop, SetOp);
PLANMUTATE(newsetop, setop);
COPYARRAY(newsetop, setop, numCols, dupColIdx);
return (Node *) newsetop;
}
break;
case T_Limit:
{
Limit *limit = (Limit *) node;
Limit *newlimit;
FLATCOPY(newlimit, limit, Limit);
PLANMUTATE(newlimit, limit);
MUTATE(newlimit->limitOffset, limit->limitOffset, Node *);
MUTATE(newlimit->limitCount, limit->limitCount, Node *);
return (Node *) newlimit;
}
break;
case T_Motion:
{
Motion *motion = (Motion *) node;
Motion *newmotion;
FLATCOPY(newmotion, motion, Motion);
PLANMUTATE(newmotion, motion);
MUTATE(newmotion->hashExprs, motion->hashExprs, List *);
COPYARRAY(newmotion, motion, numSortCols, sortColIdx);
COPYARRAY(newmotion, motion, numSortCols, sortOperators);
COPYARRAY(newmotion, motion, numSortCols, nullsFirst);
return (Node *) newmotion;
}
break;
case T_Flow:
{
Flow *flow = (Flow *) node;
Flow *newflow;
FLATCOPY(newflow, flow, Flow);
return (Node *) newflow;
}
break;
case T_IntList:
case T_OidList:
/*
* Note that expression_tree_mutator handles T_List but not these.
* A shallow copy will do.
*/
return (Node *) list_copy((List *) node);
break;
case T_Query:
/*
* Since expression_tree_mutator doesn't descend into Query nodes,
* we use ...
*/
return (Node *) query_tree_mutator((Query *) node, mutator, context, 0);
break;
case T_SubPlan:
/*
* Since expression_tree_mutator doesn't descend into the plan in
* a SubPlan node, we handle the case directly.
*/
{
SubPlan *subplan = (SubPlan *) node;
SubPlan *newnode;
FLATCOPY(newnode, subplan, SubPlan);
MUTATE(newnode->testexpr, subplan->testexpr, Node *);
MUTATE(newnode->args, subplan->args, List *);
if (recurse_into_subplans)
{
Plan *subplan_plan = plan_tree_base_subplan_get_plan(context, subplan);
Plan *newsubplan_plan;
MUTATE(newsubplan_plan, subplan_plan, Plan *);
if (newsubplan_plan != subplan_plan)
plan_tree_base_subplan_put_plan(context, newnode, newsubplan_plan);
}
/* An IntList isn't interesting to mutate; just copy. */
newnode->paramIds = (List *) copyObject(subplan->paramIds);
newnode->setParam = (List *) copyObject(subplan->setParam);
newnode->parParam = (List *) copyObject(subplan->parParam);
newnode->extParam = (List *) copyObject(subplan->extParam);
return (Node *) newnode;
}
break;
case T_RangeTblEntry:
/*
* Also expression_tree_mutator doesn't recognize range table
* entries.
*
* TODO Figure out what's to do and handle this case. ***************************************************
*
*/
{
RangeTblEntry *rte = (RangeTblEntry *) node;
RangeTblEntry *newrte;
FLATCOPY(newrte, rte, RangeTblEntry);
switch (rte->rtekind)
{
case RTE_RELATION: /* ordinary relation reference */
case RTE_VOID: /* deleted entry */
case RTE_RESULT:
case RTE_NAMEDTUPLESTORE:
/* No extras. */
break;
case RTE_SUBQUERY: /* subquery in FROM */
newrte->subquery = copyObject(rte->subquery);
break;
case RTE_CTE:
newrte->ctename = pstrdup(rte->ctename);
newrte->ctelevelsup = rte->ctelevelsup;
newrte->self_reference = rte->self_reference;
MUTATE(newrte->coltypes, rte->coltypes, List *);
MUTATE(newrte->coltypmods, rte->coltypmods, List *);
break;
case RTE_JOIN: /* join */
newrte->joinaliasvars = copyObject(rte->joinaliasvars);
break;
case RTE_FUNCTION: /* functions in FROM */
MUTATE(newrte->functions, rte->functions, List *);
break;
case RTE_TABLEFUNCTION:
newrte->subquery = copyObject(rte->subquery);
MUTATE(newrte->functions, rte->functions, List *);
break;
case RTE_TABLEFUNC:
newrte->tablefunc = copyObject(rte->tablefunc);
MUTATE(newrte->tablefunc, rte->tablefunc, TableFunc *);
break;
case RTE_VALUES:
MUTATE(newrte->values_lists, rte->values_lists, List *);
break;
}
return (Node *) newrte;
}
break;
case T_RangeTblFunction:
{
RangeTblFunction *rtfunc = (RangeTblFunction *) node;
RangeTblFunction *newrtfunc;
FLATCOPY(newrtfunc, rtfunc, RangeTblFunction);
MUTATE(newrtfunc->funcexpr, rtfunc->funcexpr, Node *);
/*
* TODO is this right? //newrte->coldeflist = (List *)
* copyObject(rte->coldeflist);
*/
}
break;
case T_ForeignScan:
{
ForeignScan *fdwscan = (ForeignScan *) node;
ForeignScan *newfdwscan;
FLATCOPY(newfdwscan, fdwscan, ForeignScan);
SCANMUTATE(newfdwscan, fdwscan);
MUTATE(newfdwscan->fdw_exprs, fdwscan->fdw_exprs, List *);
/*
* Don't mutate fdw_private, it's private to the FDW. Must make
* a copy of it, though.
*/
newfdwscan->fdw_private = copyObject(fdwscan->fdw_private);
newfdwscan->fsSystemCol = fdwscan->fsSystemCol;
return (Node *) newfdwscan;
}
break;
case T_SplitUpdate:
{
SplitUpdate *splitUpdate = (SplitUpdate *) node;
SplitUpdate *newSplitUpdate;
FLATCOPY(newSplitUpdate, splitUpdate, SplitUpdate);
PLANMUTATE(newSplitUpdate, splitUpdate);
return (Node *) newSplitUpdate;
}
break;
/*
* The following cases are handled by expression_tree_mutator. In
* addition, we let expression_tree_mutator handle unrecognized
* nodes.
*
* TODO: Identify node types that should never appear in plan
* trees and disallow them here by issuing an error or asserting
* false.
*/
case T_Var:
case T_Const:
case T_Param:
case T_CoerceToDomainValue:
case T_CaseTestExpr:
case T_SetToDefault:
case T_RangeTblRef:
case T_Aggref:
case T_WindowFunc:
case T_SubscriptingRef:
case T_FuncExpr:
case T_OpExpr:
case T_DistinctExpr:
case T_ScalarArrayOpExpr:
case T_BoolExpr:
case T_SubLink:
case T_FieldSelect:
case T_FieldStore:
case T_RelabelType:
case T_CaseExpr:
case T_CaseWhen:
case T_ArrayExpr:
case T_RowExpr:
case T_CoalesceExpr:
case T_NullIfExpr:
case T_NullTest:
case T_BooleanTest:
case T_CoerceToDomain:
case T_TargetEntry:
case T_List:
case T_FromExpr:
case T_JoinExpr:
case T_SetOperationStmt:
case T_SpecialJoinInfo:
default:
/*
* Let expression_tree_mutator handle remaining cases or complain
* of unrecognized node type.
*/
return expression_tree_mutator(node, mutator, context);
break;
}
/* can't get here, but keep compiler happy */
return NULL;
}
/* Function mutate_plan_fields() is a subroutine for plan_tree_mutator().
* It "hijacks" the macro MUTATE defined for use in that function, so don't
* change the argument names "mutator" and "context" use in the macro
* definition.
*
*/
static void
mutate_plan_fields(Plan *newplan, Plan *oldplan, Node *(*mutator) (), void *context)
{
/*
* Scalar fields startup_cost total_cost plan_rows plan_width nParamExec
* need no mutation.
*/
/* Node fields need mutation. */
MUTATE(newplan->targetlist, oldplan->targetlist, List *);
MUTATE(newplan->qual, oldplan->qual, List *);
MUTATE(newplan->lefttree, oldplan->lefttree, Plan *);
MUTATE(newplan->righttree, oldplan->righttree, Plan *);
MUTATE(newplan->initPlan, oldplan->initPlan, List *);
/* Bitmapsets aren't nodes but need to be copied to palloc'd space. */
newplan->extParam = bms_copy(oldplan->extParam);
newplan->allParam = bms_copy(oldplan->allParam);
}
/* Function mutate_plan_fields() is a subroutine for plan_tree_mutator().
* It "hijacks" the macro MUTATE defined for use in that function, so don't
* change the argument names "mutator" and "context" use in the macro
* definition.
*
*/
static void
mutate_join_fields(Join *newjoin, Join *oldjoin, Node *(*mutator) (), void *context)
{
/* A Join node is a Plan node. */
mutate_plan_fields((Plan *) newjoin, (Plan *) oldjoin, mutator, context);
/* Scalar field jointype needs no mutation. */
/* Node fields need mutation. */
MUTATE(newjoin->joinqual, oldjoin->joinqual, List *);
}
/* Utility to get a name for a function to use as an eref. */
static char *
get_function_name(Oid proid, const char *dflt)
{
char *result;
if (!OidIsValid(proid))
{
result = pstrdup(dflt);
}
else
{
result = get_func_name(proid);
if (result == NULL)
result = pstrdup(dflt);
}
return result;
}
/* Utility to get a name for a tle to use as an eref. */
Value *
get_tle_name(TargetEntry *tle, List *rtable, const char *default_name)
{
char *name = NULL;
Node *expr = (Node*)tle->expr;
if ( tle->resname != NULL )
{
name = pstrdup(tle->resname);
}
else if ( IsA(tle->expr, Var) && rtable != NULL )
{
Var *var = (Var*)tle->expr;
RangeTblEntry *rte = rt_fetch(var->varno, rtable);
name = pstrdup(get_rte_attribute_name(rte, var->varattno));
}
else if ( IsA(tle->expr, WindowFunc) )
{
if ( default_name == NULL ) default_name = "window_func";
name = get_function_name(((WindowFunc *)expr)->winfnoid, default_name);
}
else if ( IsA(tle->expr, Aggref) )
{
if ( default_name == NULL ) default_name = "aggregate_func";
name = get_function_name(((Aggref*)expr)->aggfnoid, default_name);
}
if ( name == NULL )
{
if (default_name == NULL ) default_name = "unnamed_attr";
name = pstrdup(default_name);
}
return makeString(name);
}
相关信息
相关文章
greenplumn cdbappendonlystorageformat 源码
greenplumn cdbappendonlystorageread 源码
greenplumn cdbappendonlystoragewrite 源码
greenplumn cdbappendonlyxlog 源码
greenplumn cdbbufferedappend 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦