📄 nodeagg.c
字号:
} else { /* * apply the transition functions. */ args[0] = value1[aggno]; args[1] = newVal; value1[aggno] = (Datum) fmgr_c(&aggfns->xfn1, (FmgrValues *) args, &isNull1); Assert(!isNull1); } } if (aggfns->xfn2.fn_addr != NULL) { args[0] = value2[aggno]; value2[aggno] = (Datum) fmgr_c(&aggfns->xfn2, (FmgrValues *) args, &isNull2); Assert(!isNull2); } } /* * keep this for the projection (we only need one of these - * all the tuples we aggregate over share the same group * column) */ if (!oneTuple) oneTuple = heap_copytuple(outerslot->val); nTuplesAgged++; } /* -------------- * finalize the aggregate (if necessary), and get the resultant value * -------------- */ aggno = -1; foreach(alist, node->aggs) { char *args[2]; AggFuncInfo *aggfns = &aggFuncInfo[++aggno]; if (noInitValue[aggno]) { /* * No values found for this agg; return current state. * This seems to fix behavior for avg() aggregate. -tgl * 12/96 */ } else if (aggfns->finalfn.fn_addr != NULL && nTuplesAgged > 0) { if (aggfns->finalfn.fn_nargs > 1) { args[0] = (char *) value1[aggno]; args[1] = (char *) value2[aggno]; } else if (aggfns->xfn1.fn_addr != NULL) args[0] = (char *) value1[aggno]; else if (aggfns->xfn2.fn_addr != NULL) args[0] = (char *) value2[aggno]; else elog(NOTICE, "ExecAgg: no valid transition functions??"); value1[aggno] = (Datum) fmgr_c(&aggfns->finalfn, (FmgrValues *) args, &(nulls[aggno])); } else if (aggfns->xfn1.fn_addr != NULL) { /* * value in the right place, ignore. (If you remove this * case, fix the else part. -ay 2/95) */ } else if (aggfns->xfn2.fn_addr != NULL) value1[aggno] = value2[aggno]; else elog(ERROR, "ExecAgg: no valid transition functions??"); } /* * whether the aggregation is done depends on whether we are doing * aggregation over groups or the entire table */ if (nodeTag(outerPlan) == T_Group) { /* aggregation over groups */ aggstate->agg_done = ((Group *) outerPlan)->grpstate->grp_done; } else aggstate->agg_done = TRUE; /* ---------------- * form a projection tuple, store it in the result tuple * slot and return it. * ---------------- */ ExecStoreTuple(oneTuple, aggstate->csstate.css_ScanTupleSlot, InvalidBuffer, false); econtext->ecxt_scantuple = aggstate->csstate.css_ScanTupleSlot; resultSlot = ExecProject(projInfo, &isDone); /* * As long as the retrieved group does not match the * qualifications it is ignored and the next group is fetched */ if (node->plan.qual != NULL) qual_result = ExecQual(fix_opids(node->plan.qual), econtext); else qual_result = false; if (oneTuple) pfree(oneTuple); } while (node->plan.qual != NULL && qual_result != true); return resultSlot;}/* ----------------- * ExecInitAgg * * Creates the run-time information for the agg node produced by the * planner and initializes its outer subtree * ----------------- */boolExecInitAgg(Agg *node, EState *estate, Plan *parent){ AggState *aggstate; Plan *outerPlan; ExprContext *econtext; /* * assign the node's execution state */ node->plan.state = estate; /* * create state structure */ aggstate = makeNode(AggState); node->aggstate = aggstate; aggstate->agg_done = FALSE; /* * assign node's base id and create expression context */ ExecAssignNodeBaseInfo(estate, &aggstate->csstate.cstate, (Plan *) parent); ExecAssignExprContext(estate, &aggstate->csstate.cstate);#define AGG_NSLOTS 2 /* * tuple table initialization */ ExecInitScanTupleSlot(estate, &aggstate->csstate); ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate); econtext = aggstate->csstate.cstate.cs_ExprContext; econtext->ecxt_values = (Datum *) palloc(sizeof(Datum) * length(node->aggs)); MemSet(econtext->ecxt_values, 0, sizeof(Datum) * length(node->aggs)); econtext->ecxt_nulls = (char *) palloc(sizeof(char) * length(node->aggs)); MemSet(econtext->ecxt_nulls, 0, sizeof(char) * length(node->aggs)); /* * initializes child nodes */ outerPlan = outerPlan(node); ExecInitNode(outerPlan, estate, (Plan *) node); /* * Result runs in its own context, but make it use our aggregates fix * for 'select sum(2+2)' */ if (nodeTag(outerPlan) == T_Result) { ((Result *) outerPlan)->resstate->cstate.cs_ProjInfo->pi_exprContext->ecxt_values = econtext->ecxt_values; ((Result *) outerPlan)->resstate->cstate.cs_ProjInfo->pi_exprContext->ecxt_nulls = econtext->ecxt_nulls; } /* ---------------- * initialize tuple type. * ---------------- */ ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate); /* * Initialize tuple type for both result and scan. This node does no * projection */ ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate); ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate); return TRUE;}intExecCountSlotsAgg(Agg *node){ return ExecCountSlotsNode(outerPlan(node)) + ExecCountSlotsNode(innerPlan(node)) + AGG_NSLOTS;}/* ------------------------ * ExecEndAgg(node) * * ----------------------- */voidExecEndAgg(Agg *node){ AggState *aggstate; Plan *outerPlan; aggstate = node->aggstate; ExecFreeProjectionInfo(&aggstate->csstate.cstate); outerPlan = outerPlan(node); ExecEndNode(outerPlan, (Plan *) node); /* clean up tuple table */ ExecClearTuple(aggstate->csstate.css_ScanTupleSlot);}/***************************************************************************** * Support Routines *****************************************************************************//* * aggGetAttr - * get the attribute (specified in the Var node in agg) to aggregate * over from the tuple */static DatumaggGetAttr(TupleTableSlot *slot, Aggref *aggref, bool *isNull){ Datum result; AttrNumber attnum; HeapTuple heapTuple; TupleDesc tuple_type; Buffer buffer; /* ---------------- * extract tuple information from the slot * ---------------- */ heapTuple = slot->val; tuple_type = slot->ttc_tupleDescriptor; buffer = slot->ttc_buffer; attnum = ((Var *) aggref->target)->varattno; /* * If the attribute number is invalid, then we are supposed to return * the entire tuple, we give back a whole slot so that callers know * what the tuple looks like. */ if (attnum == InvalidAttrNumber) { TupleTableSlot *tempSlot; TupleDesc td; HeapTuple tup; tempSlot = makeNode(TupleTableSlot); tempSlot->ttc_shouldFree = false; tempSlot->ttc_descIsNew = true; tempSlot->ttc_tupleDescriptor = (TupleDesc) NULL; tempSlot->ttc_buffer = InvalidBuffer; tempSlot->ttc_whichplan = -1; tup = heap_copytuple(heapTuple); td = CreateTupleDescCopy(slot->ttc_tupleDescriptor); ExecSetSlotDescriptor(tempSlot, td); ExecStoreTuple(tup, tempSlot, InvalidBuffer, true); return (Datum) tempSlot; } result = heap_getattr(heapTuple, /* tuple containing attribute */ attnum, /* attribute number of desired * attribute */ tuple_type, /* tuple descriptor of tuple */ isNull); /* return: is attribute null? */ /* ---------------- * return null if att is null * ---------------- */ if (*isNull) return (Datum) NULL; return result;}voidExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent){ AggState *aggstate = node->aggstate; ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext; aggstate->agg_done = FALSE; MemSet(econtext->ecxt_values, 0, sizeof(Datum) * length(node->aggs)); MemSet(econtext->ecxt_nulls, 0, sizeof(char) * length(node->aggs)); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (((Plan *) node)->lefttree->chgParam == NULL) ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -