* ExecAgg for non-hashed case */
| 2377 | * ExecAgg for non-hashed case |
| 2378 | */ |
| 2379 | static TupleTableSlot * |
| 2380 | agg_retrieve_direct(AggState *aggstate) |
| 2381 | { |
| 2382 | Agg *node = aggstate->phase->aggnode; |
| 2383 | ExprContext *econtext; |
| 2384 | ExprContext *tmpcontext; |
| 2385 | AggStatePerAgg peragg; |
| 2386 | AggStatePerGroup *pergroups; |
| 2387 | TupleTableSlot *outerslot; |
| 2388 | TupleTableSlot *firstSlot; |
| 2389 | TupleTableSlot *result; |
| 2390 | bool hasGroupingSets = aggstate->phase->numsets > 0; |
| 2391 | int numGroupingSets = Max(aggstate->phase->numsets, 1); |
| 2392 | int currentSet; |
| 2393 | int nextSetSize; |
| 2394 | int numReset; |
| 2395 | int i; |
| 2396 | |
| 2397 | /* |
| 2398 | * get state info from node |
| 2399 | * |
| 2400 | * econtext is the per-output-tuple expression context |
| 2401 | * |
| 2402 | * tmpcontext is the per-input-tuple expression context |
| 2403 | */ |
| 2404 | econtext = aggstate->ss.ps.ps_ExprContext; |
| 2405 | tmpcontext = aggstate->tmpcontext; |
| 2406 | |
| 2407 | peragg = aggstate->peragg; |
| 2408 | pergroups = aggstate->pergroups; |
| 2409 | firstSlot = aggstate->ss.ss_ScanTupleSlot; |
| 2410 | |
| 2411 | /* |
| 2412 | * We loop retrieving groups until we find one matching |
| 2413 | * aggstate->ss.ps.qual |
| 2414 | * |
| 2415 | * For grouping sets, we have the invariant that aggstate->projected_set |
| 2416 | * is either -1 (initial call) or the index (starting from 0) in |
| 2417 | * gset_lengths for the group we just completed (either by projecting a |
| 2418 | * row or by discarding it in the qual). |
| 2419 | */ |
| 2420 | while (!aggstate->agg_done) |
| 2421 | { |
| 2422 | /* |
| 2423 | * Clear the per-output-tuple context for each group, as well as |
| 2424 | * aggcontext (which contains any pass-by-ref transvalues of the old |
| 2425 | * group). Some aggregate functions store working state in child |
| 2426 | * contexts; those now get reset automatically without us needing to |
| 2427 | * do anything special. |
| 2428 | * |
| 2429 | * We use ReScanExprContext not just ResetExprContext because we want |
| 2430 | * any registered shutdown callbacks to be called. That allows |
| 2431 | * aggregate functions to ensure they've cleaned up any non-memory |
| 2432 | * resources. |
| 2433 | */ |
| 2434 | ReScanExprContext(econtext); |
| 2435 | |
| 2436 | /* |
no test coverage detected