mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
optimizer rather than parser. This has many advantages, such as not getting fooled by chance uses of operator names ~ and ~~ (the operators are identified by OID now), and not creating useless comparison operations in contexts where the comparisons will not actually be used as indexquals. The new code also recognizes exact-match LIKE and regex patterns, and produces an = indexqual instead of >= and <=. This change does NOT fix the problem with non-ASCII locales: the code still doesn't know how to generate an upper bound indexqual for non-ASCII collation order. But it's no worse than before, just the same deficiency in a different place... Also, dike out loc_restrictinfo fields in Plan nodes. These were doing nothing useful in the absence of 'expensive functions' optimization, and they took a considerable amount of processing to fill in.
1849 lines
37 KiB
C
1849 lines
37 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* 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.89 1999/07/27 03:51:07 tgl Exp $
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "catalog/pg_type.h"
|
|
#include "optimizer/planmain.h"
|
|
#include "optimizer/subselect.h"
|
|
#include "utils/syscache.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)
|
|
{
|
|
newnode->cost = from->cost;
|
|
newnode->plan_size = from->plan_size;
|
|
newnode->plan_width = from->plan_width;
|
|
newnode->plan_tupperpage = from->plan_tupperpage;
|
|
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((Node *) 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);
|
|
|
|
/*
|
|
* We must add subplans in resconstantqual to the new plan's subPlan
|
|
* list
|
|
*/
|
|
newnode->plan.subPlan = nconc(newnode->plan.subPlan,
|
|
SS_pull_subplan(newnode->resconstantqual));
|
|
|
|
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);
|
|
|
|
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;
|
|
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, indxqualorig);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
return newnode;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* CopyNonameFields
|
|
*
|
|
* This function copies the fields of the Noname node. It is used by
|
|
* all the copy functions for classes which inherit from Noname.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
CopyNonameFields(Noname *from, Noname *newnode)
|
|
{
|
|
newnode->nonameid = from->nonameid;
|
|
newnode->keycount = from->keycount;
|
|
return;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _copyNoname
|
|
* ----------------
|
|
*/
|
|
static Noname *
|
|
_copyNoname(Noname *from)
|
|
{
|
|
Noname *newnode = makeNode(Noname);
|
|
|
|
/* ----------------
|
|
* copy node superclass fields
|
|
* ----------------
|
|
*/
|
|
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
|
CopyNonameFields(from, newnode);
|
|
|
|
return newnode;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyMaterial
|
|
* ----------------
|
|
*/
|
|
static Material *
|
|
_copyMaterial(Material *from)
|
|
{
|
|
Material *newnode = makeNode(Material);
|
|
|
|
/* ----------------
|
|
* copy node superclass fields
|
|
* ----------------
|
|
*/
|
|
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
|
CopyNonameFields((Noname *) from, (Noname *) newnode);
|
|
|
|
return newnode;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _copySort
|
|
* ----------------
|
|
*/
|
|
static Sort *
|
|
_copySort(Sort *from)
|
|
{
|
|
Sort *newnode = makeNode(Sort);
|
|
|
|
/* ----------------
|
|
* copy node superclass fields
|
|
* ----------------
|
|
*/
|
|
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
|
CopyNonameFields((Noname *) from, (Noname *) newnode);
|
|
|
|
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));
|
|
|
|
return newnode;
|
|
}
|
|
|
|
/* ---------------
|
|
* _copyAgg
|
|
* --------------
|
|
*/
|
|
static Agg *
|
|
_copyAgg(Agg *from)
|
|
{
|
|
Agg *newnode = makeNode(Agg);
|
|
|
|
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
|
|
|
/*
|
|
* Cannot copy agg list; it must be rebuilt to point to subnodes of
|
|
* new node.
|
|
*/
|
|
set_agg_tlist_references(newnode);
|
|
|
|
return newnode;
|
|
}
|
|
|
|
/* ---------------
|
|
* _copyGroupClause
|
|
* --------------
|
|
*/
|
|
static GroupClause *
|
|
_copyGroupClause(GroupClause *from)
|
|
{
|
|
GroupClause *newnode = makeNode(GroupClause);
|
|
|
|
newnode->grpOpoid = from->grpOpoid;
|
|
newnode->tleGroupref = from->tleGroupref;
|
|
|
|
return newnode;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _copyUnique
|
|
* ----------------
|
|
*/
|
|
static Unique *
|
|
_copyUnique(Unique *from)
|
|
{
|
|
Unique *newnode = makeNode(Unique);
|
|
|
|
/* ----------------
|
|
* copy node superclass fields
|
|
* ----------------
|
|
*/
|
|
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
|
CopyNonameFields((Noname *) from, (Noname *) newnode);
|
|
|
|
/* ----------------
|
|
* copy remainder of node
|
|
* ----------------
|
|
*/
|
|
if (from->uniqueAttr)
|
|
newnode->uniqueAttr = pstrdup(from->uniqueAttr);
|
|
else
|
|
newnode->uniqueAttr = NULL;
|
|
newnode->uniqueAttrNum = from->uniqueAttrNum;
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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->resgroupref = from->resgroupref;
|
|
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;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyAggref
|
|
* ----------------
|
|
*/
|
|
static Aggref *
|
|
_copyAggref(Aggref *from)
|
|
{
|
|
Aggref *newnode = makeNode(Aggref);
|
|
|
|
/* ----------------
|
|
* 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;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyCaseExpr
|
|
* ----------------
|
|
*/
|
|
static CaseExpr *
|
|
_copyCaseExpr(CaseExpr *from)
|
|
{
|
|
CaseExpr *newnode = makeNode(CaseExpr);
|
|
|
|
/* ----------------
|
|
* copy remainder of node
|
|
* ----------------
|
|
*/
|
|
newnode->casetype = from->casetype;
|
|
|
|
Node_Copy(from, newnode, arg);
|
|
Node_Copy(from, newnode, args);
|
|
Node_Copy(from, newnode, defresult);
|
|
|
|
return newnode;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyCaseWhen
|
|
* ----------------
|
|
*/
|
|
static CaseWhen *
|
|
_copyCaseWhen(CaseWhen *from)
|
|
{
|
|
CaseWhen *newnode = makeNode(CaseWhen);
|
|
|
|
/* ----------------
|
|
* copy remainder of node
|
|
* ----------------
|
|
*/
|
|
Node_Copy(from, newnode, expr);
|
|
Node_Copy(from, newnode, result);
|
|
|
|
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, 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, restrictinfo);
|
|
Node_Copy(from, newnode, joininfo);
|
|
Node_Copy(from, newnode, innerjoin);
|
|
|
|
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->pathorder = makeNode(PathOrder);
|
|
newnode->pathorder->ordtype = from->pathorder->ordtype;
|
|
if (from->pathorder->ordtype == SORTOP_ORDER)
|
|
{
|
|
int len,
|
|
i;
|
|
Oid *ordering = from->pathorder->ord.sortop;
|
|
|
|
if (ordering)
|
|
{
|
|
for (len = 0; ordering[len] != 0; len++)
|
|
;
|
|
newnode->pathorder->ord.sortop = (Oid *) palloc(sizeof(Oid) * (len + 1));
|
|
for (i = 0; i < len; i++)
|
|
newnode->pathorder->ord.sortop[i] = ordering[i];
|
|
newnode->pathorder->ord.sortop[len] = 0;
|
|
}
|
|
}
|
|
else
|
|
Node_Copy(from, newnode, pathorder->ord.merge);
|
|
|
|
Node_Copy(from, newnode, pathkeys);
|
|
|
|
newnode->outerjoincost = from->outerjoincost;
|
|
|
|
newnode->joinid = listCopy(from->joinid);
|
|
}
|
|
|
|
/* ----------------
|
|
* _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;
|
|
}
|
|
|
|
/* ----------------
|
|
* CopyNestPathFields
|
|
*
|
|
* This function copies the fields of the NestPath node. It is used by
|
|
* all the copy functions for classes which inherit from NestPath.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
CopyNestPathFields(NestPath *from, NestPath *newnode)
|
|
{
|
|
Node_Copy(from, newnode, pathinfo);
|
|
Node_Copy(from, newnode, outerjoinpath);
|
|
Node_Copy(from, newnode, innerjoinpath);
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyNestPath
|
|
* ----------------
|
|
*/
|
|
static NestPath *
|
|
_copyNestPath(NestPath *from)
|
|
{
|
|
NestPath *newnode = makeNode(NestPath);
|
|
|
|
/* ----------------
|
|
* copy the node superclass fields
|
|
* ----------------
|
|
*/
|
|
CopyPathFields((Path *) from, (Path *) newnode);
|
|
CopyNestPathFields(from, newnode);
|
|
|
|
return newnode;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyMergePath
|
|
* ----------------
|
|
*/
|
|
static MergePath *
|
|
_copyMergePath(MergePath *from)
|
|
{
|
|
MergePath *newnode = makeNode(MergePath);
|
|
|
|
/* ----------------
|
|
* copy the node superclass fields
|
|
* ----------------
|
|
*/
|
|
CopyPathFields((Path *) from, (Path *) newnode);
|
|
CopyNestPathFields((NestPath *) from, (NestPath *) 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);
|
|
CopyNestPathFields((NestPath *) from, (NestPath *) 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;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyRestrictInfo
|
|
* ----------------
|
|
*/
|
|
static RestrictInfo *
|
|
_copyRestrictInfo(RestrictInfo *from)
|
|
{
|
|
RestrictInfo *newnode = makeNode(RestrictInfo);
|
|
|
|
/* ----------------
|
|
* copy remainder of node
|
|
* ----------------
|
|
*/
|
|
Node_Copy(from, newnode, clause);
|
|
|
|
newnode->selectivity = from->selectivity;
|
|
|
|
Node_Copy(from, newnode, indexids);
|
|
Node_Copy(from, newnode, mergejoinorder);
|
|
newnode->hashjoinoperator = from->hashjoinoperator;
|
|
|
|
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;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyHashInfo
|
|
* ----------------
|
|
*/
|
|
static HashInfo *
|
|
_copyHashInfo(HashInfo *from)
|
|
{
|
|
HashInfo *newnode = makeNode(HashInfo);
|
|
|
|
/* ----------------
|
|
* copy remainder of node
|
|
* ----------------
|
|
*/
|
|
CopyJoinMethodFields((JoinMethod *) from, (JoinMethod *) newnode);
|
|
newnode->hashop = from->hashop;
|
|
|
|
return newnode;
|
|
}
|
|
|
|
/* ----------------
|
|
* _copyMergeInfo
|
|
* ----------------
|
|
*/
|
|
static MergeInfo *
|
|
_copyMergeInfo(MergeInfo *from)
|
|
{
|
|
MergeInfo *newnode = makeNode(MergeInfo);
|
|
|
|
/* ----------------
|
|
* 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->unjoined_relids = listCopy(from->unjoined_relids);
|
|
Node_Copy(from, newnode, jinfo_restrictinfo);
|
|
|
|
newnode->mergejoinable = from->mergejoinable;
|
|
newnode->hashjoinable = from->hashjoinable;
|
|
|
|
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 RowMark *
|
|
_copyRowMark(RowMark *from)
|
|
{
|
|
RowMark *newnode = makeNode(RowMark);
|
|
|
|
newnode->rti = from->rti;
|
|
newnode->info = from->info;
|
|
|
|
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->isTemp = from->isTemp;
|
|
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;
|
|
}
|
|
|
|
Node_Copy(from, newnode, limitOffset);
|
|
Node_Copy(from, newnode, limitCount);
|
|
|
|
Node_Copy(from, newnode, rowMark);
|
|
|
|
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_Noname:
|
|
retval = _copyNoname(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_Aggref:
|
|
retval = _copyAggref(from);
|
|
break;
|
|
case T_SubLink:
|
|
retval = _copySubLink(from);
|
|
break;
|
|
case T_CaseExpr:
|
|
retval = _copyCaseExpr(from);
|
|
break;
|
|
case T_CaseWhen:
|
|
retval = _copyCaseWhen(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_NestPath:
|
|
retval = _copyNestPath(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_RestrictInfo:
|
|
retval = _copyRestrictInfo(from);
|
|
break;
|
|
case T_JoinMethod:
|
|
retval = _copyJoinMethod(from);
|
|
break;
|
|
case T_HashInfo:
|
|
retval = _copyHashInfo(from);
|
|
break;
|
|
case T_MergeInfo:
|
|
retval = _copyMergeInfo(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_RowMark:
|
|
retval = _copyRowMark(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(ERROR, "copyObject: don't know how to copy %d", nodeTag(from));
|
|
retval = from;
|
|
break;
|
|
}
|
|
return retval;
|
|
}
|