diff options
author | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
commit | 1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch) | |
tree | 8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/executor/nodeGroup.c | |
parent | 8fecd4febf8357f3cc20383ed29ced484877d5ac (diff) | |
download | postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip |
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/executor/nodeGroup.c')
-rw-r--r-- | src/backend/executor/nodeGroup.c | 632 |
1 files changed, 330 insertions, 302 deletions
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 0637a8dd282..1a96a1ee911 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -1,19 +1,19 @@ /*------------------------------------------------------------------------- * * nodeGroup.c-- - * Routines to handle group nodes (used for queries with GROUP BY clause). + * Routines to handle group nodes (used for queries with GROUP BY clause). * * Copyright (c) 1994, Regents of the University of California * * * DESCRIPTION - * The Group node is designed for handling queries with a GROUP BY clause. - * It's outer plan must be a sort node. It assumes that the tuples it gets - * back from the outer plan is sorted in the order specified by the group - * columns. (ie. tuples from the same group are consecutive) + * The Group node is designed for handling queries with a GROUP BY clause. + * It's outer plan must be a sort node. It assumes that the tuples it gets + * back from the outer plan is sorted in the order specified by the group + * columns. (ie. tuples from the same group are consecutive) * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.5 1997/01/10 20:17:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.6 1997/09/07 04:41:31 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,329 +28,348 @@ #include "executor/executor.h" #include "executor/nodeGroup.h" -static TupleTableSlot *ExecGroupEveryTuple(Group *node); -static TupleTableSlot *ExecGroupOneTuple(Group *node); -static bool sameGroup(TupleTableSlot *oldslot, TupleTableSlot *newslot, - int numCols, AttrNumber *grpColIdx, TupleDesc tupdesc); +static TupleTableSlot *ExecGroupEveryTuple(Group * node); +static TupleTableSlot *ExecGroupOneTuple(Group * node); +static bool +sameGroup(TupleTableSlot * oldslot, TupleTableSlot * newslot, + int numCols, AttrNumber * grpColIdx, TupleDesc tupdesc); /* --------------------------------------- - * ExecGroup - + * ExecGroup - * - * There are two modes in which tuples are returned by ExecGroup. If - * tuplePerGroup is TRUE, every tuple from the same group will be - * returned, followed by a NULL at the end of each group. This is - * useful for Agg node which needs to aggregate over tuples of the same - * group. (eg. SELECT salary, count{*} FROM emp GROUP BY salary) + * There are two modes in which tuples are returned by ExecGroup. If + * tuplePerGroup is TRUE, every tuple from the same group will be + * returned, followed by a NULL at the end of each group. This is + * useful for Agg node which needs to aggregate over tuples of the same + * group. (eg. SELECT salary, count{*} FROM emp GROUP BY salary) * - * If tuplePerGroup is FALSE, only one tuple per group is returned. The - * tuple returned contains only the group columns. NULL is returned only - * at the end when no more groups is present. This is useful when - * the query does not involve aggregates. (eg. SELECT salary FROM emp - * GROUP BY salary) + * If tuplePerGroup is FALSE, only one tuple per group is returned. The + * tuple returned contains only the group columns. NULL is returned only + * at the end when no more groups is present. This is useful when + * the query does not involve aggregates. (eg. SELECT salary FROM emp + * GROUP BY salary) * ------------------------------------------ */ TupleTableSlot * -ExecGroup(Group *node) +ExecGroup(Group * node) { - if (node->tuplePerGroup) - return ExecGroupEveryTuple(node); - else - return ExecGroupOneTuple(node); + if (node->tuplePerGroup) + return ExecGroupEveryTuple(node); + else + return ExecGroupOneTuple(node); } /* * ExecGroupEveryTuple - - * return every tuple with a NULL between each group + * return every tuple with a NULL between each group */ static TupleTableSlot * -ExecGroupEveryTuple(Group *node) +ExecGroupEveryTuple(Group * node) { - GroupState *grpstate; - EState *estate; - ExprContext *econtext; + GroupState *grpstate; + EState *estate; + ExprContext *econtext; - HeapTuple outerTuple = NULL; - TupleTableSlot *outerslot, *lastslot; - ProjectionInfo *projInfo; - TupleTableSlot *resultSlot; + HeapTuple outerTuple = NULL; + TupleTableSlot *outerslot, + *lastslot; + ProjectionInfo *projInfo; + TupleTableSlot *resultSlot; - bool isDone; + bool isDone; - /* --------------------- - * get state info from node - * --------------------- - */ - grpstate = node->grpstate; - if (grpstate->grp_done) - return NULL; + /* --------------------- + * get state info from node + * --------------------- + */ + grpstate = node->grpstate; + if (grpstate->grp_done) + return NULL; - estate = node->plan.state; + estate = node->plan.state; - econtext = grpstate->csstate.cstate.cs_ExprContext; + econtext = grpstate->csstate.cstate.cs_ExprContext; - if (grpstate->grp_useLastTuple) { - /* - * we haven't returned last tuple yet because it is not of the - * same group - */ - grpstate->grp_useLastTuple = FALSE; + if (grpstate->grp_useLastTuple) + { + + /* + * we haven't returned last tuple yet because it is not of the + * same group + */ + grpstate->grp_useLastTuple = FALSE; - ExecStoreTuple(grpstate->grp_lastSlot->val, - grpstate->csstate.css_ScanTupleSlot, - grpstate->grp_lastSlot->ttc_buffer, - false); - } else { - outerslot = ExecProcNode(outerPlan(node), (Plan*)node); - if (outerslot) - outerTuple = outerslot->val; - if (!HeapTupleIsValid(outerTuple)) { - grpstate->grp_done = TRUE; - return NULL; + ExecStoreTuple(grpstate->grp_lastSlot->val, + grpstate->csstate.css_ScanTupleSlot, + grpstate->grp_lastSlot->ttc_buffer, + false); + } + else + { + outerslot = ExecProcNode(outerPlan(node), (Plan *) node); + if (outerslot) + outerTuple = outerslot->val; + if (!HeapTupleIsValid(outerTuple)) + { + grpstate->grp_done = TRUE; + 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)))) + { +/* ExecGetResultType(&grpstate->csstate.cstate)))) {*/ + + grpstate->grp_useLastTuple = TRUE; + + /* save it for next time */ + grpstate->grp_lastSlot = outerslot; + + /* + * signifies the end of the group + */ + return NULL; + } + + ExecStoreTuple(outerTuple, + grpstate->csstate.css_ScanTupleSlot, + outerslot->ttc_buffer, + false); } /* ---------------- - * Compare with last tuple and see if this tuple is of - * the same group. + * form a projection tuple, store it in the result tuple + * slot and return it. * ---------------- */ - lastslot = grpstate->csstate.css_ScanTupleSlot; - - if (lastslot->val != NULL && - (!sameGroup(lastslot, outerslot, - node->numCols, node->grpColIdx, - ExecGetScanType(&grpstate->csstate)))) { -/* ExecGetResultType(&grpstate->csstate.cstate)))) {*/ - - grpstate->grp_useLastTuple = TRUE; + projInfo = grpstate->csstate.cstate.cs_ProjInfo; - /* save it for next time */ - grpstate->grp_lastSlot = outerslot; + econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot; + resultSlot = ExecProject(projInfo, &isDone); - /* - * signifies the end of the group - */ - return NULL; - } - - ExecStoreTuple(outerTuple, - grpstate->csstate.css_ScanTupleSlot, - outerslot->ttc_buffer, - false); - } - - /* ---------------- - * form a projection tuple, store it in the result tuple - * slot and return it. - * ---------------- - */ - projInfo = grpstate->csstate.cstate.cs_ProjInfo; - - econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot; - resultSlot = ExecProject(projInfo, &isDone); - - return resultSlot; + return resultSlot; } /* * ExecGroupOneTuple - - * returns one tuple per group, a NULL at the end when there are no more - * tuples. + * returns one tuple per group, a NULL at the end when there are no more + * tuples. */ static TupleTableSlot * -ExecGroupOneTuple(Group *node) +ExecGroupOneTuple(Group * node) { - GroupState *grpstate; - EState *estate; - ExprContext *econtext; + GroupState *grpstate; + EState *estate; + ExprContext *econtext; - HeapTuple outerTuple = NULL; - TupleTableSlot *outerslot, *lastslot; - ProjectionInfo *projInfo; - TupleTableSlot *resultSlot; + HeapTuple outerTuple = NULL; + TupleTableSlot *outerslot, + *lastslot; + ProjectionInfo *projInfo; + TupleTableSlot *resultSlot; - bool isDone; + bool isDone; - /* --------------------- - * get state info from node - * --------------------- - */ - grpstate = node->grpstate; - if (grpstate->grp_done) - return NULL; + /* --------------------- + * get state info from node + * --------------------- + */ + grpstate = node->grpstate; + if (grpstate->grp_done) + return NULL; - estate = node->plan.state; + estate = node->plan.state; - econtext = node->grpstate->csstate.cstate.cs_ExprContext; + 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 { - outerslot = ExecProcNode(outerPlan(node), (Plan*)node); - if (outerslot) outerTuple = outerslot->val; - if (!HeapTupleIsValid(outerTuple)) { - grpstate->grp_done = TRUE; - return NULL; + if (grpstate->grp_useLastTuple) + { + grpstate->grp_useLastTuple = FALSE; + ExecStoreTuple(grpstate->grp_lastSlot->val, + grpstate->csstate.css_ScanTupleSlot, + grpstate->grp_lastSlot->ttc_buffer, + false); } - ExecStoreTuple(outerTuple, - grpstate->csstate.css_ScanTupleSlot, - outerslot->ttc_buffer, - false); - } - lastslot = grpstate->csstate.css_ScanTupleSlot; - - /* - * find all tuples that belong to a group - */ - for(;;) { - outerslot = ExecProcNode(outerPlan(node), (Plan*)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; + else + { + outerslot = ExecProcNode(outerPlan(node), (Plan *) node); + if (outerslot) + outerTuple = outerslot->val; + if (!HeapTupleIsValid(outerTuple)) + { + grpstate->grp_done = TRUE; + return NULL; + } + ExecStoreTuple(outerTuple, + grpstate->csstate.css_ScanTupleSlot, + outerslot->ttc_buffer, + false); } + lastslot = grpstate->csstate.css_ScanTupleSlot; - /* ---------------- - * Compare with last tuple and see if this tuple is of - * the same group. - * ---------------- + /* + * find all tuples that belong to a group */ - if ((!sameGroup(lastslot, outerslot, - node->numCols, node->grpColIdx, - ExecGetScanType(&grpstate->csstate)))) { -/* ExecGetResultType(&grpstate->csstate.cstate)))) {*/ + for (;;) + { + outerslot = ExecProcNode(outerPlan(node), (Plan *) 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 + * the same group. + * ---------------- + */ + if ((!sameGroup(lastslot, outerslot, + 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; + } - grpstate->grp_useLastTuple = TRUE; + ExecStoreTuple(lastslot->val, + grpstate->csstate.css_ScanTupleSlot, + lastslot->ttc_buffer, + false); - /* save it for next time */ - grpstate->grp_lastSlot = outerslot; + /* ---------------- + * form a projection tuple, store it in the result tuple + * slot and return it. + * ---------------- + */ + projInfo = grpstate->csstate.cstate.cs_ProjInfo; - /* return lastslot */ - break; - } - - ExecStoreTuple(outerTuple, - grpstate->csstate.css_ScanTupleSlot, - outerslot->ttc_buffer, - false); + econtext->ecxt_scantuple = lastslot; + resultSlot = ExecProject(projInfo, &isDone); - 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. - * ---------------- - */ - projInfo = grpstate->csstate.cstate.cs_ProjInfo; - - econtext->ecxt_scantuple = lastslot; - resultSlot = ExecProject(projInfo, &isDone); - - return resultSlot; + return resultSlot; } /* ----------------- - * ExecInitGroup + * ExecInitGroup * - * Creates the run-time information for the group node produced by the - * planner and initializes its outer subtree + * Creates the run-time information for the group node produced by the + * planner and initializes its outer subtree * ----------------- */ bool -ExecInitGroup(Group *node, EState *estate, Plan *parent) +ExecInitGroup(Group * node, EState * estate, Plan * parent) { - GroupState *grpstate; - Plan *outerPlan; - - /* - * assign the node's execution state - */ - node->plan.state = estate; - - /* - * create state structure - */ - grpstate = makeNode(GroupState); - node->grpstate = grpstate; - grpstate->grp_useLastTuple = FALSE; - grpstate->grp_done = FALSE; - - /* - * assign node's base id and create expression context - */ - ExecAssignNodeBaseInfo(estate, &grpstate->csstate.cstate, - (Plan*) parent); - ExecAssignExprContext(estate, &grpstate->csstate.cstate); - + GroupState *grpstate; + Plan *outerPlan; + + /* + * assign the node's execution state + */ + node->plan.state = estate; + + /* + * create state structure + */ + grpstate = makeNode(GroupState); + node->grpstate = grpstate; + grpstate->grp_useLastTuple = FALSE; + grpstate->grp_done = FALSE; + + /* + * assign node's base id and create expression context + */ + ExecAssignNodeBaseInfo(estate, &grpstate->csstate.cstate, + (Plan *) parent); + ExecAssignExprContext(estate, &grpstate->csstate.cstate); + #define GROUP_NSLOTS 2 - /* - * tuple table initialization - */ - ExecInitScanTupleSlot(estate, &grpstate->csstate); - ExecInitResultTupleSlot(estate, &grpstate->csstate.cstate); - - /* - * initializes child nodes - */ - outerPlan = outerPlan(node); - ExecInitNode(outerPlan, estate, (Plan *)node); - - /* ---------------- - * initialize tuple type. - * ---------------- - */ - ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate); - - /* - * Initialize tuple type for both result and scan. - * This node does no projection - */ - ExecAssignResultTypeFromTL((Plan*) node, &grpstate->csstate.cstate); - ExecAssignProjectionInfo((Plan*)node, &grpstate->csstate.cstate); - - return TRUE; + + /* + * tuple table initialization + */ + ExecInitScanTupleSlot(estate, &grpstate->csstate); + ExecInitResultTupleSlot(estate, &grpstate->csstate.cstate); + + /* + * initializes child nodes + */ + outerPlan = outerPlan(node); + ExecInitNode(outerPlan, estate, (Plan *) node); + + /* ---------------- + * initialize tuple type. + * ---------------- + */ + ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate); + + /* + * Initialize tuple type for both result and scan. This node does no + * projection + */ + ExecAssignResultTypeFromTL((Plan *) node, &grpstate->csstate.cstate); + ExecAssignProjectionInfo((Plan *) node, &grpstate->csstate.cstate); + + return TRUE; } int -ExecCountSlotsGroup(Group *node) +ExecCountSlotsGroup(Group * node) { - return ExecCountSlotsNode(outerPlan(node)) + GROUP_NSLOTS; + return ExecCountSlotsNode(outerPlan(node)) + GROUP_NSLOTS; } /* ------------------------ - * ExecEndGroup(node) + * ExecEndGroup(node) * * ----------------------- */ void -ExecEndGroup(Group *node) +ExecEndGroup(Group * node) { - GroupState *grpstate; - Plan *outerPlan; + GroupState *grpstate; + Plan *outerPlan; + + grpstate = node->grpstate; - grpstate = node->grpstate; + ExecFreeProjectionInfo(&grpstate->csstate.cstate); - ExecFreeProjectionInfo(&grpstate->csstate.cstate); + outerPlan = outerPlan(node); + ExecEndNode(outerPlan, (Plan *) node); - outerPlan = outerPlan(node); - ExecEndNode(outerPlan, (Plan*)node); - - /* clean up tuple table */ - ExecClearTuple(grpstate->csstate.css_ScanTupleSlot); + /* clean up tuple table */ + ExecClearTuple(grpstate->csstate.css_ScanTupleSlot); } /***************************************************************************** @@ -360,54 +379,63 @@ ExecEndGroup(Group *node) /* * code swiped from nodeUnique.c */ -static bool -sameGroup(TupleTableSlot *oldslot, - TupleTableSlot *newslot, - int numCols, - AttrNumber *grpColIdx, - TupleDesc tupdesc) +static bool +sameGroup(TupleTableSlot * oldslot, + TupleTableSlot * newslot, + int numCols, + AttrNumber * grpColIdx, + TupleDesc tupdesc) { - bool isNull1,isNull2; - char *attr1, *attr2; - char *val1, *val2; - int i; - AttrNumber att; - Oid typoutput; - - for(i = 0; i < numCols; i++) { - att = grpColIdx[i]; - typoutput = typtoout((Oid)tupdesc->attrs[att-1]->atttypid); - - attr1 = heap_getattr(oldslot->val, - InvalidBuffer, - att, - tupdesc, - &isNull1); - - attr2 = heap_getattr(newslot->val, - InvalidBuffer, - att, - tupdesc, - &isNull2); - - if (isNull1 == isNull2) { - if (isNull1) /* both are null, they are equal */ - continue; - - val1 = fmgr(typoutput, attr1, - gettypelem(tupdesc->attrs[att-1]->atttypid)); - val2 = fmgr(typoutput, attr2, - gettypelem(tupdesc->attrs[att-1]->atttypid)); - - /* now, val1 and val2 are ascii representations so we can - use strcmp for comparison */ - if (strcmp(val1,val2) != 0) - return FALSE; - } else { - /* one is null and the other isn't, they aren't equal */ - return FALSE; + bool isNull1, + isNull2; + char *attr1, + *attr2; + char *val1, + *val2; + int i; + AttrNumber att; + Oid typoutput; + + for (i = 0; i < numCols; i++) + { + att = grpColIdx[i]; + typoutput = typtoout((Oid) tupdesc->attrs[att - 1]->atttypid); + + attr1 = heap_getattr(oldslot->val, + InvalidBuffer, + att, + tupdesc, + &isNull1); + + attr2 = heap_getattr(newslot->val, + InvalidBuffer, + att, + tupdesc, + &isNull2); + + if (isNull1 == isNull2) + { + if (isNull1) /* both are null, they are equal */ + continue; + + val1 = fmgr(typoutput, attr1, + gettypelem(tupdesc->attrs[att - 1]->atttypid)); + val2 = fmgr(typoutput, attr2, + gettypelem(tupdesc->attrs[att - 1]->atttypid)); + + /* + * now, val1 and val2 are ascii representations so we can use + * strcmp for comparison + */ + if (strcmp(val1, val2) != 0) + return FALSE; + } + else + { + /* one is null and the other isn't, they aren't equal */ + return FALSE; + } } - } - return TRUE; + return TRUE; } |