mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
sort order down into planner, instead of handling it only at the very top level of the planner. This fixes many things. An explicit sort is now avoided if there is a cheaper alternative (typically an indexscan) not only for ORDER BY, but also for the internal sort of GROUP BY. It works even when there is no other reason (such as a WHERE condition) to consider the indexscan. It works for indexes on functions. It works for indexes on functions, backwards. It's just so cool... CAUTION: I have changed the representation of SortClause nodes, therefore THIS UPDATE BREAKS STORED RULES. You will need to initdb.
1250 lines
20 KiB
C
1250 lines
20 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* freefuncs.c
|
|
* Free functions for Postgres tree nodes.
|
|
*
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.26 1999/08/21 03:48:57 tgl Exp $
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
#include "optimizer/planmain.h"
|
|
|
|
/* ****************************************************************
|
|
* plannodes.h free functions
|
|
* ****************************************************************
|
|
*/
|
|
static void freeObject(void *obj);
|
|
|
|
/* ----------------
|
|
* FreePlanFields
|
|
*
|
|
* This function frees the fields of the Plan node. It is used by
|
|
* all the free functions for classes which inherit node Plan.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
FreePlanFields(Plan *node)
|
|
{
|
|
freeObject(node->targetlist);
|
|
freeObject(node->qual);
|
|
freeObject(node->lefttree);
|
|
freeObject(node->righttree);
|
|
freeList(node->extParam);
|
|
freeList(node->locParam);
|
|
freeList(node->chgParam);
|
|
freeObject(node->initPlan);
|
|
freeList(node->subPlan);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freePlan
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freePlan(Plan *node)
|
|
{
|
|
/* ----------------
|
|
* free the node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields(node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeResult
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeResult(Result *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->resconstantqual);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeAppend
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeAppend(Append *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->appendplans);
|
|
freeObject(node->unionrtables);
|
|
freeObject(node->inheritrtable);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* FreeScanFields
|
|
*
|
|
* This function frees the fields of the Scan node. It is used by
|
|
* all the free functions for classes which inherit node Scan.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
FreeScanFields(Scan *node)
|
|
{
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeScan
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeScan(Scan *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeScanFields((Scan *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeSeqScan
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeSeqScan(SeqScan *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeScanFields((Scan *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeIndexScan
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeIndexScan(IndexScan *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeScanFields((Scan *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeList(node->indxid);
|
|
freeObject(node->indxqual);
|
|
freeObject(node->indxqualorig);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* FreeJoinFields
|
|
*
|
|
* This function frees the fields of the Join node. It is used by
|
|
* all the free functions for classes which inherit node Join.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
FreeJoinFields(Join *node)
|
|
{
|
|
/* nothing extra */
|
|
return;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeJoin
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeJoin(Join *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeJoinFields(node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeNestLoop
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeNestLoop(NestLoop *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeJoinFields((Join *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeMergeJoin
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeMergeJoin(MergeJoin *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeJoinFields((Join *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->mergeclauses);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeHashJoin
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeHashJoin(HashJoin *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeJoinFields((Join *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->hashclauses);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* FreeNonameFields
|
|
*
|
|
* This function frees the fields of the Noname node. It is used by
|
|
* all the free functions for classes which inherit node Noname.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
FreeNonameFields(Noname *node)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeNoname
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeNoname(Noname *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeNonameFields(node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeMaterial
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeMaterial(Material *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeNonameFields((Noname *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeSort
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeSort(Sort *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeNonameFields((Noname *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeGroup
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeGroup(Group *node)
|
|
{
|
|
FreePlanFields((Plan *) node);
|
|
|
|
pfree(node->grpColIdx);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ---------------
|
|
* _freeAgg
|
|
* --------------
|
|
*/
|
|
static void
|
|
_freeAgg(Agg *node)
|
|
{
|
|
FreePlanFields((Plan *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ---------------
|
|
* _freeGroupClause
|
|
* --------------
|
|
*/
|
|
static void
|
|
_freeGroupClause(GroupClause *node)
|
|
{
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeUnique
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeUnique(Unique *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
FreeNonameFields((Noname *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
if (node->uniqueAttr)
|
|
pfree(node->uniqueAttr);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeHash
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeHash(Hash *node)
|
|
{
|
|
/* ----------------
|
|
* free node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePlanFields((Plan *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->hashkey);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeSubPlan(SubPlan *node)
|
|
{
|
|
freeObject(node->plan);
|
|
freeObject(node->rtable);
|
|
freeList(node->setParam);
|
|
freeList(node->parParam);
|
|
freeObject(node->sublink);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ****************************************************************
|
|
* primnodes.h free functions
|
|
* ****************************************************************
|
|
*/
|
|
|
|
/* ----------------
|
|
* _freeResdom
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeResdom(Resdom *node)
|
|
{
|
|
if (node->resname != NULL)
|
|
pfree(node->resname);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeFjoin(Fjoin *node)
|
|
{
|
|
freeObject(node->fj_innerNode);
|
|
pfree(node->fj_results);
|
|
pfree(node->fj_alwaysDone);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeExpr
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeExpr(Expr *node)
|
|
{
|
|
freeObject(node->oper);
|
|
freeObject(node->args);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeVar
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeVar(Var *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeFcache(FunctionCachePtr ptr)
|
|
{
|
|
if (ptr->argOidVect)
|
|
pfree(ptr->argOidVect);
|
|
if (ptr->nullVect)
|
|
pfree(ptr->nullVect);
|
|
if (ptr->src)
|
|
pfree(ptr->src);
|
|
if (ptr->bin)
|
|
pfree(ptr->bin);
|
|
if (ptr->func_state)
|
|
pfree(ptr->func_state);
|
|
if (ptr->setArg)
|
|
pfree(ptr->setArg);
|
|
|
|
pfree(ptr);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeOper
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeOper(Oper *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
if (node->op_fcache)
|
|
_freeFcache(node->op_fcache);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeConst
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeConst(Const *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
if (!node->constbyval)
|
|
pfree((void *) node->constvalue);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeParam
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeParam(Param *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
if (node->paramname != NULL)
|
|
pfree(node->paramname);
|
|
freeObject(node->param_tlist);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeFunc
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeFunc(Func *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->func_tlist);
|
|
freeObject(node->func_planlist);
|
|
if (node->func_fcache)
|
|
_freeFcache(node->func_fcache);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeAggref
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeAggref(Aggref *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
pfree(node->aggname);
|
|
freeObject(node->target);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeSubLink
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeSubLink(SubLink *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->lefthand);
|
|
freeObject(node->oper);
|
|
freeObject(node->subselect);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeCaseExpr
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeCaseExpr(CaseExpr *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->arg);
|
|
freeObject(node->args);
|
|
freeObject(node->defresult);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeCaseWhen
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeCaseWhen(CaseWhen *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->expr);
|
|
freeObject(node->result);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeArray(Array *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeArrayRef(ArrayRef *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->refupperindexpr);
|
|
freeObject(node->reflowerindexpr);
|
|
freeObject(node->refexpr);
|
|
freeObject(node->refassgnexpr);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ****************************************************************
|
|
* relation.h free functions
|
|
* ****************************************************************
|
|
*/
|
|
|
|
/* ----------------
|
|
* _freeRelOptInfo
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeRelOptInfo(RelOptInfo *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeList(node->relids);
|
|
|
|
freeObject(node->targetlist);
|
|
freeObject(node->pathlist);
|
|
/* is this right? cheapestpath will typically be a pointer into
|
|
* pathlist, won't it?
|
|
*/
|
|
freeObject(node->cheapestpath);
|
|
|
|
if (node->classlist)
|
|
pfree(node->classlist);
|
|
|
|
if (node->indexkeys)
|
|
pfree(node->indexkeys);
|
|
|
|
if (node->ordering)
|
|
pfree(node->ordering);
|
|
|
|
freeObject(node->indpred);
|
|
|
|
freeObject(node->restrictinfo);
|
|
freeObject(node->joininfo);
|
|
freeObject(node->innerjoin);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* FreePathFields
|
|
*
|
|
* This function frees the fields of the Path node. It is used by
|
|
* all the free functions for classes which inherit node Path.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
FreePathFields(Path *node)
|
|
{
|
|
/* we do NOT free the parent; it doesn't belong to the Path */
|
|
|
|
freeObject(node->pathkeys);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freePath
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freePath(Path *node)
|
|
{
|
|
FreePathFields(node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeIndexPath
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeIndexPath(IndexPath *node)
|
|
{
|
|
/* ----------------
|
|
* free the node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePathFields((Path *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeList(node->indexid);
|
|
freeObject(node->indexqual);
|
|
freeList(node->joinrelids);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* FreeJoinPathFields
|
|
*
|
|
* This function frees the fields of the JoinPath node. It is used by
|
|
* all the free functions for classes which inherit node JoinPath.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
FreeJoinPathFields(JoinPath *node)
|
|
{
|
|
freeObject(node->pathinfo);
|
|
freeObject(node->outerjoinpath);
|
|
freeObject(node->innerjoinpath);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeNestPath
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeNestPath(NestPath *node)
|
|
{
|
|
/* ----------------
|
|
* free the node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePathFields((Path *) node);
|
|
FreeJoinPathFields((JoinPath *) node);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeMergePath
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeMergePath(MergePath *node)
|
|
{
|
|
/* ----------------
|
|
* free the node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePathFields((Path *) node);
|
|
FreeJoinPathFields((JoinPath *) node);
|
|
|
|
/* ----------------
|
|
* free the remainder of the node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->path_mergeclauses);
|
|
freeObject(node->outersortkeys);
|
|
freeObject(node->innersortkeys);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeHashPath
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeHashPath(HashPath *node)
|
|
{
|
|
/* ----------------
|
|
* free the node superclass fields
|
|
* ----------------
|
|
*/
|
|
FreePathFields((Path *) node);
|
|
FreeJoinPathFields((JoinPath *) node);
|
|
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->path_hashclauses);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freePathKeyItem
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freePathKeyItem(PathKeyItem *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->key);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/* ----------------
|
|
* _freeRestrictInfo
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeRestrictInfo(RestrictInfo *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeObject(node->clause);
|
|
/* this is certainly wrong? index RelOptInfos don't belong to
|
|
* RestrictInfo...
|
|
*/
|
|
freeObject(node->subclauseindices);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* _freeJoinInfo
|
|
* ----------------
|
|
*/
|
|
static void
|
|
_freeJoinInfo(JoinInfo *node)
|
|
{
|
|
/* ----------------
|
|
* free remainder of node
|
|
* ----------------
|
|
*/
|
|
freeList(node->unjoined_relids);
|
|
freeObject(node->jinfo_restrictinfo);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeIter(Iter *node)
|
|
{
|
|
freeObject(node->iterexpr);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeStream(Stream *node)
|
|
{
|
|
freeObject(node->downstream);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/*
|
|
* parsenodes.h routines have no free functions
|
|
*/
|
|
|
|
static void
|
|
_freeTargetEntry(TargetEntry *node)
|
|
{
|
|
freeObject(node->resdom);
|
|
freeObject(node->fjoin);
|
|
freeObject(node->expr);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeRangeTblEntry(RangeTblEntry *node)
|
|
{
|
|
if (node->relname)
|
|
pfree(node->relname);
|
|
if (node->refname)
|
|
pfree(node->refname);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeRowMark(RowMark *node)
|
|
{
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeSortClause(SortClause *node)
|
|
{
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeAConst(A_Const *node)
|
|
{
|
|
freeObject(&(node->val));
|
|
freeObject(node->typename);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeTypeName(TypeName *node)
|
|
{
|
|
if (node->name)
|
|
pfree(node->name);
|
|
freeObject(node->arrayBounds);
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
static void
|
|
_freeQuery(Query *node)
|
|
{
|
|
if (node->utilityStmt && nodeTag(node->utilityStmt) == T_NotifyStmt)
|
|
{
|
|
NotifyStmt *node_notify = (NotifyStmt *) node->utilityStmt;
|
|
|
|
pfree(node_notify->relname);
|
|
pfree(node_notify);
|
|
}
|
|
if (node->into)
|
|
pfree(node->into);
|
|
freeObject(node->rtable);
|
|
freeObject(node->targetList);
|
|
freeObject(node->qual);
|
|
freeObject(node->rowMark);
|
|
if (node->uniqueFlag)
|
|
pfree(node->uniqueFlag);
|
|
|
|
freeObject(node->sortClause);
|
|
freeObject(node->groupClause);
|
|
freeObject(node->havingQual);
|
|
/* why not intersectClause? */
|
|
freeObject(node->unionClause);
|
|
freeObject(node->limitOffset);
|
|
freeObject(node->limitCount);
|
|
|
|
/* XXX should we be freeing the planner internal fields? */
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
|
|
/*
|
|
* mnodes.h routines have no free functions
|
|
*/
|
|
|
|
/* ****************************************************************
|
|
* pg_list.h free functions
|
|
* ****************************************************************
|
|
*/
|
|
|
|
static void
|
|
_freeValue(Value *node)
|
|
{
|
|
switch (node->type)
|
|
{
|
|
case T_String:
|
|
pfree(node->val.str);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
pfree(node);
|
|
}
|
|
|
|
/* ----------------
|
|
* freeObject free's the node or list. If it is a list, it
|
|
* recursively frees its items.
|
|
* ----------------
|
|
*/
|
|
static void
|
|
freeObject(void *node)
|
|
{
|
|
if (node == NULL)
|
|
return;
|
|
|
|
switch (nodeTag(node))
|
|
{
|
|
|
|
/*
|
|
* PLAN NODES
|
|
*/
|
|
case T_Plan:
|
|
_freePlan(node);
|
|
break;
|
|
case T_Result:
|
|
_freeResult(node);
|
|
break;
|
|
case T_Append:
|
|
_freeAppend(node);
|
|
break;
|
|
case T_Scan:
|
|
_freeScan(node);
|
|
break;
|
|
case T_SeqScan:
|
|
_freeSeqScan(node);
|
|
break;
|
|
case T_IndexScan:
|
|
_freeIndexScan(node);
|
|
break;
|
|
case T_Join:
|
|
_freeJoin(node);
|
|
break;
|
|
case T_NestLoop:
|
|
_freeNestLoop(node);
|
|
break;
|
|
case T_MergeJoin:
|
|
_freeMergeJoin(node);
|
|
break;
|
|
case T_HashJoin:
|
|
_freeHashJoin(node);
|
|
break;
|
|
case T_Noname:
|
|
_freeNoname(node);
|
|
break;
|
|
case T_Material:
|
|
_freeMaterial(node);
|
|
break;
|
|
case T_Sort:
|
|
_freeSort(node);
|
|
break;
|
|
case T_Group:
|
|
_freeGroup(node);
|
|
break;
|
|
case T_Agg:
|
|
_freeAgg(node);
|
|
break;
|
|
case T_GroupClause:
|
|
_freeGroupClause(node);
|
|
break;
|
|
case T_Unique:
|
|
_freeUnique(node);
|
|
break;
|
|
case T_Hash:
|
|
_freeHash(node);
|
|
break;
|
|
case T_SubPlan:
|
|
_freeSubPlan(node);
|
|
break;
|
|
|
|
/*
|
|
* PRIMITIVE NODES
|
|
*/
|
|
case T_Resdom:
|
|
_freeResdom(node);
|
|
break;
|
|
case T_Fjoin:
|
|
_freeFjoin(node);
|
|
break;
|
|
case T_Expr:
|
|
_freeExpr(node);
|
|
break;
|
|
case T_Var:
|
|
_freeVar(node);
|
|
break;
|
|
case T_Oper:
|
|
_freeOper(node);
|
|
break;
|
|
case T_Const:
|
|
_freeConst(node);
|
|
break;
|
|
case T_Param:
|
|
_freeParam(node);
|
|
break;
|
|
case T_Func:
|
|
_freeFunc(node);
|
|
break;
|
|
case T_Array:
|
|
_freeArray(node);
|
|
break;
|
|
case T_ArrayRef:
|
|
_freeArrayRef(node);
|
|
break;
|
|
case T_Aggref:
|
|
_freeAggref(node);
|
|
break;
|
|
case T_SubLink:
|
|
_freeSubLink(node);
|
|
break;
|
|
case T_CaseExpr:
|
|
_freeCaseExpr(node);
|
|
break;
|
|
case T_CaseWhen:
|
|
_freeCaseWhen(node);
|
|
break;
|
|
|
|
/*
|
|
* RELATION NODES
|
|
*/
|
|
case T_RelOptInfo:
|
|
_freeRelOptInfo(node);
|
|
break;
|
|
case T_Path:
|
|
_freePath(node);
|
|
break;
|
|
case T_IndexPath:
|
|
_freeIndexPath(node);
|
|
break;
|
|
case T_NestPath:
|
|
_freeNestPath(node);
|
|
break;
|
|
case T_MergePath:
|
|
_freeMergePath(node);
|
|
break;
|
|
case T_HashPath:
|
|
_freeHashPath(node);
|
|
break;
|
|
case T_PathKeyItem:
|
|
_freePathKeyItem(node);
|
|
break;
|
|
case T_RestrictInfo:
|
|
_freeRestrictInfo(node);
|
|
break;
|
|
case T_JoinInfo:
|
|
_freeJoinInfo(node);
|
|
break;
|
|
case T_Iter:
|
|
_freeIter(node);
|
|
break;
|
|
case T_Stream:
|
|
_freeStream(node);
|
|
break;
|
|
|
|
/*
|
|
* PARSE NODES
|
|
*/
|
|
case T_Query:
|
|
_freeQuery(node);
|
|
break;
|
|
case T_TargetEntry:
|
|
_freeTargetEntry(node);
|
|
break;
|
|
case T_RangeTblEntry:
|
|
_freeRangeTblEntry(node);
|
|
break;
|
|
case T_RowMark:
|
|
_freeRowMark(node);
|
|
break;
|
|
case T_SortClause:
|
|
_freeSortClause(node);
|
|
break;
|
|
case T_A_Const:
|
|
_freeAConst(node);
|
|
break;
|
|
case T_TypeName:
|
|
_freeTypeName(node);
|
|
break;
|
|
|
|
/*
|
|
* VALUE NODES
|
|
*/
|
|
case T_Integer:
|
|
case T_String:
|
|
case T_Float:
|
|
_freeValue(node);
|
|
break;
|
|
case T_List:
|
|
{
|
|
List *list = node,
|
|
*l;
|
|
|
|
foreach(l, list)
|
|
freeObject(lfirst(l));
|
|
freeList(list);
|
|
}
|
|
break;
|
|
default:
|
|
elog(ERROR, "freeObject: don't know how to free %d", nodeTag(node));
|
|
break;
|
|
}
|
|
}
|