PostgreSQL Source Code interpretation (191)-query # 107 (aggregate function # 12-agg_retrieve_direct)
Projected_set + 1; else numReset = numGroupingSets; / * * numReset can change on a phase boundary, but that's OK; we want to * reset the contexts used in _ this_ phase, and later, after possibly * changing phase, initialize the right number of aggregates for the * _ new_ phase. * numReset may change at the boundaries of each stage, but there will be no problem. * We want to reset the context of this phase and initialize the correct aggregation number for the new phase later after the phase that may change. * / for (I = 0; I
< numReset; i++) { ReScanExprContext(aggstate->Aggcontexts [I]);} / * Check if input is complete and there are no more groups to project * in this phase; move to next phase or mark as done. * check that the input is complete and that there are no more groups for projection at this stage. * move to the next stage or mark it as completed. * / if (aggstate- > input_done = = true & & aggstate- > projected_set > = (numGroupingSets-1)) {if (aggstate- > current_phase
< aggstate->Numphases-1) {/ / still in processing initialize_phase (aggstate, aggstate- > current_phase + 1); aggstate- > input_done = false; aggstate- > projected_set =-1; numGroupingSets = Max (aggstate- > phase- > numsets, 1); node = aggstate- > phase- > aggnode; numReset = numGroupingSets } else if (aggstate- > aggstrategy = = AGG_MIXED) {/ / should not enter this branch (isn't AGG_MIXED a Hash only?) / * * Mixed mode; we've output all the grouped stuff and have * full hashtables, so switch to outputting those. * / initialize_phase (aggstate, 0); aggstate- > table_filled = true; ResetTupleHashIterator (aggstate- > perhash [0] .hashtable, & aggstate- > perhash [0] .hashiter); select_current_set (aggstate, 0, true); return agg_retrieve_hash_table (aggstate) } else {/ / finished processing aggstate- > agg_done = true; break;}} / * * Get the number of columns in the next grouping set after the last * projected one (if any). This is the number of columns to compare to * see if we reached the boundary of that set too. * get the number of columns for the next grouping set after the last projection operation. * this is the number of columns to compare to see if we have also reached the boundary of the set. * / if (aggstate- > projected_set > = 0 & & aggstate- > projected_set
< (numGroupingSets - 1)) nextSetSize = aggstate->Phase- > gset_ If a subgroup for the current grouping set is present [aggstate-> projected_set + 1]; else nextSetSize = 0; / *-* If a subgroup for the current grouping set is present, project it. * if the subgroup already exists, the projection is performed. * * We have a new group if: *-we're out of input but haven't projected all grouping sets * (checked above) * OR *-we already projected a row that wasn't from the last grouping * set * AND *-the next grouping set has at least one grouping column (since * empty grouping sets project only once input is exhausted) * AND *-the previous and pending rows differ on the grouping columns * of the next grouping set * * if the following occurs There will be a new grouping: *-input processing has been completed, but not all grouping set has been projected (check will be performed above) *-one line has been projected But this line does not come from the last grouping set * at the same time *-the next grouping set requires at least one grouping column (destroyed because the empty grouping sets projects one input) * at the same time *-the previous and subsequent rows are different from the grouping columns in the next grouping set *- -* / tmpcontext- > ecxt_innertuple = econtext- > ecxt_outertuple If (aggstate- > input_done | | (node- > aggstrategy! = AGG_PLAIN & & aggstate- > projected_set! =-1 & & aggstate- > projected_set
< (numGroupingSets - 1) && nextSetSize >0 & &! ExecQualAndReset (aggstate- > phase- > eqfunctions [nextSetSize-1], tmpcontext)) {aggstate- > projected_set + = 1; Assert (aggstate- > projected_set)
< numGroupingSets); Assert(nextSetSize > < numReset; i++)(gdb) 1644 ReScanExprContext(aggstate->Aggcontexts [I]); (gdb) 1642 for (I = 0; I)
< numReset; i++)(gdb) 检查输入是否已完成处理/本组已完成投影(实际不满足条件) (gdb) 1651 if (aggstate->Input_done = = true & & (gdb) 1688 if (aggstate- > projected_set > = 0 & & (gdb) p aggstate- > input_done$16 = false (gdb) p aggstate- > projected_set$17 =-1
Set the tuple to be processed as NULL
(gdb) 1711 tmpcontext- > ecxt_innertuple = econtext- > ecxt_outertuple; (gdb) 1712 if (aggstate- > input_done | | (gdb) (gdb) p * tmpcontext- > ecxt_innertupleCannot access memory at address 0x0
If the subpacket already exists, the projection is performed (the condition is not actually met).
(gdb) n1713 (node- > aggstrategy! = AGG_PLAIN & & (gdb) p node- > aggstrategy$18 = AGG_SORTED (gdb) n1712 if (aggstate- > input_done | | (gdb) 1714 aggstate- > projected_set! =-1 & & (gdb) 1713 (node- > aggstrategy! = AGG_PLAIN & & (gdb) 1732 aggstate- > projected_set = 0 (gdb) p aggstate- > input_done$19 = false (gdb) p aggstate- > projected_set$20 =-1 (gdb) p node- > aggstrategy$21 = AGG_SORTED (gdb)
Extract a line from outer plan and copy it as the first line
(gdb) n1738 if (aggstate- > grp_firstTuple = = NULL) (gdb) p aggstate- > grp_firstTuple$22 = (HeapTuple) 0x0 (gdb) n1740 outerslot = fetch_input_tuple (aggstate) (gdb) 1741 if (! TupIsNull (outerslot)) (gdb) p * outerslot$23 = {type = T_TupleTableSlot, tts_isempty = false, tts_shouldFree = false, tts_shouldFreeMin = false, tts_slow = false, tts_tuple = 0x26909f8, tts_tupleDescriptor = 0x26907a0, tts_mcxt = 0x268f310, tts_buffer = 0, tts_nvalid = 0, tts_values = 0x2690a18, tts_isnull = 0x2690a30, tts_mintuple = 0x26b8ad8, tts_minhdr = {t_len = 40 T_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 0}, t_tableOid = 0, t_data = 0x26b8ad0}, tts_off = 0, tts_fixedTupleDescriptor = true} (gdb) n1747 aggstate- > grp_firstTuple = ExecCopySlotTuple (outerslot) (gdb)
Initializes the working state for the newly entered tuple.
(gdb) 1797 initialize_aggregates (aggstate, pergroups, numReset)
Copy the tuple into the memory context and perform the aggregate operation (advance_aggregates)
(gdb) n1799 if (aggstate- > grp_firstTuple! = NULL) (gdb) 1806 ExecStoreTuple (aggstate- > grp_firstTuple, (gdb) 1810 aggstate- > grp_firstTuple = NULL; / * don't keep two pointers * / (gdb) 1813 tmpcontext- > ecxt_outertuple = firstSlot (gdb) 1825 if (aggstate- > aggstrategy = = AGG_MIXED & & (gdb) 1832 advance_aggregates (aggstate); (gdb) 1835 ResetExprContext (tmpcontext); (gdb)
Continue to extract rows and copy them to the memory context
(gdb) n1837 outerslot = fetch_input_tuple (aggstate); (gdb) 1838 if (TupIsNull (outerslot)) (gdb) 1853 tmpcontext- > ecxt_outertuple = outerslot; (gdb) 1859 if (node- > aggstrategy! = AGG_PLAIN) (gdb) 1861 tmpcontext- > ecxt_innertuple = firstSlot (gdb) 1862 if (! ExecQual (aggstate- > phase- > eqfunctions [numCols-> numCols-1], (gdb) 1869}
Perform the aggregate operation and continue to extract the next row
If (aggstate- > aggstrategy = = AGG_MIXED & & (gdb) 1832 advance_aggregates (aggstate); (gdb) 1835 ResetExprContext (tmpcontext); (gdb) 1837 outerslot = fetch_input_tuple (aggstate) (gdb) 1838 if (TupIsNull (outerslot)) (gdb) 1853 tmpcontext- > ecxt_outertuple = outerslot; (gdb) 1859 if (node- > aggstrategy! = AGG_PLAIN) (gdb) 1861 tmpcontext- > ecxt_innertuple = firstSlot; (gdb)
If it is a grouping, check whether it has crossed the packet boundary, such as jumping out of the loop.
1862 if (! ExecQual (aggstate- > phase- > eqfunctions [node-> numCols-1]), (gdb) 1865 aggstate- > grp_firstTuple = ExecCopySlotTuple (outerslot); (gdb) 1866 break
A row of result rows has been obtained and the result is returned
(gdb) 1880 econtext- > ecxt_outertuple = firstSlot; (gdb) n1883 Assert (aggstate- > projected_set > = 0); (gdb) 1885 currentSet = aggstate- > projected_set; (gdb) 1887 prepare_projection_slot (aggstate, econtext- > ecxt_outertuple, currentSet); (gdb) p aggstate- > projected_set$24 = 0 (gdb) n1889 select_current_set (aggstate, currentSet, false) (gdb) 1893 pergroups [currentSet]); (gdb) 1891 finalize_aggregates (aggstate, (gdb) 1899 result = project_aggregates (aggstate); (gdb) 1900 if (result) (gdb) 1901 return result (gdb) p * result$25 = {type = T_TupleTableSlot, tts_isempty = false, tts_shouldFree = false, tts_shouldFreeMin = false, tts_slow = false, tts_tuple = 0x0, tts_tupleDescriptor = 0x2690b38, tts_mcxt = 0x268f310, tts_buffer = 0, tts_nvalid = 4, tts_values = 0x2690db0, tts_isnull = 0x2690dd0, tts_mintuple = 0x0, tts_minhdr = {t_len = 0, t_self = {ip_blkid = {bi_hi = 0, bi_lo = 0} Ip_posid = 0}, t_tableOid = 0, t_data = 0x0}, tts_off = 0, tts_fixedTupleDescriptor = true} (gdb)
DONE!
IV. Reference materials
PostgreSQL Source Code interpretation (178)-query # 95 (aggregate function) # 1 related data structures
PostgreSQL Source Code interpretation-query # 102 (aggregate function # 7-advance_aggregates)