mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-30 19:00:29 +08:00
New nodeGroup.c code uses own copy of first tuple in a group.
Free memory after comparison in nodeUnique.c
This commit is contained in:
parent
3d18ca70a7
commit
b1b246ab40
@ -13,7 +13,7 @@
|
||||
* columns. (ie. tuples from the same group are consecutive)
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.16 1998/02/10 16:02:58 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.17 1998/02/18 12:40:43 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -31,7 +31,7 @@
|
||||
static TupleTableSlot *ExecGroupEveryTuple(Group *node);
|
||||
static TupleTableSlot *ExecGroupOneTuple(Group *node);
|
||||
static bool
|
||||
sameGroup(TupleTableSlot *oldslot, TupleTableSlot *newslot,
|
||||
sameGroup(HeapTuple oldslot, HeapTuple newslot,
|
||||
int numCols, AttrNumber *grpColIdx, TupleDesc tupdesc);
|
||||
|
||||
/* ---------------------------------------
|
||||
@ -71,8 +71,8 @@ ExecGroupEveryTuple(Group *node)
|
||||
ExprContext *econtext;
|
||||
|
||||
HeapTuple outerTuple = NULL;
|
||||
TupleTableSlot *outerslot,
|
||||
*lastslot;
|
||||
HeapTuple firsttuple;
|
||||
TupleTableSlot *outerslot;
|
||||
ProjectionInfo *projInfo;
|
||||
TupleTableSlot *resultSlot;
|
||||
|
||||
@ -90,18 +90,14 @@ ExecGroupEveryTuple(Group *node)
|
||||
|
||||
econtext = grpstate->csstate.cstate.cs_ExprContext;
|
||||
|
||||
if (grpstate->grp_useLastTuple)
|
||||
/* if we haven't returned first tuple of new group yet ... */
|
||||
if (grpstate->grp_useFirstTuple)
|
||||
{
|
||||
grpstate->grp_useFirstTuple = FALSE;
|
||||
|
||||
/*
|
||||
* we haven't returned last tuple yet because it is not of the
|
||||
* same group
|
||||
*/
|
||||
grpstate->grp_useLastTuple = FALSE;
|
||||
|
||||
ExecStoreTuple(grpstate->grp_lastSlot->val,
|
||||
ExecStoreTuple(grpstate->grp_firstTuple,
|
||||
grpstate->csstate.css_ScanTupleSlot,
|
||||
grpstate->grp_lastSlot->ttc_buffer,
|
||||
InvalidBuffer,
|
||||
false);
|
||||
}
|
||||
else
|
||||
@ -115,29 +111,28 @@ ExecGroupEveryTuple(Group *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Compare with last tuple and see if this tuple is of
|
||||
* the same group.
|
||||
* ----------------
|
||||
*/
|
||||
lastslot = grpstate->csstate.css_ScanTupleSlot;
|
||||
|
||||
if (lastslot->val != NULL &&
|
||||
(!sameGroup(lastslot, outerslot,
|
||||
node->numCols, node->grpColIdx,
|
||||
ExecGetScanType(&grpstate->csstate))))
|
||||
firsttuple = grpstate->grp_firstTuple;
|
||||
/* this should occur on the first call only */
|
||||
if (firsttuple == NULL)
|
||||
{
|
||||
grpstate->grp_firstTuple = heap_copytuple (outerTuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ExecGetResultType(&grpstate->csstate.cstate)))) {*/
|
||||
|
||||
grpstate->grp_useLastTuple = TRUE;
|
||||
|
||||
/* save it for next time */
|
||||
grpstate->grp_lastSlot = outerslot;
|
||||
|
||||
/*
|
||||
* signifies the end of the group
|
||||
* Compare with first tuple and see if this tuple is of
|
||||
* the same group.
|
||||
*/
|
||||
return NULL;
|
||||
if (!sameGroup(firsttuple, outerslot->val,
|
||||
node->numCols, node->grpColIdx,
|
||||
ExecGetScanType(&grpstate->csstate)))
|
||||
{
|
||||
grpstate->grp_useFirstTuple = TRUE;
|
||||
pfree (firsttuple);
|
||||
grpstate->grp_firstTuple = heap_copytuple (outerTuple);
|
||||
|
||||
return NULL; /* signifies the end of the group */
|
||||
}
|
||||
}
|
||||
|
||||
ExecStoreTuple(outerTuple,
|
||||
@ -172,8 +167,8 @@ ExecGroupOneTuple(Group *node)
|
||||
ExprContext *econtext;
|
||||
|
||||
HeapTuple outerTuple = NULL;
|
||||
TupleTableSlot *outerslot,
|
||||
*lastslot;
|
||||
HeapTuple firsttuple;
|
||||
TupleTableSlot *outerslot;
|
||||
ProjectionInfo *projInfo;
|
||||
TupleTableSlot *resultSlot;
|
||||
|
||||
@ -191,15 +186,9 @@ ExecGroupOneTuple(Group *node)
|
||||
|
||||
econtext = node->grpstate->csstate.cstate.cs_ExprContext;
|
||||
|
||||
if (grpstate->grp_useLastTuple)
|
||||
{
|
||||
grpstate->grp_useLastTuple = FALSE;
|
||||
ExecStoreTuple(grpstate->grp_lastSlot->val,
|
||||
grpstate->csstate.css_ScanTupleSlot,
|
||||
grpstate->grp_lastSlot->ttc_buffer,
|
||||
false);
|
||||
}
|
||||
else
|
||||
firsttuple = grpstate->grp_firstTuple;
|
||||
/* this should occur on the first call only */
|
||||
if (firsttuple == NULL)
|
||||
{
|
||||
outerslot = ExecProcNode(outerPlan(node), (Plan *) node);
|
||||
if (outerslot)
|
||||
@ -209,12 +198,8 @@ ExecGroupOneTuple(Group *node)
|
||||
grpstate->grp_done = TRUE;
|
||||
return NULL;
|
||||
}
|
||||
ExecStoreTuple(outerTuple,
|
||||
grpstate->csstate.css_ScanTupleSlot,
|
||||
outerslot->ttc_buffer,
|
||||
false);
|
||||
grpstate->grp_firstTuple = firsttuple = heap_copytuple (outerTuple);
|
||||
}
|
||||
lastslot = grpstate->csstate.css_ScanTupleSlot;
|
||||
|
||||
/*
|
||||
* find all tuples that belong to a group
|
||||
@ -225,49 +210,21 @@ ExecGroupOneTuple(Group *node)
|
||||
outerTuple = (outerslot) ? outerslot->val : NULL;
|
||||
if (!HeapTupleIsValid(outerTuple))
|
||||
{
|
||||
|
||||
/*
|
||||
* we have at least one tuple (lastslot) if we reach here
|
||||
*/
|
||||
grpstate->grp_done = TRUE;
|
||||
|
||||
/* return lastslot */
|
||||
break;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Compare with last tuple and see if this tuple is of
|
||||
* Compare with first tuple and see if this tuple is of
|
||||
* the same group.
|
||||
* ----------------
|
||||
*/
|
||||
if ((!sameGroup(lastslot, outerslot,
|
||||
if ((!sameGroup(firsttuple, outerslot->val,
|
||||
node->numCols, node->grpColIdx,
|
||||
ExecGetScanType(&grpstate->csstate))))
|
||||
{
|
||||
/* ExecGetResultType(&grpstate->csstate.cstate)))) {*/
|
||||
|
||||
grpstate->grp_useLastTuple = TRUE;
|
||||
|
||||
/* save it for next time */
|
||||
grpstate->grp_lastSlot = outerslot;
|
||||
|
||||
/* return lastslot */
|
||||
break;
|
||||
}
|
||||
|
||||
ExecStoreTuple(outerTuple,
|
||||
grpstate->csstate.css_ScanTupleSlot,
|
||||
outerslot->ttc_buffer,
|
||||
false);
|
||||
|
||||
lastslot = grpstate->csstate.css_ScanTupleSlot;
|
||||
}
|
||||
|
||||
ExecStoreTuple(lastslot->val,
|
||||
grpstate->csstate.css_ScanTupleSlot,
|
||||
lastslot->ttc_buffer,
|
||||
false);
|
||||
|
||||
/* ----------------
|
||||
* form a projection tuple, store it in the result tuple
|
||||
* slot and return it.
|
||||
@ -275,8 +232,19 @@ ExecGroupOneTuple(Group *node)
|
||||
*/
|
||||
projInfo = grpstate->csstate.cstate.cs_ProjInfo;
|
||||
|
||||
econtext->ecxt_scantuple = lastslot;
|
||||
ExecStoreTuple(firsttuple,
|
||||
grpstate->csstate.css_ScanTupleSlot,
|
||||
InvalidBuffer,
|
||||
false);
|
||||
econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot;
|
||||
resultSlot = ExecProject(projInfo, &isDone);
|
||||
|
||||
/* save outerTuple if we are not done yet */
|
||||
if (!grpstate->grp_done)
|
||||
{
|
||||
pfree (firsttuple);
|
||||
grpstate->grp_firstTuple = heap_copytuple (outerTuple);
|
||||
}
|
||||
|
||||
return resultSlot;
|
||||
}
|
||||
@ -304,7 +272,7 @@ ExecInitGroup(Group *node, EState *estate, Plan *parent)
|
||||
*/
|
||||
grpstate = makeNode(GroupState);
|
||||
node->grpstate = grpstate;
|
||||
grpstate->grp_useLastTuple = FALSE;
|
||||
grpstate->grp_useFirstTuple = FALSE;
|
||||
grpstate->grp_done = FALSE;
|
||||
|
||||
/*
|
||||
@ -370,6 +338,11 @@ ExecEndGroup(Group *node)
|
||||
|
||||
/* clean up tuple table */
|
||||
ExecClearTuple(grpstate->csstate.css_ScanTupleSlot);
|
||||
if (grpstate->grp_firstTuple != NULL)
|
||||
{
|
||||
pfree (grpstate->grp_firstTuple);
|
||||
grpstate->grp_firstTuple = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -380,8 +353,8 @@ ExecEndGroup(Group *node)
|
||||
* code swiped from nodeUnique.c
|
||||
*/
|
||||
static bool
|
||||
sameGroup(TupleTableSlot *oldslot,
|
||||
TupleTableSlot *newslot,
|
||||
sameGroup(HeapTuple oldtuple,
|
||||
HeapTuple newtuple,
|
||||
int numCols,
|
||||
AttrNumber *grpColIdx,
|
||||
TupleDesc tupdesc)
|
||||
@ -401,12 +374,12 @@ sameGroup(TupleTableSlot *oldslot,
|
||||
att = grpColIdx[i];
|
||||
typoutput = typtoout((Oid) tupdesc->attrs[att - 1]->atttypid);
|
||||
|
||||
attr1 = heap_getattr(oldslot->val,
|
||||
attr1 = heap_getattr(oldtuple,
|
||||
att,
|
||||
tupdesc,
|
||||
&isNull1);
|
||||
|
||||
attr2 = heap_getattr(newslot->val,
|
||||
attr2 = heap_getattr(newtuple,
|
||||
att,
|
||||
tupdesc,
|
||||
&isNull2);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.14 1998/02/10 16:03:03 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.15 1998/02/18 12:40:44 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -208,9 +208,14 @@ ExecUnique(Unique *node)
|
||||
* use strcmp for comparison
|
||||
*/
|
||||
if (strcmp(val1, val2) == 0) /* they are equal */
|
||||
{
|
||||
pfree (val1);
|
||||
pfree (val2);
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
pfree (val1);
|
||||
pfree (val2);
|
||||
break;
|
||||
}
|
||||
else
|
||||
/* one is null and the other isn't, they aren't equal */
|
||||
|
Loading…
Reference in New Issue
Block a user