Interpretation of PostgreSQL Source Code-query # 97 (aggregate function # 2-ExecInitAgg)
Ss.ps); aggstate- > aggcontexts [I] = aggstate- > ss.ps.ps_ExprContext;} if (use_hashing) {ExecAssignExprContext (estate, & aggstate- > ss.ps); aggstate- > hashcontext = aggstate- > ss.ps.ps_ExprContext;} ExecAssignExprContext (estate, & aggstate- > ss.ps); / * Initialize child nodes. * initialize the child node * * If we are doing a hashed aggregation then the child plan does not need * to handle REWIND efficiently; see ExecReScanAgg. * if Hash aggregation algorithm is used, REWIND is not required for the sub-plan. For more information, please see ExecReScanAgg. * / if (node- > aggstrategy = = AGG_HASHED) eflags & = ~ EXEC_FLAG_REWIND; / / get outerPlan outerPlan = outerPlan (node); / / initialize outerPlan outerPlanState (aggstate) = ExecInitNode (outerPlan, estate, eflags); / * initialize source tuple type. * initialize the source tuple type * / ExecCreateScanSlotFromOuterPlan (estate, & aggstate- > ss); scanDesc = aggstate- > ss.ss_ScanTupleSlot- > tts_tupleDescriptor; if (node- > chain) aggstate- > sort_slot = ExecInitExtraTupleSlot (estate, scanDesc); / * Initialize result type, slot and projection. * initialize the result type, slot and projection * / ExecInitResultTupleSlotTL (estate, & aggstate- > ss.ps); ExecAssignProjectionInfo (& aggstate- > ss.ps, NULL); / * initialize child expressions * initialize the subexpression * * We expect the parser to have checked that no aggs contain other agg * calls in their arguments (and just to be sure, we verify it again while * initializing the plan node). This would make no sense under SQL * semantics, and it's forbidden by the spec. Because it is true, we * don't need to worry about evaluating the aggs in any particular order. * We expect that the parser has checked that no agg contains other agg calls in the parameters (verified when initializing the plan node, this time) * this does not make sense in SQL semantics, and the SQL specification forbids it. * because this is true, you will not need to worry about calculating the agg in any particular order. * * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState * nodes to aggstate- > aggs. Aggrefs in the qual are found here; Aggrefs * in the targetlist are found during ExecAssignProjectionInfo, below. * Note: execExpr.c will help us find Aggrefs and add AggrefExprState node to aggstate- > aggs. * the Aggrefs in the expression will be retrieved here and the Aggrefs in targetlist will be retrieved in the ExecAssignProjectionInfo below. * / aggstate- > ss.ps.qual = ExecInitQual (node- > plan.qual, (PlanState *) aggstate); / * We should now have found all Aggrefs in the targetlist and quals. * now we have retrieved all the Aggrefs in the projection column and expression. * / numaggs = aggstate- > numaggs; Assert (numaggs = = list_length (aggstate- > aggs)); / * For each phase, prepare grouping set data and fmgr lookup data for * compare functions. Accumulate all_grouped_cols in passing. * each phase requires the preparation of grouping set data and fmgr retrieval data for the comparison function. * by accumulating the cols of all packets. * / / allocate memory aggstate- > phases = palloc0 (numPhases * sizeof (AggStatePerPhaseData)); aggstate- > num_hashes = numHashes; if (numHashes) {aggstate- > perhash = palloc0 (sizeof (AggStatePerHashData) * numHashes); aggstate- > phases [0] .numsets = 0; aggstate- > phases [0] .gset _ lengths = palloc (numHashes * sizeof (int)); aggstate- > phases [0] .grouped _ cols = palloc (numHashes * sizeof (Bitmapset *)) } phase = 0; for (phaseidx = 0; phaseidx chain); + + phaseidx) {/ /-traverse each stage Agg * aggnode; Sort * sortnode If (phaseidx > 0) {/ / is not the first stage. Get node aggnode = list_nth_node (Agg, node- > chain, phaseidx-1) from the node linked list; / / sort node sortnode = castNode (Sort, aggnode- > plan.lefttree) } else {/ / the first stage, directly assign aggnode = node; sortnode = NULL } Assert (phase aggstrategy = = AGG_HASHED | | aggnode- > aggstrategy = = AGG_MIXED) {/ /-use Hash to aggregate / / phase data AggStatePerPhase phasedata = & aggstate- > phases [0]; AggStatePerHash perhash; Bitmapset * cols = NULL; Assert (phase = = 0) I = phasedata- > numsets++; perhash = & aggstate- > perhash [I]; / * phase 0 always points to the "real" Agg in the hash case * / / using Hash aggregation, phase 0 usually points to "actual" Agg phasedata- > aggnode = node; phasedata- > aggstrategy = node- > aggstrategy / * but the actual Agg node representing this hash is saved here * / / but the actual Agg nodes that represent the Hash are stored here perhash- > aggnode = aggnode; phasedata- > gset_ nodes [I] = perhash- > numCols = aggnode- > numCols; / / grouped columns are placed in the collection for (j = 0; j
< aggnode->NumCols; + + j) cols = bms_add_member (cols, aggnode- > grpColIdx [j]); / / stored in phase data phasedata- > grouped_ cols [I] = cols; / / add to large collection all_grouped_cols = bms_add_members (all_grouped_cols, cols); continue } else {/ / aggregate AggStatePerPhase phasedata = & aggstate- > phases [+ + phase] using Group; int num_sets; phasedata- > numsets = num_sets = list_length (aggnode- > groupingSets); if (num_sets) {phasedata- > gset_lengths = palloc (num_sets * sizeof (int)) Phasedata- > grouped_cols = palloc (num_sets * sizeof (Bitmapset *)); I = 0; foreach (l, aggnode- > groupingSets) {int current_length = list_length (lfirst (l)); Bitmapset * cols = NULL / * planner forces this to be correct * / for (j = 0; j
< current_length; ++j) cols = bms_add_member(cols, aggnode->GrpColIdx [j]); phasedata- > grouped_ cols [I] = cols; phasedata- > gset_ resolutions [I] = current_length; + + I;} all_grouped_cols = bms_add_members (all_grouped_cols, phasedata- > grouped_cols [0]) } else {Assert (phaseidx = = 0); phasedata- > gset_lengths = NULL; phasedata- > grouped_cols = NULL;} / * * If we are grouping, precompute fmgr lookup data for inner loop. * if you use GroupAggregate, calculate the fmgr retrieval data in advance for the inner loop * / if (aggnode- > aggstrategy = = AGG_SORTED) {int I = 0; Assert (aggnode- > numCols > 0); / * Build a separate function for each subset of columns that * need to be compared. * build independent functions for each subset of columns that need to be compared * / phasedata- > eqfunctions = (ExprState * *) palloc0 (aggnode- > numCols * sizeof (ExprState *)); / * for each grouping set * / / process for for each grouping set (I = 0; I
< phasedata->Numsets; iTunes +) {int length = phasedata- > gset_ resolutions [I]; if (phasedata- > eqfunctions [length-1]! = NULL) continue Phasedata- > eqfunctions [length-1] = execTuplesMatchPrepare (scanDesc, length, aggnode- > grpColIdx, aggnode- > grpOperators (PlanState *) aggstate) } / * and for all grouped columns, unless already computed * / / processes all columns that need to be grouped, unless the calculation of if (phasedata- > eqfunctions [aggnode-> numCols-1] = = NULL) {phasedata- > eqfunctions [aggnode-> numCols-1] = execTuplesMatchPrepare (scanDesc) has been completed Aggnode- > numCols, aggnode- > grpColIdx, aggnode- > grpOperators, (PlanState *) aggstate) } phasedata- > aggnode = aggnode; phasedata- > aggstrategy = aggnode- > aggstrategy; phasedata- > sortnode = sortnode;}} / * * Convert all_grouped_cols to a descending-order list. * convert all_grouped_cols to reverse linked list * / I =-1; while ((I = bms_next_member (all_grouped_cols, I)) > = 0) aggstate- > all_grouped_cols = lcons_int (I, aggstate- > all_grouped_cols) / * * Set up aggregate-result storage in the output expr context, and also * allocate my private per-agg working storage * set aggregate-result storage in the output expr context, and allocate private per-agg working storage * / econtext = aggstate- > ss.ps.ps_ExprContext; / / assign workspace econtext- > ecxt_aggvalues = (Datum *) palloc0 (sizeof (Datum) * numaggs) Econtext- > ecxt_aggnulls = (bool *) palloc0 (sizeof (bool) * numaggs); peraggs = (AggStatePerAgg) palloc0 (sizeof (AggStatePerAggData) * numaggs); pertransstates = (AggStatePerTrans) palloc0 (sizeof (AggStatePerTransData) * numaggs); aggstate- > peragg = peraggs; aggstate- > pertrans = pertransstates; aggstate- > all_pergroups = (AggStatePerGroup *) palloc0 (sizeof (AggStatePerGroup) * (numGroupingSets + numHashes)) Pergroups = aggstate- > all_pergroups; if (node- > aggstrategy! = AGG_HASHED) {/ /-aggregate for using Group (I = 0; I
< numGroupingSets; i++) { pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs); } aggstate-> < aggstate->Numphases; phaseidx++) {AggStatePerPhase phase = & aggstate- > phases [phaseidx]; bool dohash = false; bool dosort = false; / * phase 0 doesn't necessarily exist * / if (! phase- > aggnode) continue may not exist in the first stage If (aggstate- > aggstrategy = = AGG_MIXED & & phaseidx = = 1) {/ * Phase one, and only phase one, in a mixed agg performs both * sorting and aggregation. * if and only if stage 1, in mixed agg, perform sorting and aggregation. * / dohash = true; dosort = true } else if (aggstate- > aggstrategy = = AGG_MIXED & & phaseidx = = 0) {/ * No need to compute a transition function for an AGG_MIXED phase * 0-the contents of the hashtables will have been computed * during phase 1. * in the AGG_MIXED phase 0, there is no need to calculate the conversion function. * the contents of the hash table have been calculated in stage 1. * / continue;} else if (phase- > aggstrategy = = AGG_PLAIN | | phase- > aggstrategy = = AGG_SORTED) {dohash = false; dosort = true;} else if (phase- > aggstrategy = = AGG_HASHED) {dohash = true; dosort = false } else Assert (false); phase- > evaltrans = ExecBuildAggTrans (aggstate, phase, dosort, dohash);} return aggstate;} III. Tracking analysis
Test script
/ / disable parallel testdb=# set max_parallel_workers_per_gather=0;SETtestdb=# explain verbose select bh,avg (C1), min (C1), max (c2) from t_agg group by bh QUERY PLAN-HashAggregate (cost=13677.00..13677.06 rows=5 width=45) Output: bh Avg (C1), min (C1), max (c2) Group Key: t_agg.bh-> Seq Scan on public.t_agg (cost=0.00..8677.00 rows=500000 width=13) Output: bh, C1, c2, c3, c4, c5, c6 (5 rows)
Tracking and analysis
(gdb) b ExecInitAggBreakpoint 1 at 0x6eefc9: file nodeAgg.c, line 2096. (gdb) cContinuing.Breakpoint 1, ExecInitAgg (node=0x2d903a0, estate=0x2d52428, eflags=16) at nodeAgg.c:20962096 Bitmapset * all_grouped_cols = NULL; (gdb)
Input parameters
(gdb) p * node$1 = {plan = {type = T_Agg, startup_cost = 13677, total_cost = 13677.0625, plan_rows = 5, plan_width = 45, parallel_aware = false, parallel_safe = false, plan_node_id = 0, targetlist = 0x2d631f8, qual = 0x0, lefttree = 0x2d62cb8, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, numCols = 1, grpColIdx = 0x2d62fa8, grpOperators = grpOperators, 0x2d62f88 = 5, 0x2d62f88 = 0x2d62f88 GroupingSets = 0x0, chain = 0x0} (gdb) p * estate$2 = {type = T_EState, es_direction = ForwardScanDirection, es_snapshot = 0x2d00b80, es_crosscheck_snapshot = 0x0, es_range_table = 0x2d62ff0, es_plannedstmt = 0x2c72530, es_sourceText = 0x2c70d78 "select bh,avg (C1), min (C1), max (c2) from t_agg group by bh ", es_junkFilter = 0x0, es_output_cid = 0, es_result_relations = 0x0, es_num_result_relations = 0, es_result_relation_info = 0x0, es_root_result_relations = 0x0, es_num_root_result_relations = 0, es_tuple_routing_result_relations = 0x0, es_trig_target_relations = 0x0, es_trig_tuple_slot = 0x0, es_trig_oldtup_slot = 0x0, es_trig_newtup_slot = 0x0, es_param_list_info = 0x0 Es_param_exec_vals = 0x0, es_queryEnv = 0x0, es_query_cxt = 0x2d52310, es_tupleTable = 0x0, es_rowMarks = 0x0, es_processed = 0, es_lastoid = 0, es_top_eflags = 16, es_instrument = 0, es_finished = false, es_exprcontexts = 0x0, es_subplanstates = 0x0, es_auxmodifytables = 0x0, es_per_tuple_exprcontext = 0x0, es_epqTuple = 0x0, es_epqTupleSet = 0x0, es_epqScanDone = 0x0, es_use_parallel_mode = false Es_query_dsa = 0x0, es_jit_flags = 0, es_jit = 0x0, es_jit_worker_instr = 0x0} (gdb)
Using the Hash algorithm to calculate
(gdb) n2097 int numGroupingSets = 1; (gdb) 2100 int I = 0; (gdb) 2101 int j = 0; (gdb) 2102 bool use_hashing = (node- > aggstrategy = = AGG_HASHED | | (gdb) 2106 Assert (! (eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK); (gdb) p use_hashing$3 = true (gdb)
1. Initialize the AggState structure
(gdb) n2111 aggstate = makeNode (AggState); (gdb) 2112 aggstate- > ss.ps.plan = (Plan *) node; (gdb) 2113 aggstate- > ss.ps.state = estate; (gdb) 2114 aggstate- > ss.ps.ExecProcNode = ExecAgg; (gdb) 2116 aggstate- > aggs = NIL; (gdb) 2117 aggstate- > numaggs = 0; (gdb) 2118 aggstate- > numtrans = 0; (gdb) 2119 aggstate- > aggstrategy = node- > aggstrategy (gdb) 2120 aggstate- > aggsplit = node- > aggsplit; (gdb) 2121 aggstate- > maxsets = 0; (gdb) 2122 aggstate- > projected_set =-1; (gdb) 2123 aggstate- > current_set = 0; (gdb) 2124 aggstate- > peragg = NULL; (gdb) 2125 aggstate- > pertrans = NULL; (gdb) 2126 aggstate- > curperagg = NULL; (gdb) 2127 aggstate- > curpertrans = NULL; (gdb) 2128 aggstate- > input_done = false (gdb) 2129 aggstate- > agg_done = false; (gdb) 2130 aggstate- > pergroups = NULL; (gdb) 2131 aggstate- > grp_firstTuple = NULL; (gdb) 2132 aggstate- > sort_in = NULL; (gdb) 2133 aggstate- > sort_out = NULL (gdb) (gdb) p * aggstate$4 = {ss = {ps = {type = T_AggState, plan = 0x2d903a0, state = 0x2d52428, ExecProcNode = 0x6ee438, ExecProcNodeReal = 0x0, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x0, ps_ExprContext = 0x0, ps_ResultTupleSlot = 0x0, ps_ExprContext = ps_ExprContext, 0x0 = 0x0, ps_ProjInfo = ps_ProjInfo, ps_ProjInfo = 0x0 Ss_ScanTupleSlot = 0x0}, aggs = 0x0, numaggs = 0, numtrans = 0, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, phase = 0x0, numphases = 0, current_phase = 0, peragg = 0x0, pertrans = 0x0, hashcontext = 0x0, aggcontexts = 0x0, tmpcontext = 0x0, curaggcontext = 0x0, curperagg = 0x0, curpertrans = 0x0, input_done = false, agg_done = false, projected_set =-1, current_set = 0, grouped_cols = grouped_cols, grouped_cols = grouped_cols, 0x0 = 0, 0x0 = Sort_in = 0x0, sort_out = 0x0, sort_slot = 0x0, pergroups = 0x0, grp_firstTuple = 0x0, table_filled = false, num_hashes = 0, perhash = 0x0, hash_pergroup = 0x0, all_pergroups = 0x0, combinedproj = 0x0} (gdb)
two。 The calculation is divided into several stages (Hash vs Group)
(gdb) 2138 numPhases = (use_hashing? 1: 2); (gdb) p numPhases$5 = 1 (gdb) p numHashes$6 = 1 (gdb)
Hash only needs one phase to execute Hash
3. Initialize relevant information if grouping set exists
(gdb) n2168 aggstate- > maxsets = numGroupingSets
There is no grouping set here, and there is no need to initialize the relevant information.
4. Allocate memory context
(gdb) 2169 aggstate- > numphases = numPhases; (gdb) 2172 palloc0 (sizeof (ExprContext *) * numGroupingSets); (gdb) 2171 aggstate- > aggcontexts = (ExprContext * *) (gdb) 2188 ExecAssignExprContext (estate, & aggstate- > ss.ps); (gdb) 2189 aggstate- > tmpcontext = aggstate- > ss.ps.ps_ExprContext; (gdb) 2191 for (I = 0; I
< numGroupingSets; ++i)(gdb) 2193 ExecAssignExprContext(estate, &aggstate->Ss.ps); (gdb) 2194 aggstate- > aggcontexts [I] = aggstate- > ss.ps.ps_ExprContext; (gdb) 2191 for (I = 0; I
< numGroupingSets; ++i)(gdb) 2197 if (use_hashing)(gdb) 2199 ExecAssignExprContext(estate, &aggstate->Ss.ps); (gdb) 2200 aggstate- > hashcontext = aggstate- > ss.ps.ps_ExprContext; (gdb) 2203 ExecAssignExprContext (estate, & aggstate- > ss.ps); (gdb) 2211 if (node- > aggstrategy = = AGG_HASHED) (gdb) 2212 eflags & = EXEC_FLAG_REWIND; (gdb)
5. Initialize the outer plan child node
(gdb) 2213 outerPlan = outerPlan (node); (gdb) n2214 outerPlanState (aggstate) = ExecInitNode (outerPlan, estate, eflags); (gdb) p * outerPlan$7 = {type = T_SeqScan, startup_cost = 0, total_cost = 8677, plan_rows = 500000, plan_width = 13, parallel_aware = false, parallel_safe = false, plan_node_id = 1, targetlist = 0x2d62770, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, 0x0 = allParam}
Outer (left tree) node is SeqScan, sequential full table scan.
6. Initialize the result type, slot and projection
(gdb) n2219 ExecCreateScanSlotFromOuterPlan (estate, & aggstate- > ss); (gdb) n2220 scanDesc = aggstate- > ss.ss_ScanTupleSlot- > tts_tupleDescriptor (gdb) n2221 if (node- > chain) (gdb) p * aggstate$8 = {ss = {ps = {type = T_AggState, plan = 0x2d903a0, state = 0x2d52428, ExecProcNode = 0x6ee438, ExecProcNodeReal = 0x0, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, qual = 0x0, lefttree = 0x2d52bb0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, 0x0 = 0x0, ps_ResultTupleSlot = ps_ResultTupleSlot, 0x0 = 0x0, 0x0 = 0x0, 0x0 = 0x0 Ss_currentScanDesc = 0x0, ss_ScanTupleSlot = 0x2d53458}, aggs = 0x0, numaggs = 0, numtrans = 0, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, phase = 0x0, numphases = 1, current_phase = 0, peragg = 0x0, pertrans = 0x0, hashcontext = 0x2d52a30, aggcontexts = 0x2d52858, tmpcontext = 0x2d52878, curaggcontext = 0x0, curperagg = 0x0, curpertrans = 0x0, input_done = false, agg_done = false, false =-1, projected_set = 0, projected_set = current_set, current_set = current_set, current_set = 1 Phases = 0x0, sort_in = 0x0, sort_out = 0x0, sort_slot = 0x0, pergroups = 0x0, grp_firstTuple = 0x0, table_filled = false, num_hashes = 0, perhash = 0x0, hash_pergroup = 0x0, all_pergroups = 0x0, combinedproj = 0x0} (gdb) (gdb) p * scanDesc$9 = {natts = 7, tdtypeid = 2249, tdtypmod =-1, tdhasoid = false, tdrefcount =-1, constr = 0x0, attrs = 0x2d52f20} (0x2d52f20) p * gdb > gdb = {gdb = 7, gdb = 2249 Tdtypmod =-1, tdhasoid = false, tdrefcount =-1, constr = 0x0, attrs = 0x2d52f20} (gdb) (gdb) n2227 ExecInitResultTupleSlotTL (estate, & aggstate- > ss.ps) (gdb) 2228 ExecAssignProjectionInfo (& aggstate- > ss.ps, NULL); (gdb) 2244 ExecInitQual (node- > plan.qual, (PlanState *) aggstate) (gdb) p * aggstate$11 = {ss = {ps = {type = T_AggState, plan = 0x2d903a0, state = 0x2d52428, ExecProcNode = 0x6ee438, ExecProcNodeReal = 0x0, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, qual = 0x0, lefttree = 0x2d52bb0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2d537b0, ps_ExprContext = 0x2d52af0, 0x2d52af0 = 0x0, ps_ResultTupleSlot = 0x2d537b0, ps_ExprContext = 0x2d52af0, 0x2d52af0 = ps_ProjInfo, 0x2d538f0 = 0x2d538f0}, 0x2d538f0 = 0x2d538f0, scandesc =} Aggs = 0x2d53e00, numaggs = 3, numtrans = 0, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, phase = 0x0, numphases = 1, current_phase = 0, peragg = 0x0, pertrans = 0x0, hashcontext = 0x2d52a30, aggcontexts = 0x2d52858, tmpcontext = 0x2d52878, curaggcontext = 0x0, curperagg = 0x0, curpertrans = 0x0, input_done = false, agg_done = false, projected_set =-1, current_set = 0, grouped_cols = 0x0, all_grouped_cols = all_grouped_cols, all_grouped_cols = 1, 0x0 = 0x0, 0x0 = 0x0 Sort_out = 0x0, sort_slot = 0x0, pergroups = 0x0, grp_firstTuple = 0x0, table_filled = false, num_hashes = 0, perhash = 0x0, hash_pergroup = 0x0, all_pergroups = 0x0, combinedproj = 0x0} (gdb) p * aggstate- > ss.ps.scandesc$12 = {natts = 7, tdtypeid = 2249, tdtypmod =-1, tdhasoid = false, tdrefcount =-1, constr = 0x0, attrs = 0x2d52f20} # result: Slot (gdb) p * aggstate- > ss.ps.ps_ResultTupleSlot$13 = {ss.ps.ps_ResultTupleSlot$13 = type Tts_isempty = true, tts_shouldFree = false, tts_shouldFreeMin = false, tts_slow = false, tts_tuple = 0x0, tts_tupleDescriptor = 0x2d53598, tts_mcxt = 0x2d52310, tts_buffer = 0, tts_nvalid = 0, tts_values = 0x2d53810, tts_isnull = 0x2d53830, 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} # projection information (gdb) p * aggstate- > ss.ps.ps_ProjInfo$14 = {type = T_ProjectionInfo, pi_state = {tag = {type = T_ExprState}, flags = 6'\ 006, resnull = false, resvalue = 0, resultslot = 0x2d537b0, steps = 0x2d53988, evalfunc = 0x6cd882, expr = 0x2d631f8, evalfunc_private = 0x6cb43e, steps_len = 9, steps_alloc = 16, parent = 0x2d52640, ext_params = 0x0, innermost_caseval = 0x0 Innermost_casenull = 0x0, innermost_domainval = 0x0, innermost_domainnull = 0x0}, pi_exprContext = 0x2d52af0} (gdb)
7. Initialize subexpression
(gdb) n2243 aggstate- > ss.ps.qual = (gdb) 2249 numaggs = aggstate- > numaggs; (gdb) p * aggstate- > ss.ps.qualCannot access memory at address 0x0 (gdb) (gdb) n2250 Assert (numaggs = = list_length (aggstate- > aggs)); (gdb) p aggstate- > numaggs$16 = 3
The expression is NULL, with a total of three aggregate functions
8. Allocate memory for structures such as AggStatePerPhaseData/AggStatePerHashData
(gdb) n2256 aggstate- > phases = palloc0 (numPhases * sizeof (AggStatePerPhaseData)); (gdb) 2258 aggstate- > num_hashes = numHashes; (gdb) 2259 if (numHashes) (gdb) 2261 aggstate- > perhash = palloc0 (sizeof (AggStatePerHashData) * numHashes); (gdb) 2262 aggstate- > phases [0] .numsets = 0; (gdb) 2263 aggstate- > phases [0] .gset _ lengths = palloc (numHashes * sizeof (int)) (gdb) n2264 aggstate- > phases [0]. Grouped _ cols = palloc (numHashes * sizeof (Bitmapset *)); (gdb) 2267 phase = 0; (gdb) (gdb) p aggstate- > phases [0] $17 = {aggstrategy = AGG_PLAIN, numsets = 0, gset_lengths = 0x2d5
9. Cycle through each stage
Compute grouped columns, stored in the phasedata- > grouped_cols array and all_grouped_cols
Initialize the AggState- > phases array (the structure corresponding to the array element is AggStatePerPhase)
Initialize the AggState- > perhash array (the corresponding structure is AggStatePerHash)
(gdb) n2268 for (phaseidx = 0; phaseidx chain); + + phaseidx) (gdb) p list_length (node- > chain) $18 = 0 (gdb) n2273 if (phaseidx > 0) (gdb) 2280 aggnode = node (gdb) p * node$19 = {plan = {type = T_Agg, startup_cost = 13677, total_cost = 13677.0625, plan_rows = 5, plan_width = 45, parallel_aware = false, parallel_safe = false, plan_node_id = 0, targetlist = 0x2d631f8, qual = 0x0, lefttree = 0x2d62cb8, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, numCols = 1, grpColIdx = 0x2d62fa8, grpOperators = grpOperators, 0x2d62f88 = 5, 0x2d62f88 = 0x2d62f88 GroupingSets = 0x0, chain = 0x0} (gdb) n2281 sortnode = NULL (gdb) 2284 Assert (phase aggstrategy = = AGG_HASHED (gdb) 2289 AggStatePerPhase phasedata = & aggstate- > phases [0]; (gdb) 2291 Bitmapset * cols = NULL; (gdb) 2293 Assert (phase = = 0); (gdb) 2294 I = phasedata- > numsets++; (gdb) 2295 perhash = & aggstate- > perhash [I]; (gdb) 2298 phasedata- > aggnode = node (gdb) p * phasedata$20 = {aggstrategy = AGG_PLAIN, numsets = 1, gset_lengths = 0x2d53fe8, grouped_cols = 0x2d54008, eqfunctions = 0x0, aggnode = 0x0, sortnode = 0x0, evaltrans = 0x0} (gdb) pirou21 = 0 (gdb) n2299 phasedata- > aggstrategy = node- > aggstrategy; (gdb) 2302 perhash- > aggnode = aggnode; (gdb) 2304 phasedata- > gset_ recipes [I] = perhash- > numCols = aggnode- > numCols (gdb) 2306 for (j = 0; j
< aggnode->NumCols; + + j) (gdb) p aggnode- > numCols$22 = 1 (gdb) n2307 cols = bms_add_member (cols, aggnode- > grpColIdx [j]); (gdb) 2306 for (j = 0; j)
< aggnode->NumCols; + + j) (gdb) 2309 phasedata- > grouped_ cols [I] = cols; (gdb) p cols$23 = (Bitmapset *) 0x2d54028 (gdb) p * cols$24 = {nwords = 1, words = 0x2d5402c} (gdb) p * cols- > words$25 = 2 (gdb) n2311 all_grouped_cols = bms_add_members (all_grouped_cols, cols); (gdb) 2312 continue (gdb) p all_grouped_cols$26 = (Bitmapset *) 0x2d54048 (gdb) p * all_grouped_cols$27 = {nwords = 1, words = 0x2d5404c} (gdb) p * all_grouped_cols- > words$28 = 2 (gdb) n2268 for (phaseidx = 0; phaseidx chain); + + phaseidx) (gdb) 2406 I =-1
10. Convert all_grouped_cols to reverse linked list
2407 while ((I = bms_next_member (all_grouped_cols, I)) > = 0) (gdb) p * all_grouped_cols$29 = {nwords = 1, words = 0x2d5404c} (gdb) n2408 aggstate- > all_grouped_cols = lcons_int (I, aggstate- > all_grouped_cols); (gdb) 2407 while ((I = bms_next_member (all_grouped_cols, I) > = 0) (gdb)
11. Set up aggregate-result storage in the output expr context while allocating private per-agg working storage
(gdb) 2414 econtext = aggstate- > ss.ps.ps_ExprContext; (gdb) 2415 econtext- > ecxt_aggvalues = (Datum *) palloc0 (sizeof (Datum) * numaggs); (gdb) 2416 econtext- > ecxt_aggnulls = (bool *) palloc0 (sizeof (bool) * numaggs); (gdb) 2418 peraggs = (AggStatePerAgg) palloc0 (sizeof (AggStatePerAggData) * numaggs); (gdb) 2419 pertransstates = (AggStatePerTrans) palloc0 (sizeof (AggStatePerTransData) * numaggs) (gdb) 2421 aggstate- > peragg = peraggs; (gdb) 2422 aggstate- > pertrans = pertransstates; (gdb) 2427 * (numGroupingSets + numHashes); (gdb) 2426 (AggStatePerGroup *) palloc0 (sizeof (AggStatePerGroup) (gdb) 2425 aggstate- > all_pergroups = (gdb) 2428 pergroups = aggstate- > all_pergroups; (gdb) 2430 if (node- > aggstrategy! = AGG_HASHED) (gdb)
twelve。 If you use the Hash algorithm, call the find_hash_columns and build_hash_table methods to initialize the relevant data
(gdb) 2445 if (use_hashing) (gdb) 2448 aggstate- > hash_pergroup = pergroups; (gdb) 2450 find_hash_columns (aggstate); (gdb) 2451 build_hash_table (aggstate); (gdb) 2452 aggstate- > table_filled = false (gdb) 2461 if (node- > aggstrategy = = AGG_HASHED) (gdb) p * aggstate$30 = {ss = {ps = {type = T_AggState, plan = 0x2d903a0, state = 0x2d52428, ExecProcNode = 0x6ee438, ExecProcNodeReal = 0x0, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, qual = 0x0, lefttree = 0x2d52bb0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = chgParam, 0x0 = 0x0, 0x0 = ps_ResultTupleSlot, ps_ResultTupleSlot = ps_ResultTupleSlot, ps_ResultTupleSlot = 0x2d537b0} Ss_currentRelation = 0x0, ss_currentScanDesc = 0x0, ss_ScanTupleSlot = 0x2d53458}, aggs = 0x2d53e00, numaggs = 3, numtrans = 0, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, phase = 0x0, numphases = 1, current_phase = 0, peragg = 0x2d54770, pertrans = 0x2d56780, hashcontext = 0x2d52a30, aggcontexts = 0x2d52858, tmpcontext = 0x2d52878, curaggcontext = 0x0, curperagg = 0x0, curpertrans = 0x0, input_done = false, false = false, agg_done =-1, false = 0, agg_done = agg_done All_grouped_cols = 0x2d54090, maxsets = 1, phases = 0x2d53ef8, sort_in = 0x0, sort_out = 0x0, sort_slot = 0x0, pergroups = 0x0, grp_firstTuple = 0x0, table_filled = false, num_hashes = 1, perhash = 0x2d53f50, hash_pergroup = 0x2d54988, all_pergroups = 0x2d54988, combinedproj = 0x0} (gdb) p * aggstate- > perhash$31 = {hashtable = 0x2d54ad8, hashiter = {cur = 0, end = 0, done = false}, false = hashslot, hashslot = 0x2d54238, 0x2d54238 = 0x2d54238, 0x2d54238 = 1, 0x2d54238 = 1 LargestGrpColIdx = 1, hashGrpColIdxInput = 0x2d549f0, hashGrpColIdxHash = 0x2d54a10, aggnode = 0x2d903a0} (gdb) p * aggstate- > hash_pergroup$32 = (AggStatePerGroup) 0x0 (gdb) p * aggstate- > all_pergroups$33 = (AggStatePerGroup) 0x0 (gdb) p * aggstate- > phases$34 = {aggstrategy = AGG_HASHED, numsets = 1, gset_lengths = 0x2d53fe8, grouped_cols = 0x2d54008, eqfunctions = 0x0, aggnode = 0x2d903a0, sortnode = 0x0, evaltrans = 0x0} (gdb)
13. Call initialize_phase/select_current_set initialization phase data
(gdb) n2463 aggstate- > current_phase = 0; (gdb) 2464 initialize_phase (aggstate, 0); (gdb) 2465 select_current_set (aggstate, 0, true); (gdb) 2510 aggno =-1; (gdb) p * aggstate- > phases$35 = {aggstrategy = AGG_HASHED, numsets = 1, gset_lengths = 0x2d53fe8, grouped_cols = 0x2d54008, eqfunctions = 0x0, aggnode = 0x2d903a0, sortnode = 0x0, evaltrans = 0x0} (gdb)
14. Retrieve aggregate function information and initialize per-agg and per-trans data immutable fields
(gdb) n2463 aggstate- > current_phase = 0; (gdb) 2464 initialize_phase (aggstate, 0); (gdb) 2465 select_current_set (aggstate, 0, true); (gdb) 2510 aggno =-1; (gdb) p * aggstate- > phases$35 = {aggstrategy = AGG_HASHED, numsets = 1, gset_lengths = 0x2d53fe8, grouped_cols = 0x2d54008, eqfunctions = 0x0, aggnode = 0x2d903a0, sortnode = 0x0, evaltrans = 0x0} (gdb) n2511 transno =-1 (gdb) 2512 foreach (l, aggstate- > aggs) (gdb) 2514 AggrefExprState * aggrefstate = (AggrefExprState *) lfirst (l); (gdb) 2515 Aggref * aggref = aggrefstate- > aggref; (gdb) 2539 Assert (aggref- > agglevelsup = = 0) (gdb) p aggstate- > aggs$36 = (List *) 0x2d53e00 (gdb) p * aggstate- > aggs$37 = {type = T_List, length = 3, head = 0x2d53ed0, tail = 0x2d53dd8} (gdb) n2541 Assert (aggref- > aggsplit = = aggstate- > aggsplit); (gdb) 2544 existing_aggno = find_compatible_peragg (aggref, aggstate, aggno, (gdb) 2546 if (existing_aggno! =-1) (gdb) 2557 peragg = & peraggs [+ + aggno] (gdb) 2558 peragg- > aggref = aggref; (gdb) 2559 aggrefstate- > aggno = aggno; (gdb) 2563 ObjectIdGetDatum (aggref- > aggfnoid)) (gdb) 2562 aggTuple = SearchSysCache1 (AGGFNOID, (gdb) p aggref- > aggfnoid$38 = 2116 (gdb) n2564 if (! HeapTupleIsValid (aggTuple)) (gdb) p * aggTuple$39 = {t_len = 96, t_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 17}, t_tableOid = 2600, t_data = 0x7fa0c01f1630} (gdb) p * aggTuple- > t_data$40 = {t_choice = {t_heap = {t_xmin = 1, t_xmax = 0 T_field3 = {t_cid = 0, t_xvac = 0}}, t_datum = {datum_len_ = 1, datum_typmod = 0, datum_typeid = 0}}, t_ctid = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 17}, t_infomask2 = 22, t_infomask = 2305, t_hoff = 32' T_bits = 0x7fa0c01f1647 "\ 377\ 377\ 017"} (gdb) n2567 aggform = (Form_pg_aggregate) GETSTRUCT (aggTuple) (gdb) 2570 aclresult = pg_proc_aclcheck (aggref- > aggfnoid, GetUserId (), (gdb) p * aggform$41 = {aggfnoid = 2116, aggkind = 110 'nails, aggnumdirectargs = 0, aggtransfn = 768, aggfinalfn = 0, aggcombinefn = 768, aggserialfn = 0, aggdeserialfn = 0, aggmtransfn = 0, aggminvtransfn = 0, aggmfinalfn = 0, aggfinalextra = false, aggmfinalextra = false, aggfinalmodify = 114' rDNA, aggmfinalmodify = 114 'rDNA, aggsortop = 521, aggtranstype = 23, aggtransspace = 0, aggmtranstype = 0 Aggmtransspace = 0} (gdb) n2572 if (aclresult! = ACLCHECK_OK) (gdb) 2575 InvokeFunctionExecuteHook (aggref- > aggfnoid) (gdb) 2578 aggtranstype = aggref- > aggtranstype; (gdb) 2579 Assert (OidIsValid (aggtranstype)); (gdb) 2585 if (DO_AGGSPLIT_COMBINE (aggstate- > aggsplit)) (gdb) 2594 transfn_oid = aggform- > aggtransfn; (gdb) 2597 if (DO_AGGSPLIT_SKIPFINAL (aggstate- > aggsplit)) (gdb) p transfn_oid$42 = 768 (gdb) n2600 peragg- > finalfn_oid = finalfn_oid = aggform- > aggfinalfn (gdb) 2607 shareable = (aggform- > aggfinalmodify! = AGGMODIFY_READ_WRITE) | | (gdb) p aggform- > aggfinalfn$43 = 0 (gdb) n2609 peragg- > shareable = shareable; (gdb) 2611 serialfn_oid = InvalidOid; (gdb) p shareable$44 = true (gdb) n2612 deserialfn_oid = InvalidOid (gdb) 2618 if (aggtranstype = = INTERNALOID) (gdb) 2653 ObjectIdGetDatum (aggref- > aggfnoid)); (gdb) 2652 procTuple = SearchSysCache1 (PROCOID, (gdb) 2654 if (! HeapTupleIsValid (procTuple)) (gdb) 2657 aggOwner = (Form_pg_proc) GETSTRUCT (procTuple)-> proowner; (gdb) 2658 ReleaseSysCache (procTuple) (gdb) 2660 aclresult = pg_proc_aclcheck (transfn_oid, aggOwner, (gdb) 2662 if (aclresult! = ACLCHECK_OK) (gdb) 2665 InvokeFunctionExecuteHook (transfn_oid) (gdb) 2666 if (OidIsValid (finalfn_oid)) (gdb) 2675 if (OidIsValid (serialfn_oid)) (gdb) 2684 if (OidIsValid (deserialfn_oid)) (gdb) 2700 numArguments = get_aggregate_argtypes (aggref, inputTypes); (gdb) 2703 numDirectArgs = list_length (aggref- > aggdirectargs) (gdb) 2706 if (aggform- > aggfinalextra) (gdb) 2709 peragg- > numFinalArgs = numDirectArgs + 1 (gdb) 2712 peragg- > aggdirectargs = ExecInitExprList (aggref- > aggdirectargs, (gdb) 2719 if (OidIsValid (finalfn_oid)) (gdb) 2733 get_typlenbyval (aggref- > aggtype, (gdb) 2741 textInitVal = SysCacheGetAttr (AGGFNOID, aggTuple, (gdb) 2744 if (initValueIsNull) (gdb) 2745 initValue = (Datum) 0 (gdb) 2757 existing_transno = find_compatible_pertrans (aggstate, aggref, (gdb) 2763 if (existing_transno! =-1) (gdb) 2775 pertrans = & pertransactions [+ + transno]; (gdb) 2776 build_pertrans_for_aggref (pertrans, aggstate, estate, (gdb) 2781 peragg- > transno = transno; (gdb) 2783 ReleaseSysCache (aggTuple)) (gdb) 2512 foreach (l, aggstate- > aggs) (gdb) # testdb=# select oid,proname from pg_proc where oid in (2116768); oid | proname-+-768 | int4larger 2116 | max (2 rows) #
Next cycle
(gdb) p * aggref$45 = {xpr = {type = T_Aggref}, aggfnoid = 2132, aggtype = 23, aggcollid = 0, inputcollid = 0, aggtranstype = 23, aggargtypes = 0x2d63578, aggdirectargs = 0x0, args = 0x2d63688, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, aggstar = false, aggvariadic = false, aggkind = 110n, agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 18}. (gdb) p transfn_oid$49 = 769...testdb=# select oid,proname from pg_proc where oid in (2132769) Oid | proname-+-769 | int4smaller 2132 | min (2 rows)
The third cycle
(gdb) p * aggref$50 = {xpr = {type = T_Aggref}, aggfnoid = 2101, aggtype = 1700, aggcollid = 0, inputcollid = 0, aggtranstype = 1016, aggargtypes = 0x2d632f0, aggdirectargs = 0x0, args = 0x2d63400, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, aggstar = false, aggvariadic = false, aggkind = 110n, agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 10}. (gdb) p transfn_oid$51 = 1963.2512 foreach (l. Aggstate- > aggs) (gdb) # testdb=# select oid,proname from pg_proc where oid in (2101 and 1963) Oid | proname-+-1963 | int4_avg_accum 2101 | avg (2 rows) #
15. Build an expression that does all the conversion work at once.
(gdb) 2790 aggstate- > numaggs = aggno + 1; (gdb) 2791 aggstate- > numtrans = transno + 1; (gdb) 2803 if (numaggs! = list_length (aggstate- > aggs)) (gdb) 2815 for (phaseidx = 0; phaseidx)
< aggstate->Numphases; phaseidx++) (gdb) 2817 AggStatePerPhase phase = & aggstate- > phases [phaseidx]; (gdb) 2818 bool dohash = false; (gdb) 2819 bool dosort = false (gdb) 2822 if (! phase- > aggnode) (gdb) 2825 if (aggstate- > aggstrategy = = AGG_MIXED & & phaseidx = = 1) (gdb) 2834 else if (aggstate- > aggstrategy = = AGG_MIXED & & phaseidx = = 0) (gdb) 2843 else if (phase- > aggstrategy = = AGG_PLAIN | | (gdb) 2844 phase- > aggstrategy = AGG_SORTED) (gdb) 2843 else if (phase -> aggstrategy = = AGG_PLAIN | | (gdb) 2849 else if (phase- > aggstrategy = = AGG_HASHED) (gdb) 2851 dohash = true (gdb) 2852 dosort = false; (gdb) 2857 phase- > evaltrans = ExecBuildAggTrans (aggstate, phase, dosort, dohash); (gdb) 2815 for (phaseidx = 0; phaseidx)
< aggstate->Numphases; phaseidx++) (gdb) 2861 return aggstate; (gdb)
The final result
AggState structure
(gdb) p * aggstate$52 = {ss = {ps = {type = T_AggState, plan = 0x2d903a0, state = 0x2d52428, ExecProcNode = 0x6ee438, ExecProcNodeReal = 0x0, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, qual = 0x0, lefttree = 0x2d52bb0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2d537b0, ps_ExprContext = 0x2d52af0, 0x2d52af0 = 0x0, ps_ResultTupleSlot = 0x2d537b0, ps_ExprContext = 0x2d52af0, 0x2d52af0 = ps_ProjInfo, 0x2d538f0 = 0x2d538f0}, 0x2d538f0 = 0x2d538f0, scandesc =} Aggs = 0x2d53e00, numaggs = 3, numtrans = 3, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, phase = 0x2d53ef8, numphases = 1, current_phase = 0, peragg = 0x2d54770, pertrans = 0x2d56780, hashcontext = 0x2d52a30, aggcontexts = 0x2d52858, tmpcontext = 0x2d52878, curaggcontext = 0x2d52a30, curperagg = 0x0, curpertrans = 0x0, input_done = false, agg_done = false, projected_set =-1, current_set = 0, grouped_cols = 0x0, all_grouped_cols = all_grouped_cols, all_grouped_cols = 1, 0x2d54090 = 0x2d54090, 0x2d54090 = 0x2d54090 Sort_out = 0x0, sort_slot = 0x0, pergroups = 0x0, grp_firstTuple = 0x0, table_filled = false, num_hashes = 1, perhash = 0x2d53f50, hash_pergroup = 0x2d54988, all_pergroups = 0x2d54988, combinedproj = 0x0}
AggState- > phase
(gdb) p * aggstate- > phase$53 = {aggstrategy = AGG_HASHED, numsets = 1, gset_lengths = 0x2d53fe8, grouped_cols = 0x2d54008, eqfunctions = 0x0, aggnode = 0x2d903a0, sortnode = 0x0, evaltrans = 0x2d55e78}
AggState- > peragg
(gdb) p * aggstate- > peragg$54 = {aggref = 0x2d63740, transno = 0, finalfn_oid = 0, finalfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000others, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, numFinalArgs = 1, aggdirectargs = 0x0, resulttypeLen = 4, resulttypeByVal = true, shareable = true} (gdb) p * aggstate- > peragg- > aggref$55 = {xpr = {xpr = type} Aggfnoid = 2116, aggtype = 23, aggcollid = 0, inputcollid = 0, aggtranstype = 23, aggargtypes = 0x2d63800, aggdirectargs = 0x0, args = 0x2d63910, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, aggstar = false, aggvariadic = false, aggkind = false, agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 26} (gdb) p aggstate- > peragg [1] $56 = {aggref = 0x2d634b8, transno = 1, finalfn_oid = 0, finalfn = {fn_addr = 0x0, 0x0 = 0, fn_oid = 0, fn_oid = fn_nargs Fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, numFinalArgs = 1, aggdirectargs = 0x0, resulttypeLen = 4, resulttypeByVal = true, shareable = true} (gdb) p * aggstate- > peragg [1]-> aggref$57 = {xpr = {type = T_Aggref}, aggfnoid = 2132, aggtype = 23, aggcollid = 0, inputcollid = 0, aggtranstype = 23, aggargtypes = 0x2d63578, aggdirectargs = 0x0, args = 0x2d63688, aggorder = 0x0, 0x0 = 0x0, 0x0 = aggdistinct, aggdistinct = aggdistinct Aggvariadic = false, aggkind = 110 'nails, agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 18} (gdb) p aggstate- > peragg [2] $58 = {aggref = 0x2d63230, transno = 2, finalfn_oid = 1964, finalfn = {fn_addr = 0x978251, fn_oid = 1964, fn_nargs = 1, fn_strict = true, fn_retset = false, fn_stats = 2'\ 002, fn_extra = 0x0, fn_mcxt = 0x2d52310, fn_expr = 0x2d55b80}, numFinalArgs = 1, aggdirectargs = 0x0, resulttypeLen =-1 ResulttypeByVal = false, shareable = true} (gdb) p * aggstate- > peragg [2]-> aggref$59 = {xpr = {type = T_Aggref}, aggfnoid = 2101, aggtype = 1700, aggcollid = 0, inputcollid = 0, aggtranstype = 1016, aggargtypes = 0x2d632f0, aggdirectargs = 0x0, args = 0x2d63400, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, aggstar = false, aggvariadic = false, aggkind = 110ncy, agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, AGGSPLIT_SIMPLE = 10}
AggState- > pertrans
(gdb) p aggstate- > pertrans [0] $60 = {aggref = 0x2d63740, aggshared = false, numInputs = 1, numTransInputs = 1, transfn_oid = 768, serialfn_oid = 0, deserialfn_oid = 0, aggtranstype = 23, transfn = {fn_addr = 0x93e877, fn_oid = 768, fn_nargs = 2, fn_strict = true, fn_retset = false, fn_stats = 2'\ 002, fn_extra = 0x0, fn_mcxt = 0x2d52310, fn_expr = 0x2d55940}, serialfn = {fn_addr = 0x0, fn_oid = 0 Fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, deserialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, aggCollation = 0, numSortCols = 0, numDistinctCols = 0, sortColIdx = 0x0 SortOperators = 0x0, sortCollations = 0x0, sortNullsFirst = 0x0, equalfnOne = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, equalfnMulti = 0x0, initValue = 0, initValueIsNull = true, inputtypeLen = 0, transtypeLen = 4, inputtypeByVal = false, transtypeByVal = true, sortslot = 0x0, uniqslot = uniqslot, 0x0 = 0x0, 0x0 = sortdesc, sortdesc = sortdesc Context = 0x2d52640, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {0}, argnull = {false}}, serialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, arg = {0}, argnull = {false}}, deserialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, nargs = {0} Argnull = {false}} (gdb) p aggstate- > pertrans [1] $61 = {aggref = 0x2d634b8, aggshared = false, numInputs = 1, numTransInputs = 1, transfn_oid = 769, serialfn_oid = 0, deserialfn_oid = 0, aggtranstype = 23, transfn = {fn_addr = 0x93e8a3, fn_oid = 769, fn_nargs = 2, fn_strict = true, fn_retset = false, fn_stats = 2'\ 002, fn_extra = 0x0, fn_mcxt = 0x2d52310, fn_expr = 0x2d55a90} Serialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, deserialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0} AggCollation = 0, numSortCols = 0, numDistinctCols = 0, sortColIdx = 0x0, sortOperators = 0x0, sortCollations = 0x0, sortNullsFirst = 0x0, equalfnOne = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, equalfnMulti = 0x0, initValue = 0, initValueIsNull = true, inputtypeLen = 0, transtypeLen = 4, inputtypeByVal = false, false = transtypeByVal, transtypeByVal = transtypeByVal, transtypeByVal = transtypeByVal Sortdesc = 0x0, sortstates = 0x2d549d0, transfn_fcinfo = {flinfo = 0x2d573f0, context = 0x2d52640, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {0}, argnull = {false}}, serialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, arg = {0}, argnull = {false}, deserialfn_fcinfo = {flinfo = 0x0, context = context, 0x0 = 0x0, 0x0 = 0, resultinfo = 0 Arg = {0}, argnull = {false}} (gdb) p aggstate- > pertrans [2] $62 = {aggref = 0x2d63230, aggshared = false, numInputs = 1, numTransInputs = 1, transfn_oid = 1963, serialfn_oid = 0, deserialfn_oid = 0, aggtranstype = 1016, transfn = {fn_addr = 0x977d8f, fn_oid = 1963, fn_nargs = 2, fn_strict = true, fn_retset = false, fn_stats = 2'\ 002, fn_extra = 0x0, fn_mcxt = 0x2d52310, fn_expr = 0x2d55e20} Serialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, deserialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0} AggCollation = 0, numSortCols = 0, numDistinctCols = 0, sortColIdx = 0x0, sortOperators = 0x0, sortCollations = 0x0, sortNullsFirst = 0x0, equalfnOne = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0'\ 000mm, fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, equalfnMulti = 0x0, initValue = 47537400, initValueIsNull = false, inputtypeLen = 0, transtypeLen =-1, inputtypeByVal = false, transtypeByVal = transtypeByVal, transtypeByVal = transtypeByVal Uniqslot = 0x0, sortdesc = 0x0, sortstates = 0x2d55bd8, transfn_fcinfo = {flinfo = 0x2d58038, context = 0x2d52640, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {0}, argnull = {false}}, serialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, arg = {0}, argnull = {false}}, deserialfn_fcinfo = {flinfo = flinfo, 0x0 = 0x0, context = context, context = 0, context = context, = 0 Arg = {0}, argnull = {false}
AggState- > groups related
(gdb) p * aggstate- > pergroupsCannot access memory at address 0x0 (gdb) p * aggstate- > hash_pergroup$65 = (AggStatePerGroup) 0x0 (gdb) p * aggstate- > all_pergroups$66 = (AggStatePerGroup) 0x0
AggState- > perhash
(gdb) p * aggstate- > perhash$67 = {hashtable = 0x2d54ad8, hashiter = {cur = 0, end = 0, done = false}, hashslot = 0x2d54238, hashfunctions = 0x2d542d0, eqfuncoids = 0x2d54a90, numCols = 1, numhashGrpCols = 1, largestGrpColIdx = 1, hashGrpColIdxInput = 0x2d549f0, hashGrpColIdxHash = 0x2d54a10, aggnode = 0x2d903a0} (gdb) p * aggstate- > perhash- > hashtable$68 = {hashtab = 0x2d54b70, numCols = 1, keyColIdx = 0x2d54a10, tab_hash_funcs = 0x2d542d0, 0x2d542d0 = 0x2d542d0, tab_eq_func = tab_eq_func, tab_eq_func = 0x2d54e90, tablecxt = 24, 0x2d54e90 = 0x2d54e90, = In_hash_funcs = 0x0, cur_eq_func = 0x0, hash_iv = 0, exprcontext = 0x2d557b0} (gdb) p * aggstate- > perhash- > hashfunctions$69 = {fn_addr = 0x4c8a31, fn_oid = 400, fn_nargs = 1, fn_strict = true, fn_retset = false, fn_stats = 2'\ 002, fn_extra = 0x0, fn_mcxt = 0x2d52310, fn_expr = 0x0}
DONE!
There are still many details to sort out.
IV. Reference materials
N/A