blob: 31152c81bef281c3c5460b19a65c4f789831ae37 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*-------------------------------------------------------------------------
*
* cdbplan.c
* Provides routines supporting plan tree manipulation.
*
* NOTES
* See src/backend/optimizer/util/clauses.c for background information
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "nodes/primnodes.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "cdb/cdbplan.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)
{
/*
* 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");
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_Repeat:
{
Repeat *repeat = (Repeat *) node;
Repeat *newrepeat;
FLATCOPY(newrepeat, repeat, Repeat);
PLANMUTATE(newrepeat, repeat);
return (Node *)newrepeat;
}
break;
case T_Append:
{
Append *append = (Append *) node;
Append *newappend;
FLATCOPY(newappend, append, Append);
PLANMUTATE(newappend, append);
MUTATE(newappend->appendplans, append->appendplans, List *);
/* isTarget is scalar. */
return (Node *) newappend;
}
break;
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);
MUTATE(newPartsel->levelEqExpressions, partsel->levelEqExpressions, List *);
MUTATE(newPartsel->levelExpressions, partsel->levelExpressions, List *);
MUTATE(newPartsel->residualPredicate, partsel->residualPredicate, Node *);
MUTATE(newPartsel->propagationExpression, partsel->propagationExpression, Node *);
MUTATE(newPartsel->printablePredicate, partsel->printablePredicate, Node *);
MUTATE(newPartsel->staticPartOids, partsel->staticPartOids, List *);
MUTATE(newPartsel->staticScanIds, partsel->staticScanIds, List *);
newPartsel->nLevels = partsel->nLevels;
newPartsel->scanId = partsel->scanId;
newPartsel->selectorId = partsel->selectorId;
newPartsel->relid = partsel->relid;
newPartsel->staticSelection = partsel->staticSelection;
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");
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_AppendOnlyScan:
{
AppendOnlyScan *appendonlyscan = (AppendOnlyScan *) node;
AppendOnlyScan *newappendonlyscan;
FLATCOPY(newappendonlyscan, appendonlyscan, AppendOnlyScan);
SCANMUTATE(newappendonlyscan, appendonlyscan);
/* (for now) A AppendOnlyScan is really just a Scan, so we're done. */
return (Node *) newappendonlyscan;
}
break;
case T_ParquetScan:
{
ParquetScan *parquet = (ParquetScan *) node;
ParquetScan *newparquet;
FLATCOPY(newparquet, parquet, ParquetScan);
SCANMUTATE(newparquet, parquet);
/* (for now) A ParquetScan is really just a Scan, so we're done. */
return (Node *) newparquet;
}
break;
case T_TableScan:
{
TableScan *tableScan = (TableScan *) node;
TableScan *newTableScan = NULL;
FLATCOPY(newTableScan, tableScan, TableScan);
SCANMUTATE(newTableScan, tableScan);
return (Node *) newTableScan;
}
break;
case T_DynamicTableScan:
{
DynamicTableScan *tableScan = (DynamicTableScan *) node;
DynamicTableScan *newTableScan = NULL;
FLATCOPY(newTableScan, tableScan, DynamicTableScan);
SCANMUTATE(newTableScan, tableScan);
newTableScan->partIndex = tableScan->partIndex;
newTableScan->partIndexPrintable = tableScan->partIndexPrintable;
return (Node *) newTableScan;
}
break;
case T_ExternalScan:
{
ExternalScan *extscan = (ExternalScan *) node;
ExternalScan *newextscan;
FLATCOPY(newextscan, extscan, ExternalScan);
SCANMUTATE(newextscan, extscan);
MUTATE(newextscan->uriList, extscan->uriList, List *);
MUTATE(newextscan->fmtOpts, extscan->fmtOpts, List *);
newextscan->fmtType = extscan->fmtType;
newextscan->isMasterOnly = extscan->isMasterOnly;
return (Node *) newextscan;
}
break;
case T_IndexScan:
{
IndexScan *idxscan = (IndexScan *) node;
IndexScan *newidxscan;
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 *);
MUTATE(newidxscan->indexstrategy, idxscan->indexstrategy, List *);
MUTATE(newidxscan->indexsubtype, idxscan->indexsubtype, List *);
/* indxorderdir is scalar */
return (Node *) newidxscan;
}
break;
case T_BitmapIndexScan:
{
BitmapIndexScan *idxscan = (BitmapIndexScan *) node;
BitmapIndexScan *newidxscan;
FLATCOPY(newidxscan, idxscan, BitmapIndexScan);
SCANMUTATE(newidxscan, idxscan);
newidxscan->indexid = idxscan->indexid;
MUTATE(newidxscan->indexqual, idxscan->indexqual, List *);
MUTATE(newidxscan->indexqualorig, idxscan->indexqualorig, List *);
MUTATE(newidxscan->indexstrategy, idxscan->indexstrategy, List *);
MUTATE(newidxscan->indexsubtype, idxscan->indexsubtype, List *);
return (Node *) newidxscan;
}
break;
case T_BitmapHeapScan:
{
BitmapHeapScan *bmheapscan = (BitmapHeapScan *) node;
BitmapHeapScan *newbmheapscan;
FLATCOPY(newbmheapscan, bmheapscan, BitmapHeapScan);
SCANMUTATE(newbmheapscan, bmheapscan);
MUTATE(newbmheapscan->bitmapqualorig, bmheapscan->bitmapqualorig, List *);
return (Node *) newbmheapscan;
}
break;
case T_BitmapTableScan:
{
BitmapTableScan *bmtablescan = (BitmapTableScan *) node;
BitmapTableScan *newbmtablescan = NULL;
FLATCOPY(newbmtablescan, bmtablescan, BitmapTableScan);
SCANMUTATE(newbmtablescan, bmtablescan);
MUTATE(newbmtablescan->bitmapqualorig, bmtablescan->bitmapqualorig, List *);
return (Node *) newbmtablescan;
}
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);
SCANMUTATE(newscan, scan);
return (Node *) newscan;
}
break;
case T_Join:
/* Abstract: Should see only subclasses. */
elog(ERROR, "abstract node type not allowed: T_Join");
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);
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_TableFunctionScan:
{
TableFunctionScan *tabfunc = (TableFunctionScan *) node;
TableFunctionScan *newtabfunc;
FLATCOPY(newtabfunc, tabfunc, TableFunctionScan);
PLANMUTATE(newtabfunc, tabfunc);
return (Node *) newtabfunc;
}
break;
case T_Window:
{
Window *window = (Window *) node;
Window *newwindow;
FLATCOPY(newwindow, window, Window);
PLANMUTATE(newwindow, window);
COPYARRAY(newwindow, window, numPartCols, partColIdx);
MUTATE(newwindow->windowKeys, window->windowKeys, List *);
return (Node *) newwindow;
}
break;
case T_WindowKey:
{
WindowKey *key = (WindowKey *)node;
WindowKey *newkey;
FLATCOPY(newkey, key, WindowKey);
COPYARRAY(newkey, key, numSortCols, sortColIdx);
COPYARRAY(newkey, key, numSortCols, sortOperators);
MUTATE(newkey->frame, key->frame, WindowFrame *);
return (Node *) newkey;
}
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_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->hashExpr, motion->hashExpr, List *);
MUTATE(newmotion->hashDataTypes, motion->hashDataTypes, List *);
COPYARRAY(newmotion, motion, numOutputSegs, outputSegIdx);
COPYARRAY(newmotion, motion, numSortCols, sortColIdx);
COPYARRAY(newmotion, motion, numSortCols, sortOperators);
return (Node *) newmotion;
}
break;
case T_Flow:
{
Flow *flow = (Flow *) node;
Flow *newflow;
FLATCOPY(newflow, flow, Flow);
MUTATE(newflow->hashExpr, flow->hashExpr, List *);
COPYARRAY(newflow, flow, numSortCols, sortColIdx);
COPYARRAY(newflow, flow, numSortCols, sortOperators);
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;
Plan *subplan_plan = plan_tree_base_subplan_get_plan(context, subplan);
SubPlan *newnode;
Plan *newsubplan_plan;
FLATCOPY(newnode, subplan, SubPlan);
MUTATE(newnode->testexpr, subplan->testexpr, Node *);
MUTATE(newsubplan_plan, subplan_plan, Plan *);
MUTATE(newnode->args, subplan->args, List *);
/* 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);
if (newsubplan_plan != subplan_plan)
plan_tree_base_subplan_put_plan(context, newnode, newsubplan_plan);
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_SPECIAL: /* special rule relation (NEW or OLD) */
case RTE_VOID: /* deleted entry */
/* 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->ctecoltypes, rte->ctecoltypes, List *);
MUTATE(newrte->ctecoltypmods, rte->ctecoltypmods, List *);
break;
case RTE_JOIN: /* join */
newrte->joinaliasvars = copyObject(rte->joinaliasvars);
break;
case RTE_FUNCTION: /* function in FROM */
MUTATE(newrte->funcexpr, rte->funcexpr, Node *);
// TODO is this right? //newrte->coldeflist = (List *) copyObject(rte->coldeflist);
break;
case RTE_TABLEFUNCTION:
newrte->subquery = copyObject(rte->subquery);
MUTATE(newrte->funcexpr, rte->funcexpr, Node *);
break;
case RTE_VALUES:
MUTATE(newrte->values_lists, rte->values_lists, List *);
break;
}
return (Node *) newrte;
}
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_AggOrder:
case T_WindowRef:
case T_WindowFrame:
case T_WindowFrameEdge:
case T_ArrayRef:
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_InClauseInfo:
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.
*
*/
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.
*
*/
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 *);
}
/*
* set_hasxslice_in_append_walker -- set hasXslice field in Append nodes by
* walking the tree.
*
* If the subnodes of the Append node contain cross-slice shared node, and
* one of these subnodes running in the same slice as the Append node,
* the hasXslice is set to true. Otherwise, hasXslice is set to false.
*/
bool
set_hasxslice_in_append_walker(Node *node, void *ctx)
{
XsliceInAppendContext *context = (XsliceInAppendContext *)ctx;
if (node == NULL)
return false;
switch(nodeTag(node))
{
case T_Append:
{
walk_plan_node_fields((Plan *) node, set_hasxslice_in_append_walker, ctx);
set_hasxslice_in_append_walker((Node *) ((Append *) node)->appendplans, context);
((Append *)node)->hasXslice =
bms_is_member(context->currentSliceNo, context->slices);
return false;
}
case T_Sequence:
{
walk_plan_node_fields((Plan *) node, set_hasxslice_in_append_walker, ctx);
set_hasxslice_in_append_walker((Node *) ((Sequence *) node)->subplans, context);
return false;
}
case T_Motion:
{
/* Save the currentSliceNo */
int currentSliceNo = context->currentSliceNo;
context->currentSliceNo = ((Motion *)node)->motionID;
walk_plan_node_fields((Plan *) node, set_hasxslice_in_append_walker, ctx);
/* Reset the currentSliceNo */
context->currentSliceNo = currentSliceNo;
return false;
}
case T_ShareInputScan:
{
if (((ShareInputScan *)node)->share_type == SHARE_MATERIAL_XSLICE ||
((ShareInputScan *)node)->share_type == SHARE_SORT_XSLICE)
{
context->slices = bms_add_member(context->slices, context->currentSliceNo);
}
walk_plan_node_fields((Plan *) node, set_hasxslice_in_append_walker, context);
return false;
}
default:
return plan_tree_walker(node, set_hasxslice_in_append_walker, ctx);
}
}