/*------------------------------------------------------------------------- * * copyfuncs.c-- * Copy functions for Postgres tree nodes. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.48 1998/09/01 04:29:00 momjian Exp $ * *------------------------------------------------------------------------- */ #include #include #include "postgres.h" #include "nodes/pg_list.h" #include "nodes/execnodes.h" #include "nodes/plannodes.h" #include "nodes/parsenodes.h" #include "nodes/primnodes.h" #include "nodes/relation.h" #include "utils/syscache.h" #include "utils/builtins.h" /* for namecpy */ #include "utils/elog.h" #include "utils/palloc.h" #include "catalog/pg_type.h" #include "storage/lmgr.h" /* * listCopy-- * this copy function only copies the "lcons-cells" of the list but not * its contents. (good for list of pointers as well as list of integers). */ List * listCopy(List *list) { List *newlist = NIL; List *l, *nl = NIL; foreach(l, list) { if (newlist == NIL) newlist = nl = lcons(lfirst(l), NIL); else { lnext(nl) = lcons(lfirst(l), NIL); nl = lnext(nl); } } return newlist; } /* * Node_Copy-- * a macro to simplify calling of copyObject on the specified field */ #define Node_Copy(from, newnode, field) \ newnode->field = copyObject(from->field) /* **************************************************************** * plannodes.h copy functions * **************************************************************** */ /* ---------------- * CopyPlanFields * * This function copies the fields of the Plan node. It is used by * all the copy functions for classes which inherit from Plan. * ---------------- */ static void CopyPlanFields(Plan *from, Plan *newnode) { extern List *SS_pull_subplan(void *expr); newnode->cost = from->cost; newnode->plan_size = from->plan_size; newnode->plan_width = from->plan_width; newnode->plan_tupperpage = from->plan_tupperpage; newnode->state = from->state; newnode->targetlist = copyObject(from->targetlist); newnode->qual = copyObject(from->qual); newnode->lefttree = copyObject(from->lefttree); newnode->righttree = copyObject(from->righttree); newnode->extParam = listCopy(from->extParam); newnode->locParam = listCopy(from->locParam); newnode->chgParam = listCopy(from->chgParam); Node_Copy(from, newnode, initPlan); if (from->subPlan != NULL) newnode->subPlan = SS_pull_subplan(newnode->qual); else newnode->subPlan = NULL; newnode->nParamExec = from->nParamExec; } /* ---------------- * _copyPlan * ---------------- */ static Plan * _copyPlan(Plan *from) { Plan *newnode = makeNode(Plan); /* ---------------- * copy the node superclass fields * ---------------- */ CopyPlanFields(from, newnode); return newnode; } /* ---------------- * _copyResult * ---------------- */ static Result * _copyResult(Result *from) { Result *newnode = makeNode(Result); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, resconstantqual); Node_Copy(from, newnode, resstate); return newnode; } /* ---------------- * _copyAppend * ---------------- */ static Append * _copyAppend(Append *from) { Append *newnode = makeNode(Append); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, appendplans); Node_Copy(from, newnode, unionrtables); newnode->inheritrelid = from->inheritrelid; Node_Copy(from, newnode, inheritrtable); Node_Copy(from, newnode, appendstate); return newnode; } /* ---------------- * CopyScanFields * * This function copies the fields of the Scan node. It is used by * all the copy functions for classes which inherit from Scan. * ---------------- */ static void CopyScanFields(Scan *from, Scan *newnode) { newnode->scanrelid = from->scanrelid; Node_Copy(from, newnode, scanstate); return; } /* ---------------- * _copyScan * ---------------- */ static Scan * _copyScan(Scan *from) { Scan *newnode = makeNode(Scan); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyScanFields((Scan *) from, (Scan *) newnode); return newnode; } /* ---------------- * _copySeqScan * ---------------- */ static SeqScan * _copySeqScan(SeqScan *from) { SeqScan *newnode = makeNode(SeqScan); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyScanFields((Scan *) from, (Scan *) newnode); return newnode; } /* ---------------- * _copyIndexScan * ---------------- */ static IndexScan * _copyIndexScan(IndexScan *from) { IndexScan *newnode = makeNode(IndexScan); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyScanFields((Scan *) from, (Scan *) newnode); /* ---------------- * copy remainder of node * ---------------- */ newnode->indxid = listCopy(from->indxid); Node_Copy(from, newnode, indxqual); Node_Copy(from, newnode, indxstate); return newnode; } /* ---------------- * CopyJoinFields * * This function copies the fields of the Join node. It is used by * all the copy functions for classes which inherit from Join. * ---------------- */ static void CopyJoinFields(Join *from, Join *newnode) { /* nothing extra */ return; } /* ---------------- * _copyJoin * ---------------- */ static Join * _copyJoin(Join *from) { Join *newnode = makeNode(Join); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyJoinFields(from, newnode); return newnode; } /* ---------------- * _copyNestLoop * ---------------- */ static NestLoop * _copyNestLoop(NestLoop *from) { NestLoop *newnode = makeNode(NestLoop); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyJoinFields((Join *) from, (Join *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, nlstate); return newnode; } /* ---------------- * _copyMergeJoin * ---------------- */ static MergeJoin * _copyMergeJoin(MergeJoin *from) { MergeJoin *newnode = makeNode(MergeJoin); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyJoinFields((Join *) from, (Join *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, mergeclauses); newnode->mergejoinop = from->mergejoinop; newnode->mergerightorder = (Oid *) palloc(sizeof(Oid) * 2); newnode->mergerightorder[0] = from->mergerightorder[0]; newnode->mergerightorder[1] = 0; newnode->mergeleftorder = (Oid *) palloc(sizeof(Oid) * 2); newnode->mergeleftorder[0] = from->mergeleftorder[0]; newnode->mergeleftorder[1] = 0; Node_Copy(from, newnode, mergestate); return newnode; } /* ---------------- * _copyHashJoin * ---------------- */ static HashJoin * _copyHashJoin(HashJoin *from) { HashJoin *newnode = makeNode(HashJoin); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyJoinFields((Join *) from, (Join *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, hashclauses); newnode->hashjoinop = from->hashjoinop; Node_Copy(from, newnode, hashjoinstate); newnode->hashjointable = from->hashjointable; newnode->hashjointablekey = from->hashjointablekey; newnode->hashjointablesize = from->hashjointablesize; newnode->hashdone = from->hashdone; return newnode; } /* ---------------- * CopyTempFields * * This function copies the fields of the Temp node. It is used by * all the copy functions for classes which inherit from Temp. * ---------------- */ static void CopyTempFields(Temp *from, Temp *newnode) { newnode->tempid = from->tempid; newnode->keycount = from->keycount; return; } /* ---------------- * _copyTemp * ---------------- */ static Temp * _copyTemp(Temp *from) { Temp *newnode = makeNode(Temp); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyTempFields(from, newnode); return newnode; } /* ---------------- * _copyMaterial * ---------------- */ static Material * _copyMaterial(Material *from) { Material *newnode = makeNode(Material); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyTempFields((Temp *) from, (Temp *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, matstate); return newnode; } /* ---------------- * _copySort * ---------------- */ static Sort * _copySort(Sort *from) { Sort *newnode = makeNode(Sort); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyTempFields((Temp *) from, (Temp *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, sortstate); Node_Copy(from, newnode, psortstate); newnode->cleaned = from->cleaned; return newnode; } /* ---------------- * _copyGroup * ---------------- */ static Group * _copyGroup(Group *from) { Group *newnode = makeNode(Group); CopyPlanFields((Plan *) from, (Plan *) newnode); newnode->tuplePerGroup = from->tuplePerGroup; newnode->numCols = from->numCols; newnode->grpColIdx = palloc(from->numCols * sizeof(AttrNumber)); memcpy(newnode->grpColIdx, from->grpColIdx, from->numCols * sizeof(AttrNumber)); Node_Copy(from, newnode, grpstate); return newnode; } /* --------------- * _copyAgg * -------------- */ static Agg * _copyAgg(Agg *from) { Agg *newnode = makeNode(Agg); CopyPlanFields((Plan *) from, (Plan *) newnode); Node_Copy(from, newnode, aggs); Node_Copy(from, newnode, aggstate); return newnode; } /* --------------- * _copyGroupClause * -------------- */ static GroupClause * _copyGroupClause(GroupClause *from) { GroupClause *newnode = makeNode(GroupClause); Node_Copy(from, newnode, entry); newnode->grpOpoid = from->grpOpoid; return newnode; } /* ---------------- * _copyUnique * ---------------- */ static Unique * _copyUnique(Unique *from) { Unique *newnode = makeNode(Unique); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); CopyTempFields((Temp *) from, (Temp *) newnode); /* ---------------- * copy remainder of node * ---------------- */ if (newnode->uniqueAttr) newnode->uniqueAttr = pstrdup(from->uniqueAttr); else newnode->uniqueAttr = NULL; newnode->uniqueAttrNum = from->uniqueAttrNum; Node_Copy(from, newnode, uniquestate); return newnode; } /* ---------------- * _copyHash * ---------------- */ static Hash * _copyHash(Hash *from) { Hash *newnode = makeNode(Hash); /* ---------------- * copy node superclass fields * ---------------- */ CopyPlanFields((Plan *) from, (Plan *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, hashkey); Node_Copy(from, newnode, hashstate); newnode->hashtable = from->hashtable; newnode->hashtablekey = from->hashtablekey; newnode->hashtablesize = from->hashtablesize; return newnode; } static SubPlan * _copySubPlan(SubPlan *from) { SubPlan *newnode = makeNode(SubPlan); Node_Copy(from, newnode, plan); newnode->plan_id = from->plan_id; Node_Copy(from, newnode, rtable); newnode->setParam = listCopy(from->setParam); newnode->parParam = listCopy(from->parParam); Node_Copy(from, newnode, sublink); newnode->shutdown = from->shutdown; return newnode; } /* **************************************************************** * primnodes.h copy functions * **************************************************************** */ /* ---------------- * _copyResdom * ---------------- */ static Resdom * _copyResdom(Resdom *from) { Resdom *newnode = makeNode(Resdom); newnode->resno = from->resno; newnode->restype = from->restype; newnode->restypmod = from->restypmod; if (from->resname != NULL) newnode->resname = pstrdup(from->resname); newnode->reskey = from->reskey; newnode->reskeyop = from->reskeyop; newnode->resjunk = from->resjunk; return newnode; } static Fjoin * _copyFjoin(Fjoin *from) { Fjoin *newnode = makeNode(Fjoin); /* ---------------- * copy node superclass fields * ---------------- */ newnode->fj_initialized = from->fj_initialized; newnode->fj_nNodes = from->fj_nNodes; Node_Copy(from, newnode, fj_innerNode); newnode->fj_results = (DatumPtr) palloc((from->fj_nNodes) * sizeof(Datum)); memmove(from->fj_results, newnode->fj_results, (from->fj_nNodes) * sizeof(Datum)); newnode->fj_alwaysDone = (BoolPtr) palloc((from->fj_nNodes) * sizeof(bool)); memmove(from->fj_alwaysDone, newnode->fj_alwaysDone, (from->fj_nNodes) * sizeof(bool)); return newnode; } /* ---------------- * _copyExpr * ---------------- */ static Expr * _copyExpr(Expr *from) { Expr *newnode = makeNode(Expr); /* ---------------- * copy node superclass fields * ---------------- */ newnode->typeOid = from->typeOid; newnode->opType = from->opType; Node_Copy(from, newnode, oper); Node_Copy(from, newnode, args); return newnode; } /* ---------------- * _copyVar * ---------------- */ static Var * _copyVar(Var *from) { Var *newnode = makeNode(Var); /* ---------------- * copy remainder of node * ---------------- */ newnode->varno = from->varno; newnode->varattno = from->varattno; newnode->vartype = from->vartype; newnode->vartypmod = from->vartypmod; newnode->varlevelsup = from->varlevelsup; newnode->varnoold = from->varnoold; newnode->varoattno = from->varoattno; return newnode; } /* ---------------- * _copyOper * ---------------- */ static Oper * _copyOper(Oper *from) { Oper *newnode = makeNode(Oper); /* ---------------- * copy remainder of node * ---------------- */ newnode->opno = from->opno; newnode->opid = from->opid; newnode->opresulttype = from->opresulttype; newnode->opsize = from->opsize; /* * NOTE: shall we copy the cache structure or just the pointer ? * Alternatively we can set 'op_fcache' to NULL, in which case the * executor will initialize it when it needs it... */ newnode->op_fcache = from->op_fcache; return newnode; } /* ---------------- * _copyConst * ---------------- */ static Const * _copyConst(Const *from) { static Oid cached_type; static bool cached_typbyval; Const *newnode = makeNode(Const); /* ---------------- * copy remainder of node * ---------------- */ newnode->consttype = from->consttype; newnode->constlen = from->constlen; /* ---------------- * XXX super cheesy hack until parser/planner * puts in the right values here. * * But I like cheese. * ---------------- */ if (!from->constisnull && cached_type != from->consttype) { HeapTuple typeTuple; Form_pg_type typeStruct; /* ---------------- * get the type tuple corresponding to the paramList->type, * If this fails, returnValue has been pre-initialized * to "null" so we just return it. * ---------------- */ typeTuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(from->consttype), 0, 0, 0); /* ---------------- * get the type length and by-value from the type tuple and * save the information in our one element cache. * ---------------- */ Assert(PointerIsValid(typeTuple)); typeStruct = (Form_pg_type) GETSTRUCT(typeTuple); cached_typbyval = (typeStruct)->typbyval ? true : false; cached_type = from->consttype; } from->constbyval = cached_typbyval; if (!from->constisnull) { /* ---------------- * copying the Datum in a const node is a bit trickier * because it might be a pointer and it might also be of * variable length... * ---------------- */ if (from->constbyval == true) { /* ---------------- * passed by value so just copy the datum. * ---------------- */ newnode->constvalue = from->constvalue; } else { /* ---------------- * not passed by value. datum contains a pointer. * ---------------- */ if (from->constlen != -1) { /* ---------------- * fixed length structure * ---------------- */ newnode->constvalue = PointerGetDatum(palloc(from->constlen)); memmove((char *) newnode->constvalue, (char *) from->constvalue, from->constlen); } else { /* ---------------- * variable length structure. here the length is stored * in the first int pointed to by the constval. * ---------------- */ int length; length = VARSIZE(from->constvalue); newnode->constvalue = PointerGetDatum(palloc(length)); memmove((char *) newnode->constvalue, (char *) from->constvalue, length); } } } else newnode->constvalue = from->constvalue; newnode->constisnull = from->constisnull; newnode->constbyval = from->constbyval; newnode->constisset = from->constisset; newnode->constiscast = from->constiscast; return newnode; } /* ---------------- * _copyParam * ---------------- */ static Param * _copyParam(Param *from) { Param *newnode = makeNode(Param); /* ---------------- * copy remainder of node * ---------------- */ newnode->paramkind = from->paramkind; newnode->paramid = from->paramid; if (from->paramname != NULL) newnode->paramname = pstrdup(from->paramname); newnode->paramtype = from->paramtype; Node_Copy(from, newnode, param_tlist); return newnode; } /* ---------------- * _copyFunc * ---------------- */ static Func * _copyFunc(Func *from) { Func *newnode = makeNode(Func); /* ---------------- * copy remainder of node * ---------------- */ newnode->funcid = from->funcid; newnode->functype = from->functype; newnode->funcisindex = from->funcisindex; newnode->funcsize = from->funcsize; newnode->func_fcache = from->func_fcache; Node_Copy(from, newnode, func_tlist); Node_Copy(from, newnode, func_planlist); return newnode; } /* ---------------- * _copyAggreg * ---------------- */ static Aggreg * _copyAggreg(Aggreg *from) { Aggreg *newnode = makeNode(Aggreg); /* ---------------- * copy remainder of node * ---------------- */ newnode->aggname = pstrdup(from->aggname); newnode->basetype = from->basetype; newnode->aggtype = from->aggtype; Node_Copy(from, newnode, target); newnode->aggno = from->aggno; newnode->usenulls = from->usenulls; return newnode; } /* ---------------- * _copySubLink * ---------------- */ static SubLink * _copySubLink(SubLink *from) { SubLink *newnode = makeNode(SubLink); /* ---------------- * copy remainder of node * ---------------- */ newnode->subLinkType = from->subLinkType; newnode->useor = from->useor; Node_Copy(from, newnode, lefthand); Node_Copy(from, newnode, oper); Node_Copy(from, newnode, subselect); return newnode; } static Array * _copyArray(Array *from) { Array *newnode = makeNode(Array); /* ---------------- * copy remainder of node * ---------------- */ newnode->arrayelemtype = from->arrayelemtype; newnode->arrayelemlength = from->arrayelemlength; newnode->arrayelembyval = from->arrayelembyval; newnode->arrayndim = from->arrayndim; newnode->arraylow = from->arraylow; newnode->arrayhigh = from->arrayhigh; newnode->arraylen = from->arraylen; return newnode; } static ArrayRef * _copyArrayRef(ArrayRef *from) { ArrayRef *newnode = makeNode(ArrayRef); /* ---------------- * copy remainder of node * ---------------- */ newnode->refattrlength = from->refattrlength; newnode->refelemlength = from->refelemlength; newnode->refelemtype = from->refelemtype; newnode->refelembyval = from->refelembyval; Node_Copy(from, newnode, refupperindexpr); Node_Copy(from, newnode, reflowerindexpr); Node_Copy(from, newnode, refexpr); Node_Copy(from, newnode, refassgnexpr); return newnode; } /* **************************************************************** * relation.h copy functions * **************************************************************** */ /* ---------------- * _copyRelOptInfo * ---------------- */ /* ** when you change this, also make sure to fix up xfunc_copyRelOptInfo in ** planner/path/xfunc.c accordingly!!! ** -- JMH, 8/2/93 */ static RelOptInfo * _copyRelOptInfo(RelOptInfo * from) { RelOptInfo *newnode = makeNode(RelOptInfo); int i, len; /* ---------------- * copy remainder of node * ---------------- */ newnode->relids = listCopy(from->relids); newnode->indexed = from->indexed; newnode->pages = from->pages; newnode->tuples = from->tuples; newnode->size = from->size; newnode->width = from->width; Node_Copy(from, newnode, targetlist); Node_Copy(from, newnode, pathlist); Node_Copy(from, newnode, unorderedpath); Node_Copy(from, newnode, cheapestpath); newnode->pruneable = from->pruneable; if (from->classlist) { for (len = 0; from->classlist[len] != 0; len++) ; newnode->classlist = (Oid *) palloc(sizeof(Oid) * (len + 1)); for (i = 0; i < len; i++) newnode->classlist[i] = from->classlist[i]; newnode->classlist[len] = 0; } if (from->indexkeys) { for (len = 0; from->indexkeys[len] != 0; len++) ; newnode->indexkeys = (int *) palloc(sizeof(int) * (len + 1)); for (i = 0; i < len; i++) newnode->indexkeys[i] = from->indexkeys[i]; newnode->indexkeys[len] = 0; } newnode->relam = from->relam; newnode->indproc = from->indproc; Node_Copy(from, newnode, indpred); if (from->ordering) { for (len = 0; from->ordering[len] != 0; len++) ; newnode->ordering = (Oid *) palloc(sizeof(Oid) * (len + 1)); for (i = 0; i < len; i++) newnode->ordering[i] = from->ordering[i]; newnode->ordering[len] = 0; } Node_Copy(from, newnode, clauseinfo); Node_Copy(from, newnode, joininfo); Node_Copy(from, newnode, innerjoin); Node_Copy(from, newnode, superrels); return newnode; } /* ---------------- * CopyPathFields * * This function copies the fields of the Path node. It is used by * all the copy functions for classes which inherit from Path. * ---------------- */ static void CopyPathFields(Path *from, Path *newnode) { newnode->pathtype = from->pathtype; /* * Modify the next line, since it causes the copying to cycle (i.e. * the parent points right back here! -- JMH, 7/7/92. Old version: * Node_Copy(from, newnode, parent); */ newnode->parent = from->parent; newnode->path_cost = from->path_cost; newnode->p_ordering.ordtype = from->p_ordering.ordtype; if (from->p_ordering.ordtype == SORTOP_ORDER) { int len, i; Oid *ordering = from->p_ordering.ord.sortop; if (ordering) { for (len = 0; ordering[len] != 0; len++) ; newnode->p_ordering.ord.sortop = (Oid *) palloc(sizeof(Oid) * (len + 1)); for (i = 0; i < len; i++) newnode->p_ordering.ord.sortop[i] = ordering[i]; newnode->p_ordering.ord.sortop[len] = 0; } } else Node_Copy(from, newnode, p_ordering.ord.merge); Node_Copy(from, newnode, keys); newnode->outerjoincost = from->outerjoincost; newnode->joinid = listCopy(from->joinid); Node_Copy(from, newnode, locclauseinfo); } /* ---------------- * _copyPath * ---------------- */ static Path * _copyPath(Path *from) { Path *newnode = makeNode(Path); CopyPathFields(from, newnode); return newnode; } /* ---------------- * _copyIndexPath * ---------------- */ static IndexPath * _copyIndexPath(IndexPath *from) { IndexPath *newnode = makeNode(IndexPath); /* ---------------- * copy the node superclass fields * ---------------- */ CopyPathFields((Path *) from, (Path *) newnode); /* ---------------- * copy remainder of node * ---------------- */ newnode->indexid = listCopy(from->indexid); Node_Copy(from, newnode, indexqual); if (from->indexkeys) { int i, len; for (len = 0; from->indexkeys[len] != 0; len++) ; newnode->indexkeys = (int *) palloc(sizeof(int) * (len + 1)); for (i = 0; i < len; i++) newnode->indexkeys[i] = from->indexkeys[i]; newnode->indexkeys[len] = 0; } return newnode; } /* ---------------- * CopyJoinPathFields * * This function copies the fields of the JoinPath node. It is used by * all the copy functions for classes which inherit from JoinPath. * ---------------- */ static void CopyJoinPathFields(JoinPath *from, JoinPath *newnode) { Node_Copy(from, newnode, pathclauseinfo); Node_Copy(from, newnode, outerjoinpath); Node_Copy(from, newnode, innerjoinpath); } /* ---------------- * _copyJoinPath * ---------------- */ static JoinPath * _copyJoinPath(JoinPath *from) { JoinPath *newnode = makeNode(JoinPath); /* ---------------- * copy the node superclass fields * ---------------- */ CopyPathFields((Path *) from, (Path *) newnode); CopyJoinPathFields(from, newnode); return newnode; } /* ---------------- * _copyMergePath * ---------------- */ static MergePath * _copyMergePath(MergePath *from) { MergePath *newnode = makeNode(MergePath); /* ---------------- * copy the node superclass fields * ---------------- */ CopyPathFields((Path *) from, (Path *) newnode); CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode); /* ---------------- * copy the remainder of the node * ---------------- */ Node_Copy(from, newnode, path_mergeclauses); Node_Copy(from, newnode, outersortkeys); Node_Copy(from, newnode, innersortkeys); return newnode; } /* ---------------- * _copyHashPath * ---------------- */ static HashPath * _copyHashPath(HashPath *from) { HashPath *newnode = makeNode(HashPath); /* ---------------- * copy the node superclass fields * ---------------- */ CopyPathFields((Path *) from, (Path *) newnode); CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, path_hashclauses); Node_Copy(from, newnode, outerhashkeys); Node_Copy(from, newnode, innerhashkeys); return newnode; } /* ---------------- * _copyOrderKey * ---------------- */ static OrderKey * _copyOrderKey(OrderKey *from) { OrderKey *newnode = makeNode(OrderKey); /* ---------------- * copy remainder of node * ---------------- */ newnode->attribute_number = from->attribute_number; newnode->array_index = from->array_index; return newnode; } /* ---------------- * _copyJoinKey * ---------------- */ static JoinKey * _copyJoinKey(JoinKey *from) { JoinKey *newnode = makeNode(JoinKey); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, outer); Node_Copy(from, newnode, inner); return newnode; } /* ---------------- * _copyMergeOrder * ---------------- */ static MergeOrder * _copyMergeOrder(MergeOrder *from) { MergeOrder *newnode = makeNode(MergeOrder); /* ---------------- * copy remainder of node * ---------------- */ newnode->join_operator = from->join_operator; newnode->left_operator = from->left_operator; newnode->right_operator = from->right_operator; newnode->left_type = from->left_type; newnode->right_type = from->right_type; return newnode; } /* ---------------- * _copyClauseInfo * ---------------- */ static ClauseInfo * _copyClauseInfo(ClauseInfo * from) { ClauseInfo *newnode = makeNode(ClauseInfo); /* ---------------- * copy remainder of node * ---------------- */ Node_Copy(from, newnode, clause); newnode->selectivity = from->selectivity; newnode->notclause = from->notclause; Node_Copy(from, newnode, indexids); Node_Copy(from, newnode, mergejoinorder); newnode->hashjoinoperator = from->hashjoinoperator; newnode->cinfojoinid = listCopy(from->cinfojoinid); return newnode; } /* ---------------- * CopyJoinMethodFields * * This function copies the fields of the JoinMethod node. It is used by * all the copy functions for classes which inherit from JoinMethod. * ---------------- */ static void CopyJoinMethodFields(JoinMethod *from, JoinMethod *newnode) { Node_Copy(from, newnode, jmkeys); Node_Copy(from, newnode, clauses); return; } /* ---------------- * _copyJoinMethod * ---------------- */ static JoinMethod * _copyJoinMethod(JoinMethod *from) { JoinMethod *newnode = makeNode(JoinMethod); CopyJoinMethodFields(from, newnode); return newnode; } /* ---------------- * _copyHInfo * ---------------- */ static HInfo * _copyHInfo(HInfo *from) { HInfo *newnode = makeNode(HInfo); /* ---------------- * copy remainder of node * ---------------- */ CopyJoinMethodFields((JoinMethod *) from, (JoinMethod *) newnode); newnode->hashop = from->hashop; return newnode; } /* ---------------- * _copyMInfo * ---------------- */ static MInfo * _copyMInfo(MInfo *from) { MInfo *newnode = makeNode(MInfo); /* ---------------- * copy remainder of node * ---------------- */ CopyJoinMethodFields((JoinMethod *) from, (JoinMethod *) newnode); Node_Copy(from, newnode, m_ordering); return newnode; } /* ---------------- * _copyJoinInfo * ---------------- */ static JoinInfo * _copyJoinInfo(JoinInfo * from) { JoinInfo *newnode = makeNode(JoinInfo); /* ---------------- * copy remainder of node * ---------------- */ newnode->otherrels = listCopy(from->otherrels); Node_Copy(from, newnode, jinfoclauseinfo); newnode->mergejoinable = from->mergejoinable; newnode->hashjoinable = from->hashjoinable; newnode->inactive = from->inactive; return newnode; } static Iter * _copyIter(Iter *from) { Iter *newnode = makeNode(Iter); Node_Copy(from, newnode, iterexpr); newnode->itertype = from->itertype; return newnode; } static Stream * _copyStream(Stream *from) { Stream *newnode = makeNode(Stream); newnode->pathptr = from->pathptr; newnode->cinfo = from->cinfo; newnode->clausetype = from->clausetype; newnode->upstream = (StreamPtr) NULL; /* only copy nodes * downwards! */ Node_Copy(from, newnode, downstream); if (newnode->downstream) ((Stream *) newnode->downstream)->upstream = (Stream *) newnode; newnode->groupup = from->groupup; newnode->groupcost = from->groupcost; newnode->groupsel = from->groupsel; return newnode; } /* **************** * parsenodes.h routines have no copy functions * **************** */ static TargetEntry * _copyTargetEntry(TargetEntry *from) { TargetEntry *newnode = makeNode(TargetEntry); Node_Copy(from, newnode, resdom); Node_Copy(from, newnode, fjoin); Node_Copy(from, newnode, expr); return newnode; } static RangeTblEntry * _copyRangeTblEntry(RangeTblEntry *from) { RangeTblEntry *newnode = makeNode(RangeTblEntry); if (from->relname) newnode->relname = pstrdup(from->relname); if (from->refname) newnode->refname = pstrdup(from->refname); newnode->relid = from->relid; newnode->inh = from->inh; newnode->inFromCl = from->inFromCl; newnode->skipAcl = from->skipAcl; return newnode; } static SortClause * _copySortClause(SortClause *from) { SortClause *newnode = makeNode(SortClause); Node_Copy(from, newnode, resdom); newnode->opoid = from->opoid; return newnode; } static A_Const * _copyAConst(A_Const *from) { A_Const *newnode = makeNode(A_Const); newnode->val = *((Value *) (copyObject(&(from->val)))); Node_Copy(from, newnode, typename); return newnode; } static TypeName * _copyTypeName(TypeName *from) { TypeName *newnode = makeNode(TypeName); if (from->name) newnode->name = pstrdup(from->name); newnode->timezone = from->timezone; newnode->setof = from->setof; newnode->typmod = from->typmod; Node_Copy(from, newnode, arrayBounds); return newnode; } static Query * _copyQuery(Query *from) { Query *newnode = makeNode(Query); newnode->commandType = from->commandType; if (from->utilityStmt && nodeTag(from->utilityStmt) == T_NotifyStmt) { NotifyStmt *from_notify = (NotifyStmt *) from->utilityStmt; NotifyStmt *n = makeNode(NotifyStmt); n->relname = pstrdup(from_notify->relname); newnode->utilityStmt = (Node *) n; } newnode->resultRelation = from->resultRelation; if (from->into) newnode->into = pstrdup(from->into); newnode->isPortal = from->isPortal; newnode->isBinary = from->isBinary; newnode->unionall = from->unionall; if (from->uniqueFlag) newnode->uniqueFlag = pstrdup(from->uniqueFlag); Node_Copy(from, newnode, sortClause); Node_Copy(from, newnode, rtable); Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, qual); Node_Copy(from, newnode, groupClause); Node_Copy(from, newnode, havingQual); newnode->hasAggs = from->hasAggs; newnode->hasSubLinks = from->hasSubLinks; if (from->unionClause) { List *ulist, *temp_list = NIL; foreach(ulist, from->unionClause) temp_list = lappend(temp_list, copyObject(lfirst(ulist))); newnode->unionClause = temp_list; } return newnode; } /* **************** * mnodes.h routines have no copy functions * **************** */ /* **************************************************************** * pg_list.h copy functions * **************************************************************** */ static Value * _copyValue(Value *from) { Value *newnode = makeNode(Value); newnode->type = from->type; switch (from->type) { case T_String: newnode->val.str = pstrdup(from->val.str); break; case T_Integer: newnode->val.ival = from->val.ival; break; case T_Float: newnode->val.dval = from->val.dval; break; default: break; } return newnode; } /* ---------------- * copyObject returns a copy of the node or list. If it is a list, it * recursively copies its items. * ---------------- */ void * copyObject(void *from) { void *retval; if (from == NULL) return NULL; switch (nodeTag(from)) { /* * PLAN NODES */ case T_Plan: retval = _copyPlan(from); break; case T_Result: retval = _copyResult(from); break; case T_Append: retval = _copyAppend(from); break; case T_Scan: retval = _copyScan(from); break; case T_SeqScan: retval = _copySeqScan(from); break; case T_IndexScan: retval = _copyIndexScan(from); break; case T_Join: retval = _copyJoin(from); break; case T_NestLoop: retval = _copyNestLoop(from); break; case T_MergeJoin: retval = _copyMergeJoin(from); break; case T_HashJoin: retval = _copyHashJoin(from); break; case T_Temp: retval = _copyTemp(from); break; case T_Material: retval = _copyMaterial(from); break; case T_Sort: retval = _copySort(from); break; case T_Group: retval = _copyGroup(from); break; case T_Agg: retval = _copyAgg(from); break; case T_GroupClause: retval = _copyGroupClause(from); break; case T_Unique: retval = _copyUnique(from); break; case T_Hash: retval = _copyHash(from); break; case T_SubPlan: retval = _copySubPlan(from); break; /* * PRIMITIVE NODES */ case T_Resdom: retval = _copyResdom(from); break; case T_Fjoin: retval = _copyFjoin(from); break; case T_Expr: retval = _copyExpr(from); break; case T_Var: retval = _copyVar(from); break; case T_Oper: retval = _copyOper(from); break; case T_Const: retval = _copyConst(from); break; case T_Param: retval = _copyParam(from); break; case T_Func: retval = _copyFunc(from); break; case T_Array: retval = _copyArray(from); break; case T_ArrayRef: retval = _copyArrayRef(from); break; case T_Aggreg: retval = _copyAggreg(from); break; case T_SubLink: retval = _copySubLink(from); break; /* * RELATION NODES */ case T_RelOptInfo: retval = _copyRelOptInfo(from); break; case T_Path: retval = _copyPath(from); break; case T_IndexPath: retval = _copyIndexPath(from); break; case T_JoinPath: retval = _copyJoinPath(from); break; case T_MergePath: retval = _copyMergePath(from); break; case T_HashPath: retval = _copyHashPath(from); break; case T_OrderKey: retval = _copyOrderKey(from); break; case T_JoinKey: retval = _copyJoinKey(from); break; case T_MergeOrder: retval = _copyMergeOrder(from); break; case T_ClauseInfo: retval = _copyClauseInfo(from); break; case T_JoinMethod: retval = _copyJoinMethod(from); break; case T_HInfo: retval = _copyHInfo(from); break; case T_MInfo: retval = _copyMInfo(from); break; case T_JoinInfo: retval = _copyJoinInfo(from); break; case T_Iter: retval = _copyIter(from); break; case T_Stream: retval = _copyStream(from); break; /* * PARSE NODES */ case T_Query: retval = _copyQuery(from); break; case T_TargetEntry: retval = _copyTargetEntry(from); break; case T_RangeTblEntry: retval = _copyRangeTblEntry(from); break; case T_SortClause: retval = _copySortClause(from); break; case T_A_Const: retval = _copyAConst(from); break; case T_TypeName: retval = _copyTypeName(from); break; /* * VALUE NODES */ case T_Integer: case T_String: case T_Float: retval = _copyValue(from); break; case T_List: { List *list = from, *l; List *newlist = NIL, *nl = NIL; foreach(l, list) { if (newlist == NIL) newlist = nl = lcons(copyObject(lfirst(l)), NIL); else { lnext(nl) = lcons(copyObject(lfirst(l)), NIL); nl = lnext(nl); } } retval = newlist; } break; default: elog(NOTICE, "copyObject: don't know how to copy %d", nodeTag(from)); retval = from; break; } return retval; }