greenplumn cdbplan 源码

  • 2022-08-18
  • 浏览 (328)

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 源码目录

相关文章

greenplumn cdbappendonlystorageformat 源码

greenplumn cdbappendonlystorageread 源码

greenplumn cdbappendonlystoragewrite 源码

greenplumn cdbappendonlyxlog 源码

greenplumn cdbbufferedappend 源码

greenplumn cdbbufferedread 源码

greenplumn cdbcat 源码

greenplumn cdbcopy 源码

greenplumn cdbdistributedsnapshot 源码

greenplumn cdbdistributedxacts 源码

0  赞