00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 #include "postgres.h"
00080
00081 #include "access/htup_details.h"
00082 #include "catalog/objectaccess.h"
00083 #include "catalog/pg_aggregate.h"
00084 #include "catalog/pg_proc.h"
00085 #include "catalog/pg_type.h"
00086 #include "executor/executor.h"
00087 #include "executor/nodeAgg.h"
00088 #include "miscadmin.h"
00089 #include "nodes/nodeFuncs.h"
00090 #include "optimizer/clauses.h"
00091 #include "optimizer/tlist.h"
00092 #include "parser/parse_agg.h"
00093 #include "parser/parse_coerce.h"
00094 #include "utils/acl.h"
00095 #include "utils/builtins.h"
00096 #include "utils/lsyscache.h"
00097 #include "utils/memutils.h"
00098 #include "utils/syscache.h"
00099 #include "utils/tuplesort.h"
00100 #include "utils/datum.h"
00101
00102
00103
00104
00105
00106 typedef struct AggStatePerAggData
00107 {
00108
00109
00110
00111
00112
00113
00114 AggrefExprState *aggrefstate;
00115 Aggref *aggref;
00116
00117
00118 int numArguments;
00119
00120
00121 int numInputs;
00122
00123
00124 Oid transfn_oid;
00125 Oid finalfn_oid;
00126
00127
00128
00129
00130
00131
00132 FmgrInfo transfn;
00133 FmgrInfo finalfn;
00134
00135
00136 Oid aggCollation;
00137
00138
00139 int numSortCols;
00140
00141
00142
00143 int numDistinctCols;
00144
00145
00146 AttrNumber *sortColIdx;
00147 Oid *sortOperators;
00148 Oid *sortCollations;
00149 bool *sortNullsFirst;
00150
00151
00152
00153
00154
00155
00156 FmgrInfo *equalfns;
00157
00158
00159
00160
00161 Datum initValue;
00162 bool initValueIsNull;
00163
00164
00165
00166
00167
00168
00169
00170
00171 int16 inputtypeLen,
00172 resulttypeLen,
00173 transtypeLen;
00174 bool inputtypeByVal,
00175 resulttypeByVal,
00176 transtypeByVal;
00177
00178
00179
00180
00181
00182
00183
00184 TupleDesc evaldesc;
00185 ProjectionInfo *evalproj;
00186
00187
00188
00189
00190
00191 TupleTableSlot *evalslot;
00192 TupleTableSlot *uniqslot;
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 Tuplesortstate *sortstate;
00207 } AggStatePerAggData;
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 typedef struct AggStatePerGroupData
00226 {
00227 Datum transValue;
00228 bool transValueIsNull;
00229
00230 bool noTransValue;
00231
00232
00233
00234
00235
00236
00237
00238
00239 } AggStatePerGroupData;
00240
00241
00242
00243
00244
00245
00246
00247 typedef struct AggHashEntryData *AggHashEntry;
00248
00249 typedef struct AggHashEntryData
00250 {
00251 TupleHashEntryData shared;
00252
00253 AggStatePerGroupData pergroup[1];
00254 } AggHashEntryData;
00255
00256
00257 static void initialize_aggregates(AggState *aggstate,
00258 AggStatePerAgg peragg,
00259 AggStatePerGroup pergroup);
00260 static void advance_transition_function(AggState *aggstate,
00261 AggStatePerAgg peraggstate,
00262 AggStatePerGroup pergroupstate,
00263 FunctionCallInfoData *fcinfo);
00264 static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
00265 static void process_ordered_aggregate_single(AggState *aggstate,
00266 AggStatePerAgg peraggstate,
00267 AggStatePerGroup pergroupstate);
00268 static void process_ordered_aggregate_multi(AggState *aggstate,
00269 AggStatePerAgg peraggstate,
00270 AggStatePerGroup pergroupstate);
00271 static void finalize_aggregate(AggState *aggstate,
00272 AggStatePerAgg peraggstate,
00273 AggStatePerGroup pergroupstate,
00274 Datum *resultVal, bool *resultIsNull);
00275 static Bitmapset *find_unaggregated_cols(AggState *aggstate);
00276 static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
00277 static void build_hash_table(AggState *aggstate);
00278 static AggHashEntry lookup_hash_entry(AggState *aggstate,
00279 TupleTableSlot *inputslot);
00280 static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
00281 static void agg_fill_hash_table(AggState *aggstate);
00282 static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
00283 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
00284
00285
00286
00287
00288
00289
00290
00291 static void
00292 initialize_aggregates(AggState *aggstate,
00293 AggStatePerAgg peragg,
00294 AggStatePerGroup pergroup)
00295 {
00296 int aggno;
00297
00298 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
00299 {
00300 AggStatePerAgg peraggstate = &peragg[aggno];
00301 AggStatePerGroup pergroupstate = &pergroup[aggno];
00302
00303
00304
00305
00306 if (peraggstate->numSortCols > 0)
00307 {
00308
00309
00310
00311
00312 if (peraggstate->sortstate)
00313 tuplesort_end(peraggstate->sortstate);
00314
00315
00316
00317
00318
00319
00320 peraggstate->sortstate =
00321 (peraggstate->numInputs == 1) ?
00322 tuplesort_begin_datum(peraggstate->evaldesc->attrs[0]->atttypid,
00323 peraggstate->sortOperators[0],
00324 peraggstate->sortCollations[0],
00325 peraggstate->sortNullsFirst[0],
00326 work_mem, false) :
00327 tuplesort_begin_heap(peraggstate->evaldesc,
00328 peraggstate->numSortCols,
00329 peraggstate->sortColIdx,
00330 peraggstate->sortOperators,
00331 peraggstate->sortCollations,
00332 peraggstate->sortNullsFirst,
00333 work_mem, false);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 if (peraggstate->initValueIsNull)
00343 pergroupstate->transValue = peraggstate->initValue;
00344 else
00345 {
00346 MemoryContext oldContext;
00347
00348 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
00349 pergroupstate->transValue = datumCopy(peraggstate->initValue,
00350 peraggstate->transtypeByVal,
00351 peraggstate->transtypeLen);
00352 MemoryContextSwitchTo(oldContext);
00353 }
00354 pergroupstate->transValueIsNull = peraggstate->initValueIsNull;
00355
00356
00357
00358
00359
00360
00361
00362
00363 pergroupstate->noTransValue = peraggstate->initValueIsNull;
00364 }
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static void
00377 advance_transition_function(AggState *aggstate,
00378 AggStatePerAgg peraggstate,
00379 AggStatePerGroup pergroupstate,
00380 FunctionCallInfoData *fcinfo)
00381 {
00382 int numArguments = peraggstate->numArguments;
00383 MemoryContext oldContext;
00384 Datum newVal;
00385 int i;
00386
00387 if (peraggstate->transfn.fn_strict)
00388 {
00389
00390
00391
00392
00393 for (i = 1; i <= numArguments; i++)
00394 {
00395 if (fcinfo->argnull[i])
00396 return;
00397 }
00398 if (pergroupstate->noTransValue)
00399 {
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
00410 pergroupstate->transValue = datumCopy(fcinfo->arg[1],
00411 peraggstate->transtypeByVal,
00412 peraggstate->transtypeLen);
00413 pergroupstate->transValueIsNull = false;
00414 pergroupstate->noTransValue = false;
00415 MemoryContextSwitchTo(oldContext);
00416 return;
00417 }
00418 if (pergroupstate->transValueIsNull)
00419 {
00420
00421
00422
00423
00424
00425
00426 return;
00427 }
00428 }
00429
00430
00431 oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
00432
00433
00434
00435
00436 InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
00437 numArguments + 1,
00438 peraggstate->aggCollation,
00439 (void *) aggstate, NULL);
00440 fcinfo->arg[0] = pergroupstate->transValue;
00441 fcinfo->argnull[0] = pergroupstate->transValueIsNull;
00442
00443 newVal = FunctionCallInvoke(fcinfo);
00444
00445
00446
00447
00448
00449
00450 if (!peraggstate->transtypeByVal &&
00451 DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
00452 {
00453 if (!fcinfo->isnull)
00454 {
00455 MemoryContextSwitchTo(aggstate->aggcontext);
00456 newVal = datumCopy(newVal,
00457 peraggstate->transtypeByVal,
00458 peraggstate->transtypeLen);
00459 }
00460 if (!pergroupstate->transValueIsNull)
00461 pfree(DatumGetPointer(pergroupstate->transValue));
00462 }
00463
00464 pergroupstate->transValue = newVal;
00465 pergroupstate->transValueIsNull = fcinfo->isnull;
00466
00467 MemoryContextSwitchTo(oldContext);
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 static void
00479 advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
00480 {
00481 int aggno;
00482
00483 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
00484 {
00485 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
00486 AggStatePerGroup pergroupstate = &pergroup[aggno];
00487 int nargs = peraggstate->numArguments;
00488 int i;
00489 TupleTableSlot *slot;
00490
00491
00492 slot = ExecProject(peraggstate->evalproj, NULL);
00493
00494 if (peraggstate->numSortCols > 0)
00495 {
00496
00497 Assert(slot->tts_nvalid == peraggstate->numInputs);
00498
00499
00500
00501
00502
00503
00504
00505
00506 if (peraggstate->transfn.fn_strict)
00507 {
00508 for (i = 0; i < nargs; i++)
00509 {
00510 if (slot->tts_isnull[i])
00511 break;
00512 }
00513 if (i < nargs)
00514 continue;
00515 }
00516
00517
00518 if (peraggstate->numInputs == 1)
00519 tuplesort_putdatum(peraggstate->sortstate,
00520 slot->tts_values[0],
00521 slot->tts_isnull[0]);
00522 else
00523 tuplesort_puttupleslot(peraggstate->sortstate, slot);
00524 }
00525 else
00526 {
00527
00528 FunctionCallInfoData fcinfo;
00529
00530
00531
00532 Assert(slot->tts_nvalid >= nargs);
00533 for (i = 0; i < nargs; i++)
00534 {
00535 fcinfo.arg[i + 1] = slot->tts_values[i];
00536 fcinfo.argnull[i + 1] = slot->tts_isnull[i];
00537 }
00538
00539 advance_transition_function(aggstate, peraggstate, pergroupstate,
00540 &fcinfo);
00541 }
00542 }
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 static void
00566 process_ordered_aggregate_single(AggState *aggstate,
00567 AggStatePerAgg peraggstate,
00568 AggStatePerGroup pergroupstate)
00569 {
00570 Datum oldVal = (Datum) 0;
00571 bool oldIsNull = true;
00572 bool haveOldVal = false;
00573 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
00574 MemoryContext oldContext;
00575 bool isDistinct = (peraggstate->numDistinctCols > 0);
00576 Datum *newVal;
00577 bool *isNull;
00578 FunctionCallInfoData fcinfo;
00579
00580 Assert(peraggstate->numDistinctCols < 2);
00581
00582 tuplesort_performsort(peraggstate->sortstate);
00583
00584
00585 newVal = fcinfo.arg + 1;
00586 isNull = fcinfo.argnull + 1;
00587
00588
00589
00590
00591
00592
00593
00594 while (tuplesort_getdatum(peraggstate->sortstate, true,
00595 newVal, isNull))
00596 {
00597
00598
00599
00600
00601 MemoryContextReset(workcontext);
00602 oldContext = MemoryContextSwitchTo(workcontext);
00603
00604
00605
00606
00607
00608
00609 if (isDistinct &&
00610 haveOldVal &&
00611 ((oldIsNull && *isNull) ||
00612 (!oldIsNull && !*isNull &&
00613 DatumGetBool(FunctionCall2(&peraggstate->equalfns[0],
00614 oldVal, *newVal)))))
00615 {
00616
00617 if (!peraggstate->inputtypeByVal && !*isNull)
00618 pfree(DatumGetPointer(*newVal));
00619 }
00620 else
00621 {
00622 advance_transition_function(aggstate, peraggstate, pergroupstate,
00623 &fcinfo);
00624
00625 if (!oldIsNull && !peraggstate->inputtypeByVal)
00626 pfree(DatumGetPointer(oldVal));
00627
00628 oldVal = *newVal;
00629 oldIsNull = *isNull;
00630 haveOldVal = true;
00631 }
00632
00633 MemoryContextSwitchTo(oldContext);
00634 }
00635
00636 if (!oldIsNull && !peraggstate->inputtypeByVal)
00637 pfree(DatumGetPointer(oldVal));
00638
00639 tuplesort_end(peraggstate->sortstate);
00640 peraggstate->sortstate = NULL;
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 static void
00653 process_ordered_aggregate_multi(AggState *aggstate,
00654 AggStatePerAgg peraggstate,
00655 AggStatePerGroup pergroupstate)
00656 {
00657 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
00658 FunctionCallInfoData fcinfo;
00659 TupleTableSlot *slot1 = peraggstate->evalslot;
00660 TupleTableSlot *slot2 = peraggstate->uniqslot;
00661 int numArguments = peraggstate->numArguments;
00662 int numDistinctCols = peraggstate->numDistinctCols;
00663 bool haveOldValue = false;
00664 int i;
00665
00666 tuplesort_performsort(peraggstate->sortstate);
00667
00668 ExecClearTuple(slot1);
00669 if (slot2)
00670 ExecClearTuple(slot2);
00671
00672 while (tuplesort_gettupleslot(peraggstate->sortstate, true, slot1))
00673 {
00674
00675
00676
00677
00678 slot_getsomeattrs(slot1, numArguments);
00679
00680 if (numDistinctCols == 0 ||
00681 !haveOldValue ||
00682 !execTuplesMatch(slot1, slot2,
00683 numDistinctCols,
00684 peraggstate->sortColIdx,
00685 peraggstate->equalfns,
00686 workcontext))
00687 {
00688
00689
00690 for (i = 0; i < numArguments; i++)
00691 {
00692 fcinfo.arg[i + 1] = slot1->tts_values[i];
00693 fcinfo.argnull[i + 1] = slot1->tts_isnull[i];
00694 }
00695
00696 advance_transition_function(aggstate, peraggstate, pergroupstate,
00697 &fcinfo);
00698
00699 if (numDistinctCols > 0)
00700 {
00701
00702 TupleTableSlot *tmpslot = slot2;
00703
00704 slot2 = slot1;
00705 slot1 = tmpslot;
00706 haveOldValue = true;
00707 }
00708 }
00709
00710
00711 if (numDistinctCols == 0)
00712 MemoryContextReset(workcontext);
00713
00714 ExecClearTuple(slot1);
00715 }
00716
00717 if (slot2)
00718 ExecClearTuple(slot2);
00719
00720 tuplesort_end(peraggstate->sortstate);
00721 peraggstate->sortstate = NULL;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730 static void
00731 finalize_aggregate(AggState *aggstate,
00732 AggStatePerAgg peraggstate,
00733 AggStatePerGroup pergroupstate,
00734 Datum *resultVal, bool *resultIsNull)
00735 {
00736 MemoryContext oldContext;
00737
00738 oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
00739
00740
00741
00742
00743 if (OidIsValid(peraggstate->finalfn_oid))
00744 {
00745 FunctionCallInfoData fcinfo;
00746
00747 InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
00748 peraggstate->aggCollation,
00749 (void *) aggstate, NULL);
00750 fcinfo.arg[0] = pergroupstate->transValue;
00751 fcinfo.argnull[0] = pergroupstate->transValueIsNull;
00752 if (fcinfo.flinfo->fn_strict && pergroupstate->transValueIsNull)
00753 {
00754
00755 *resultVal = (Datum) 0;
00756 *resultIsNull = true;
00757 }
00758 else
00759 {
00760 *resultVal = FunctionCallInvoke(&fcinfo);
00761 *resultIsNull = fcinfo.isnull;
00762 }
00763 }
00764 else
00765 {
00766 *resultVal = pergroupstate->transValue;
00767 *resultIsNull = pergroupstate->transValueIsNull;
00768 }
00769
00770
00771
00772
00773 if (!peraggstate->resulttypeByVal && !*resultIsNull &&
00774 !MemoryContextContains(CurrentMemoryContext,
00775 DatumGetPointer(*resultVal)))
00776 *resultVal = datumCopy(*resultVal,
00777 peraggstate->resulttypeByVal,
00778 peraggstate->resulttypeLen);
00779
00780 MemoryContextSwitchTo(oldContext);
00781 }
00782
00783
00784
00785
00786
00787
00788 static Bitmapset *
00789 find_unaggregated_cols(AggState *aggstate)
00790 {
00791 Agg *node = (Agg *) aggstate->ss.ps.plan;
00792 Bitmapset *colnos;
00793
00794 colnos = NULL;
00795 (void) find_unaggregated_cols_walker((Node *) node->plan.targetlist,
00796 &colnos);
00797 (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
00798 &colnos);
00799 return colnos;
00800 }
00801
00802 static bool
00803 find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
00804 {
00805 if (node == NULL)
00806 return false;
00807 if (IsA(node, Var))
00808 {
00809 Var *var = (Var *) node;
00810
00811
00812 Assert(var->varno == OUTER_VAR);
00813 Assert(var->varlevelsup == 0);
00814 *colnos = bms_add_member(*colnos, var->varattno);
00815 return false;
00816 }
00817 if (IsA(node, Aggref))
00818 return false;
00819 return expression_tree_walker(node, find_unaggregated_cols_walker,
00820 (void *) colnos);
00821 }
00822
00823
00824
00825
00826
00827
00828 static void
00829 build_hash_table(AggState *aggstate)
00830 {
00831 Agg *node = (Agg *) aggstate->ss.ps.plan;
00832 MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
00833 Size entrysize;
00834
00835 Assert(node->aggstrategy == AGG_HASHED);
00836 Assert(node->numGroups > 0);
00837
00838 entrysize = sizeof(AggHashEntryData) +
00839 (aggstate->numaggs - 1) * sizeof(AggStatePerGroupData);
00840
00841 aggstate->hashtable = BuildTupleHashTable(node->numCols,
00842 node->grpColIdx,
00843 aggstate->eqfunctions,
00844 aggstate->hashfunctions,
00845 node->numGroups,
00846 entrysize,
00847 aggstate->aggcontext,
00848 tmpmem);
00849 }
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 static List *
00877 find_hash_columns(AggState *aggstate)
00878 {
00879 Agg *node = (Agg *) aggstate->ss.ps.plan;
00880 Bitmapset *colnos;
00881 List *collist;
00882 int i;
00883
00884
00885 colnos = find_unaggregated_cols(aggstate);
00886
00887 for (i = 0; i < node->numCols; i++)
00888 colnos = bms_add_member(colnos, node->grpColIdx[i]);
00889
00890 collist = NIL;
00891 while ((i = bms_first_member(colnos)) >= 0)
00892 collist = lcons_int(i, collist);
00893 bms_free(colnos);
00894
00895 return collist;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904 Size
00905 hash_agg_entry_size(int numAggs)
00906 {
00907 Size entrysize;
00908
00909
00910 entrysize = sizeof(AggHashEntryData) +
00911 (numAggs - 1) * sizeof(AggStatePerGroupData);
00912 entrysize = MAXALIGN(entrysize);
00913
00914 entrysize += 3 * sizeof(void *);
00915 return entrysize;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924 static AggHashEntry
00925 lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
00926 {
00927 TupleTableSlot *hashslot = aggstate->hashslot;
00928 ListCell *l;
00929 AggHashEntry entry;
00930 bool isnew;
00931
00932
00933 if (hashslot->tts_tupleDescriptor == NULL)
00934 {
00935 ExecSetSlotDescriptor(hashslot, inputslot->tts_tupleDescriptor);
00936
00937 ExecStoreAllNullTuple(hashslot);
00938 }
00939
00940
00941 slot_getsomeattrs(inputslot, linitial_int(aggstate->hash_needed));
00942 foreach(l, aggstate->hash_needed)
00943 {
00944 int varNumber = lfirst_int(l) - 1;
00945
00946 hashslot->tts_values[varNumber] = inputslot->tts_values[varNumber];
00947 hashslot->tts_isnull[varNumber] = inputslot->tts_isnull[varNumber];
00948 }
00949
00950
00951 entry = (AggHashEntry) LookupTupleHashEntry(aggstate->hashtable,
00952 hashslot,
00953 &isnew);
00954
00955 if (isnew)
00956 {
00957
00958 initialize_aggregates(aggstate, aggstate->peragg, entry->pergroup);
00959 }
00960
00961 return entry;
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 TupleTableSlot *
00978 ExecAgg(AggState *node)
00979 {
00980
00981
00982
00983
00984
00985 if (node->ss.ps.ps_TupFromTlist)
00986 {
00987 TupleTableSlot *result;
00988 ExprDoneCond isDone;
00989
00990 result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
00991 if (isDone == ExprMultipleResult)
00992 return result;
00993
00994 node->ss.ps.ps_TupFromTlist = false;
00995 }
00996
00997
00998
00999
01000
01001
01002 if (node->agg_done)
01003 return NULL;
01004
01005
01006 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
01007 {
01008 if (!node->table_filled)
01009 agg_fill_hash_table(node);
01010 return agg_retrieve_hash_table(node);
01011 }
01012 else
01013 return agg_retrieve_direct(node);
01014 }
01015
01016
01017
01018
01019 static TupleTableSlot *
01020 agg_retrieve_direct(AggState *aggstate)
01021 {
01022 Agg *node = (Agg *) aggstate->ss.ps.plan;
01023 PlanState *outerPlan;
01024 ExprContext *econtext;
01025 ExprContext *tmpcontext;
01026 Datum *aggvalues;
01027 bool *aggnulls;
01028 AggStatePerAgg peragg;
01029 AggStatePerGroup pergroup;
01030 TupleTableSlot *outerslot;
01031 TupleTableSlot *firstSlot;
01032 int aggno;
01033
01034
01035
01036
01037 outerPlan = outerPlanState(aggstate);
01038
01039 econtext = aggstate->ss.ps.ps_ExprContext;
01040 aggvalues = econtext->ecxt_aggvalues;
01041 aggnulls = econtext->ecxt_aggnulls;
01042
01043 tmpcontext = aggstate->tmpcontext;
01044 peragg = aggstate->peragg;
01045 pergroup = aggstate->pergroup;
01046 firstSlot = aggstate->ss.ss_ScanTupleSlot;
01047
01048
01049
01050
01051
01052 while (!aggstate->agg_done)
01053 {
01054
01055
01056
01057
01058 if (aggstate->grp_firstTuple == NULL)
01059 {
01060 outerslot = ExecProcNode(outerPlan);
01061 if (!TupIsNull(outerslot))
01062 {
01063
01064
01065
01066
01067 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
01068 }
01069 else
01070 {
01071
01072 aggstate->agg_done = true;
01073
01074 if (node->aggstrategy != AGG_PLAIN)
01075 return NULL;
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084
01085 ResetExprContext(econtext);
01086
01087 MemoryContextResetAndDeleteChildren(aggstate->aggcontext);
01088
01089
01090
01091
01092 initialize_aggregates(aggstate, peragg, pergroup);
01093
01094 if (aggstate->grp_firstTuple != NULL)
01095 {
01096
01097
01098
01099
01100
01101 ExecStoreTuple(aggstate->grp_firstTuple,
01102 firstSlot,
01103 InvalidBuffer,
01104 true);
01105 aggstate->grp_firstTuple = NULL;
01106
01107
01108 tmpcontext->ecxt_outertuple = firstSlot;
01109
01110
01111
01112
01113
01114 for (;;)
01115 {
01116 advance_aggregates(aggstate, pergroup);
01117
01118
01119 ResetExprContext(tmpcontext);
01120
01121 outerslot = ExecProcNode(outerPlan);
01122 if (TupIsNull(outerslot))
01123 {
01124
01125 aggstate->agg_done = true;
01126 break;
01127 }
01128
01129 tmpcontext->ecxt_outertuple = outerslot;
01130
01131
01132
01133
01134
01135 if (node->aggstrategy == AGG_SORTED)
01136 {
01137 if (!execTuplesMatch(firstSlot,
01138 outerslot,
01139 node->numCols, node->grpColIdx,
01140 aggstate->eqfunctions,
01141 tmpcontext->ecxt_per_tuple_memory))
01142 {
01143
01144
01145
01146 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
01147 break;
01148 }
01149 }
01150 }
01151 }
01152
01153
01154
01155
01156
01157 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
01158 {
01159 AggStatePerAgg peraggstate = &peragg[aggno];
01160 AggStatePerGroup pergroupstate = &pergroup[aggno];
01161
01162 if (peraggstate->numSortCols > 0)
01163 {
01164 if (peraggstate->numInputs == 1)
01165 process_ordered_aggregate_single(aggstate,
01166 peraggstate,
01167 pergroupstate);
01168 else
01169 process_ordered_aggregate_multi(aggstate,
01170 peraggstate,
01171 pergroupstate);
01172 }
01173
01174 finalize_aggregate(aggstate, peraggstate, pergroupstate,
01175 &aggvalues[aggno], &aggnulls[aggno]);
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185 econtext->ecxt_outertuple = firstSlot;
01186
01187
01188
01189
01190
01191 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
01192 {
01193
01194
01195
01196
01197 TupleTableSlot *result;
01198 ExprDoneCond isDone;
01199
01200 result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
01201
01202 if (isDone != ExprEndResult)
01203 {
01204 aggstate->ss.ps.ps_TupFromTlist =
01205 (isDone == ExprMultipleResult);
01206 return result;
01207 }
01208 }
01209 else
01210 InstrCountFiltered1(aggstate, 1);
01211 }
01212
01213
01214 return NULL;
01215 }
01216
01217
01218
01219
01220 static void
01221 agg_fill_hash_table(AggState *aggstate)
01222 {
01223 PlanState *outerPlan;
01224 ExprContext *tmpcontext;
01225 AggHashEntry entry;
01226 TupleTableSlot *outerslot;
01227
01228
01229
01230
01231 outerPlan = outerPlanState(aggstate);
01232
01233 tmpcontext = aggstate->tmpcontext;
01234
01235
01236
01237
01238
01239 for (;;)
01240 {
01241 outerslot = ExecProcNode(outerPlan);
01242 if (TupIsNull(outerslot))
01243 break;
01244
01245 tmpcontext->ecxt_outertuple = outerslot;
01246
01247
01248 entry = lookup_hash_entry(aggstate, outerslot);
01249
01250
01251 advance_aggregates(aggstate, entry->pergroup);
01252
01253
01254 ResetExprContext(tmpcontext);
01255 }
01256
01257 aggstate->table_filled = true;
01258
01259 ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
01260 }
01261
01262
01263
01264
01265 static TupleTableSlot *
01266 agg_retrieve_hash_table(AggState *aggstate)
01267 {
01268 ExprContext *econtext;
01269 Datum *aggvalues;
01270 bool *aggnulls;
01271 AggStatePerAgg peragg;
01272 AggStatePerGroup pergroup;
01273 AggHashEntry entry;
01274 TupleTableSlot *firstSlot;
01275 int aggno;
01276
01277
01278
01279
01280
01281 econtext = aggstate->ss.ps.ps_ExprContext;
01282 aggvalues = econtext->ecxt_aggvalues;
01283 aggnulls = econtext->ecxt_aggnulls;
01284 peragg = aggstate->peragg;
01285 firstSlot = aggstate->ss.ss_ScanTupleSlot;
01286
01287
01288
01289
01290
01291 while (!aggstate->agg_done)
01292 {
01293
01294
01295
01296 entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter);
01297 if (entry == NULL)
01298 {
01299
01300 aggstate->agg_done = TRUE;
01301 return NULL;
01302 }
01303
01304
01305
01306
01307 ResetExprContext(econtext);
01308
01309
01310
01311
01312
01313 ExecStoreMinimalTuple(entry->shared.firstTuple,
01314 firstSlot,
01315 false);
01316
01317 pergroup = entry->pergroup;
01318
01319
01320
01321
01322
01323 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
01324 {
01325 AggStatePerAgg peraggstate = &peragg[aggno];
01326 AggStatePerGroup pergroupstate = &pergroup[aggno];
01327
01328 Assert(peraggstate->numSortCols == 0);
01329 finalize_aggregate(aggstate, peraggstate, pergroupstate,
01330 &aggvalues[aggno], &aggnulls[aggno]);
01331 }
01332
01333
01334
01335
01336
01337 econtext->ecxt_outertuple = firstSlot;
01338
01339
01340
01341
01342
01343 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
01344 {
01345
01346
01347
01348
01349 TupleTableSlot *result;
01350 ExprDoneCond isDone;
01351
01352 result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
01353
01354 if (isDone != ExprEndResult)
01355 {
01356 aggstate->ss.ps.ps_TupFromTlist =
01357 (isDone == ExprMultipleResult);
01358 return result;
01359 }
01360 }
01361 else
01362 InstrCountFiltered1(aggstate, 1);
01363 }
01364
01365
01366 return NULL;
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376 AggState *
01377 ExecInitAgg(Agg *node, EState *estate, int eflags)
01378 {
01379 AggState *aggstate;
01380 AggStatePerAgg peragg;
01381 Plan *outerPlan;
01382 ExprContext *econtext;
01383 int numaggs,
01384 aggno;
01385 ListCell *l;
01386
01387
01388 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
01389
01390
01391
01392
01393 aggstate = makeNode(AggState);
01394 aggstate->ss.ps.plan = (Plan *) node;
01395 aggstate->ss.ps.state = estate;
01396
01397 aggstate->aggs = NIL;
01398 aggstate->numaggs = 0;
01399 aggstate->eqfunctions = NULL;
01400 aggstate->hashfunctions = NULL;
01401 aggstate->peragg = NULL;
01402 aggstate->agg_done = false;
01403 aggstate->pergroup = NULL;
01404 aggstate->grp_firstTuple = NULL;
01405 aggstate->hashtable = NULL;
01406
01407
01408
01409
01410
01411
01412 ExecAssignExprContext(estate, &aggstate->ss.ps);
01413 aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
01414 ExecAssignExprContext(estate, &aggstate->ss.ps);
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 aggstate->aggcontext =
01425 AllocSetContextCreate(CurrentMemoryContext,
01426 "AggContext",
01427 ALLOCSET_DEFAULT_MINSIZE,
01428 ALLOCSET_DEFAULT_INITSIZE,
01429 ALLOCSET_DEFAULT_MAXSIZE);
01430
01431
01432
01433
01434 ExecInitScanTupleSlot(estate, &aggstate->ss);
01435 ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
01436 aggstate->hashslot = ExecInitExtraTupleSlot(estate);
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447 aggstate->ss.ps.targetlist = (List *)
01448 ExecInitExpr((Expr *) node->plan.targetlist,
01449 (PlanState *) aggstate);
01450 aggstate->ss.ps.qual = (List *)
01451 ExecInitExpr((Expr *) node->plan.qual,
01452 (PlanState *) aggstate);
01453
01454
01455
01456
01457
01458
01459
01460 if (node->aggstrategy == AGG_HASHED)
01461 eflags &= ~EXEC_FLAG_REWIND;
01462 outerPlan = outerPlan(node);
01463 outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
01464
01465
01466
01467
01468 ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
01469
01470
01471
01472
01473 ExecAssignResultTypeFromTL(&aggstate->ss.ps);
01474 ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
01475
01476 aggstate->ss.ps.ps_TupFromTlist = false;
01477
01478
01479
01480
01481 numaggs = aggstate->numaggs;
01482 Assert(numaggs == list_length(aggstate->aggs));
01483 if (numaggs <= 0)
01484 {
01485
01486
01487
01488
01489
01490
01491
01492 numaggs = 1;
01493 }
01494
01495
01496
01497
01498
01499
01500 if (node->numCols > 0)
01501 {
01502 if (node->aggstrategy == AGG_HASHED)
01503 execTuplesHashPrepare(node->numCols,
01504 node->grpOperators,
01505 &aggstate->eqfunctions,
01506 &aggstate->hashfunctions);
01507 else
01508 aggstate->eqfunctions =
01509 execTuplesMatchPrepare(node->numCols,
01510 node->grpOperators);
01511 }
01512
01513
01514
01515
01516
01517 econtext = aggstate->ss.ps.ps_ExprContext;
01518 econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
01519 econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
01520
01521 peragg = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
01522 aggstate->peragg = peragg;
01523
01524 if (node->aggstrategy == AGG_HASHED)
01525 {
01526 build_hash_table(aggstate);
01527 aggstate->table_filled = false;
01528
01529 aggstate->hash_needed = find_hash_columns(aggstate);
01530 }
01531 else
01532 {
01533 AggStatePerGroup pergroup;
01534
01535 pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs);
01536 aggstate->pergroup = pergroup;
01537 }
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547 aggno = -1;
01548 foreach(l, aggstate->aggs)
01549 {
01550 AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
01551 Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
01552 AggStatePerAgg peraggstate;
01553 Oid inputTypes[FUNC_MAX_ARGS];
01554 int numArguments;
01555 int numInputs;
01556 int numSortCols;
01557 int numDistinctCols;
01558 List *sortlist;
01559 HeapTuple aggTuple;
01560 Form_pg_aggregate aggform;
01561 Oid aggtranstype;
01562 AclResult aclresult;
01563 Oid transfn_oid,
01564 finalfn_oid;
01565 Expr *transfnexpr,
01566 *finalfnexpr;
01567 Datum textInitVal;
01568 int i;
01569 ListCell *lc;
01570
01571
01572 Assert(aggref->agglevelsup == 0);
01573
01574
01575 for (i = 0; i <= aggno; i++)
01576 {
01577 if (equal(aggref, peragg[i].aggref) &&
01578 !contain_volatile_functions((Node *) aggref))
01579 break;
01580 }
01581 if (i <= aggno)
01582 {
01583
01584 aggrefstate->aggno = i;
01585 continue;
01586 }
01587
01588
01589 peraggstate = &peragg[++aggno];
01590
01591
01592 aggrefstate->aggno = aggno;
01593
01594
01595 peraggstate->aggrefstate = aggrefstate;
01596 peraggstate->aggref = aggref;
01597 numInputs = list_length(aggref->args);
01598 peraggstate->numInputs = numInputs;
01599 peraggstate->sortstate = NULL;
01600
01601
01602
01603
01604
01605
01606 numArguments = 0;
01607 foreach(lc, aggref->args)
01608 {
01609 TargetEntry *tle = (TargetEntry *) lfirst(lc);
01610
01611 if (!tle->resjunk)
01612 inputTypes[numArguments++] = exprType((Node *) tle->expr);
01613 }
01614 peraggstate->numArguments = numArguments;
01615
01616 aggTuple = SearchSysCache1(AGGFNOID,
01617 ObjectIdGetDatum(aggref->aggfnoid));
01618 if (!HeapTupleIsValid(aggTuple))
01619 elog(ERROR, "cache lookup failed for aggregate %u",
01620 aggref->aggfnoid);
01621 aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
01622
01623
01624 aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
01625 ACL_EXECUTE);
01626 if (aclresult != ACLCHECK_OK)
01627 aclcheck_error(aclresult, ACL_KIND_PROC,
01628 get_func_name(aggref->aggfnoid));
01629 InvokeFunctionExecuteHook(aggref->aggfnoid);
01630
01631 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
01632 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
01633
01634
01635 {
01636 HeapTuple procTuple;
01637 Oid aggOwner;
01638
01639 procTuple = SearchSysCache1(PROCOID,
01640 ObjectIdGetDatum(aggref->aggfnoid));
01641 if (!HeapTupleIsValid(procTuple))
01642 elog(ERROR, "cache lookup failed for function %u",
01643 aggref->aggfnoid);
01644 aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
01645 ReleaseSysCache(procTuple);
01646
01647 aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
01648 ACL_EXECUTE);
01649 if (aclresult != ACLCHECK_OK)
01650 aclcheck_error(aclresult, ACL_KIND_PROC,
01651 get_func_name(transfn_oid));
01652 InvokeFunctionExecuteHook(transfn_oid);
01653 if (OidIsValid(finalfn_oid))
01654 {
01655 aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
01656 ACL_EXECUTE);
01657 if (aclresult != ACLCHECK_OK)
01658 aclcheck_error(aclresult, ACL_KIND_PROC,
01659 get_func_name(finalfn_oid));
01660 InvokeFunctionExecuteHook(finalfn_oid);
01661 }
01662 }
01663
01664
01665 aggtranstype = aggform->aggtranstype;
01666 if (IsPolymorphicType(aggtranstype))
01667 {
01668
01669 Oid *declaredArgTypes;
01670 int agg_nargs;
01671
01672 (void) get_func_signature(aggref->aggfnoid,
01673 &declaredArgTypes, &agg_nargs);
01674 Assert(agg_nargs == numArguments);
01675 aggtranstype = enforce_generic_type_consistency(inputTypes,
01676 declaredArgTypes,
01677 agg_nargs,
01678 aggtranstype,
01679 false);
01680 pfree(declaredArgTypes);
01681 }
01682
01683
01684 build_aggregate_fnexprs(inputTypes,
01685 numArguments,
01686 aggtranstype,
01687 aggref->aggtype,
01688 aggref->inputcollid,
01689 transfn_oid,
01690 finalfn_oid,
01691 &transfnexpr,
01692 &finalfnexpr);
01693
01694 fmgr_info(transfn_oid, &peraggstate->transfn);
01695 fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
01696
01697 if (OidIsValid(finalfn_oid))
01698 {
01699 fmgr_info(finalfn_oid, &peraggstate->finalfn);
01700 fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
01701 }
01702
01703 peraggstate->aggCollation = aggref->inputcollid;
01704
01705 get_typlenbyval(aggref->aggtype,
01706 &peraggstate->resulttypeLen,
01707 &peraggstate->resulttypeByVal);
01708 get_typlenbyval(aggtranstype,
01709 &peraggstate->transtypeLen,
01710 &peraggstate->transtypeByVal);
01711
01712
01713
01714
01715
01716 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
01717 Anum_pg_aggregate_agginitval,
01718 &peraggstate->initValueIsNull);
01719
01720 if (peraggstate->initValueIsNull)
01721 peraggstate->initValue = (Datum) 0;
01722 else
01723 peraggstate->initValue = GetAggInitVal(textInitVal,
01724 aggtranstype);
01725
01726
01727
01728
01729
01730
01731
01732
01733 if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
01734 {
01735 if (numArguments < 1 ||
01736 !IsBinaryCoercible(inputTypes[0], aggtranstype))
01737 ereport(ERROR,
01738 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
01739 errmsg("aggregate %u needs to have compatible input type and transition type",
01740 aggref->aggfnoid)));
01741 }
01742
01743
01744
01745
01746
01747 peraggstate->evaldesc = ExecTypeFromTL(aggref->args, false);
01748
01749
01750 peraggstate->evalslot = ExecInitExtraTupleSlot(estate);
01751 ExecSetSlotDescriptor(peraggstate->evalslot, peraggstate->evaldesc);
01752
01753
01754 peraggstate->evalproj = ExecBuildProjectionInfo(aggrefstate->args,
01755 aggstate->tmpcontext,
01756 peraggstate->evalslot,
01757 NULL);
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767 if (aggref->aggdistinct)
01768 {
01769 sortlist = aggref->aggdistinct;
01770 numSortCols = numDistinctCols = list_length(sortlist);
01771 Assert(numSortCols >= list_length(aggref->aggorder));
01772 }
01773 else
01774 {
01775 sortlist = aggref->aggorder;
01776 numSortCols = list_length(sortlist);
01777 numDistinctCols = 0;
01778 }
01779
01780 peraggstate->numSortCols = numSortCols;
01781 peraggstate->numDistinctCols = numDistinctCols;
01782
01783 if (numSortCols > 0)
01784 {
01785
01786
01787
01788
01789 Assert(node->aggstrategy != AGG_HASHED);
01790
01791
01792 if (numInputs == 1)
01793 {
01794 get_typlenbyval(inputTypes[0],
01795 &peraggstate->inputtypeLen,
01796 &peraggstate->inputtypeByVal);
01797 }
01798 else if (numDistinctCols > 0)
01799 {
01800
01801 peraggstate->uniqslot = ExecInitExtraTupleSlot(estate);
01802 ExecSetSlotDescriptor(peraggstate->uniqslot,
01803 peraggstate->evaldesc);
01804 }
01805
01806
01807 peraggstate->sortColIdx =
01808 (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
01809 peraggstate->sortOperators =
01810 (Oid *) palloc(numSortCols * sizeof(Oid));
01811 peraggstate->sortCollations =
01812 (Oid *) palloc(numSortCols * sizeof(Oid));
01813 peraggstate->sortNullsFirst =
01814 (bool *) palloc(numSortCols * sizeof(bool));
01815
01816 i = 0;
01817 foreach(lc, sortlist)
01818 {
01819 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
01820 TargetEntry *tle = get_sortgroupclause_tle(sortcl,
01821 aggref->args);
01822
01823
01824 Assert(OidIsValid(sortcl->sortop));
01825
01826 peraggstate->sortColIdx[i] = tle->resno;
01827 peraggstate->sortOperators[i] = sortcl->sortop;
01828 peraggstate->sortCollations[i] = exprCollation((Node *) tle->expr);
01829 peraggstate->sortNullsFirst[i] = sortcl->nulls_first;
01830 i++;
01831 }
01832 Assert(i == numSortCols);
01833 }
01834
01835 if (aggref->aggdistinct)
01836 {
01837 Assert(numArguments > 0);
01838
01839
01840
01841
01842
01843 peraggstate->equalfns =
01844 (FmgrInfo *) palloc(numDistinctCols * sizeof(FmgrInfo));
01845
01846 i = 0;
01847 foreach(lc, aggref->aggdistinct)
01848 {
01849 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
01850
01851 fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
01852 i++;
01853 }
01854 Assert(i == numDistinctCols);
01855 }
01856
01857 ReleaseSysCache(aggTuple);
01858 }
01859
01860
01861 aggstate->numaggs = aggno + 1;
01862
01863 return aggstate;
01864 }
01865
01866 static Datum
01867 GetAggInitVal(Datum textInitVal, Oid transtype)
01868 {
01869 Oid typinput,
01870 typioparam;
01871 char *strInitVal;
01872 Datum initVal;
01873
01874 getTypeInputInfo(transtype, &typinput, &typioparam);
01875 strInitVal = TextDatumGetCString(textInitVal);
01876 initVal = OidInputFunctionCall(typinput, strInitVal,
01877 typioparam, -1);
01878 pfree(strInitVal);
01879 return initVal;
01880 }
01881
01882 void
01883 ExecEndAgg(AggState *node)
01884 {
01885 PlanState *outerPlan;
01886 int aggno;
01887
01888
01889 for (aggno = 0; aggno < node->numaggs; aggno++)
01890 {
01891 AggStatePerAgg peraggstate = &node->peragg[aggno];
01892
01893 if (peraggstate->sortstate)
01894 tuplesort_end(peraggstate->sortstate);
01895 }
01896
01897
01898
01899
01900 ExecFreeExprContext(&node->ss.ps);
01901 node->ss.ps.ps_ExprContext = node->tmpcontext;
01902 ExecFreeExprContext(&node->ss.ps);
01903
01904
01905 ExecClearTuple(node->ss.ss_ScanTupleSlot);
01906
01907 MemoryContextDelete(node->aggcontext);
01908
01909 outerPlan = outerPlanState(node);
01910 ExecEndNode(outerPlan);
01911 }
01912
01913 void
01914 ExecReScanAgg(AggState *node)
01915 {
01916 ExprContext *econtext = node->ss.ps.ps_ExprContext;
01917 int aggno;
01918
01919 node->agg_done = false;
01920
01921 node->ss.ps.ps_TupFromTlist = false;
01922
01923 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
01924 {
01925
01926
01927
01928
01929
01930
01931 if (!node->table_filled)
01932 return;
01933
01934
01935
01936
01937
01938
01939 if (node->ss.ps.lefttree->chgParam == NULL)
01940 {
01941 ResetTupleHashIterator(node->hashtable, &node->hashiter);
01942 return;
01943 }
01944 }
01945
01946
01947 for (aggno = 0; aggno < node->numaggs; aggno++)
01948 {
01949 AggStatePerAgg peraggstate = &node->peragg[aggno];
01950
01951 if (peraggstate->sortstate)
01952 tuplesort_end(peraggstate->sortstate);
01953 peraggstate->sortstate = NULL;
01954 }
01955
01956
01957 if (node->grp_firstTuple != NULL)
01958 {
01959 heap_freetuple(node->grp_firstTuple);
01960 node->grp_firstTuple = NULL;
01961 }
01962
01963
01964 MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
01965 MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
01966
01967
01968
01969
01970
01971
01972
01973
01974 MemoryContextResetAndDeleteChildren(node->aggcontext);
01975
01976 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
01977 {
01978
01979 build_hash_table(node);
01980 node->table_filled = false;
01981 }
01982 else
01983 {
01984
01985
01986
01987 MemSet(node->pergroup, 0,
01988 sizeof(AggStatePerGroupData) * node->numaggs);
01989 }
01990
01991
01992
01993
01994
01995 if (node->ss.ps.lefttree->chgParam == NULL)
01996 ExecReScan(node->ss.ps.lefttree);
01997 }
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013 int
02014 AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
02015 {
02016 if (fcinfo->context && IsA(fcinfo->context, AggState))
02017 {
02018 if (aggcontext)
02019 *aggcontext = ((AggState *) fcinfo->context)->aggcontext;
02020 return AGG_CONTEXT_AGGREGATE;
02021 }
02022 if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
02023 {
02024 if (aggcontext)
02025 *aggcontext = ((WindowAggState *) fcinfo->context)->aggcontext;
02026 return AGG_CONTEXT_WINDOW;
02027 }
02028
02029
02030 if (aggcontext)
02031 *aggcontext = NULL;
02032 return 0;
02033 }
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045 Datum
02046 aggregate_dummy(PG_FUNCTION_ARGS)
02047 {
02048 elog(ERROR, "aggregate function %u called as normal function",
02049 fcinfo->flinfo->fn_oid);
02050 return (Datum) 0;
02051 }