PostgreSQL Source Code: src/backend/executor/nodeAgg.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
250
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297#define HASHAGG_PARTITION_FACTOR 1.50
298#define HASHAGG_MIN_PARTITIONS 4
299#define HASHAGG_MAX_PARTITIONS 1024
300
301
302
303
304
305
306
307#define HASHAGG_READ_BUFFER_SIZE BLCKSZ
308#define HASHAGG_WRITE_BUFFER_SIZE BLCKSZ
309
310
311
312
313
314
315
316#define HASHAGG_HLL_BIT_WIDTH 5
317
318
319
320
321#define CHUNKHDRSZ sizeof(MemoryChunk)
322
323
324
325
326
327
328
329
330
331
333{
341
342
343
344
345
346
347
348
349
350
352{
357 double input_card;
359
360
362{
367
373 int numReset);
387 Datum *resultVal, bool *resultIsNull);
391 Datum *resultVal, bool *resultIsNull);
397 int currentSet);
408 bool nullcheck);
411 long ngroups, Size memory);
413 double hashentrysize,
414 int used_bits,
415 int *log2_npartitions);
428 int npartitions);
432 int64 input_tuples, double input_card,
433 int used_bits);
436 int used_bits, double input_groups,
437 double hashentrysize);
441 int setno);
446 Oid aggtranstype, Oid aggserialfn,
448 bool initValueIsNull, Oid *inputTypes,
449 int numArguments);
450
451
452
453
454
455
456static void
458{
459
460
461
462
463 if (is_hash)
465 else
467
469}
470
471
472
473
474
475
476
477
478static void
480{
481 Assert(newphase <= 1 || newphase == aggstate->current_phase + 1);
482
483
484
485
486
488 {
490 aggstate->sort_in = NULL;
491 }
492
493 if (newphase <= 1)
494 {
495
496
497
499 {
502 }
503 }
504 else
505 {
506
507
508
509
514 }
515
516
517
518
519
520 if (newphase > 0 && newphase < aggstate->numphases - 1)
521 {
525
528 sortnode->sortColIdx,
529 sortnode->sortOperators,
530 sortnode->collations,
531 sortnode->nullsFirst,
534 }
535
537 aggstate->phase = &aggstate->phases[newphase];
538}
539
540
541
542
543
544
545
546
547
550{
552
554 {
555
559 return NULL;
561 }
562 else
564
567
568 return slot;
569}
570
571
572
573
574
575
576
577
578
579static void
582{
583
584
585
587 {
588
589
590
591
594
595
596
597
598
599
600
602 {
604
611 }
612 else
621 }
622
623
624
625
626
627
628
631 else
632 {
634
640 }
642
643
644
645
646
647
648
649
651}
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666static void
669 int numReset)
670{
671 int transno;
673 int setno = 0;
674 int numTrans = aggstate->numtrans;
676
677 if (numReset == 0)
678 numReset = numGroupingSets;
679
680 for (setno = 0; setno < numReset; setno++)
681 {
683
685
686 for (transno = 0; transno < numTrans; transno++)
687 {
690
692 }
693 }
694}
695
696
697
698
699
700
701
702
703
704
705
706
707static void
711{
715
717 {
718
719
720
721
723 int i;
724
725 for (i = 1; i <= numTransInputs; i++)
726 {
728 return;
729 }
731 {
732
733
734
735
736
737
738
739
740
748 return;
749 }
751 {
752
753
754
755
756
757
758 return;
759 }
760 }
761
762
764
765
767
768
769
770
773 fcinfo->isnull = false;
774
776
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
796 newVal, fcinfo->isnull,
799
802
804}
805
806
807
808
809
810
811
812
813
814
815
816
817static void
819{
822}
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846static void
850{
852 bool oldIsNull = true;
853 bool haveOldVal = false;
861 bool *isNull;
862
864
866
867
870
871
872
873
874
875
876
878 true, false, newVal, isNull, &newAbbrevVal))
879 {
880
881
882
883
886
887
888
889
890 if (isDistinct &&
891 haveOldVal &&
892 ((oldIsNull && *isNull) ||
893 (!oldIsNull && !*isNull &&
894 oldAbbrevVal == newAbbrevVal &&
897 oldVal, *newVal)))))
898 {
900 continue;
901 }
902 else
903 {
905
907
908
909
910
911
913 {
914 if (!oldIsNull)
916 if (!*isNull)
919 }
920 else
921 oldVal = *newVal;
922 oldAbbrevVal = newAbbrevVal;
923 oldIsNull = *isNull;
924 haveOldVal = true;
925 }
926 }
927
930
933}
934
935
936
937
938
939
940
941
942
943
944
945
946
947static void
951{
960 bool haveOldValue = false;
962 int i;
963
965
967 if (slot2)
969
971 true, true, slot1, &newAbbrevVal))
972 {
974
977
978 if (numDistinctCols == 0 ||
979 !haveOldValue ||
980 newAbbrevVal != oldAbbrevVal ||
982 {
983
984
985
986
988
989
990
991 for (i = 0; i < numTransInputs; i++)
992 {
995 }
996
998
999 if (numDistinctCols > 0)
1000 {
1001
1003
1004 slot2 = slot1;
1005 slot1 = tmpslot;
1006
1007 oldAbbrevVal = newAbbrevVal;
1008 haveOldValue = true;
1009 }
1010 }
1011
1012
1014
1016 }
1017
1018 if (slot2)
1020
1023
1024
1026}
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044static void
1048 Datum *resultVal, bool *resultIsNull)
1049{
1051 bool anynull = false;
1053 int i;
1056
1058
1059
1060
1061
1062
1063
1064
1065 i = 1;
1067 {
1069
1072 &fcinfo->args[i].isnull);
1073 anynull |= fcinfo->args[i].isnull;
1074 i++;
1075 }
1076
1077
1078
1079
1081 {
1083
1084
1086
1088 numFinalArgs,
1090 (Node *) aggstate, NULL);
1091
1092
1093 fcinfo->args[0].value =
1099
1100
1101 for (; i < numFinalArgs; i++)
1102 {
1103 fcinfo->args[i].value = (Datum) 0;
1104 fcinfo->args[i].isnull = true;
1105 anynull = true;
1106 }
1107
1108 if (fcinfo->flinfo->fn_strict && anynull)
1109 {
1110
1111 *resultVal = (Datum) 0;
1112 *resultIsNull = true;
1113 }
1114 else
1115 {
1117
1119 *resultIsNull = fcinfo->isnull;
1121 fcinfo->isnull,
1123 }
1124 aggstate->curperagg = NULL;
1125 }
1126 else
1127 {
1128 *resultVal =
1133 }
1134
1136}
1137
1138
1139
1140
1141
1142
1143
1144static void
1148 Datum *resultVal, bool *resultIsNull)
1149{
1152
1154
1155
1156
1157
1158
1160 {
1161
1163 {
1164 *resultVal = (Datum) 0;
1165 *resultIsNull = true;
1166 }
1167 else
1168 {
1171
1177 fcinfo->isnull = false;
1178
1180 *resultIsNull = fcinfo->isnull;
1184 }
1185 }
1186 else
1187 {
1188 *resultVal =
1193 }
1194
1196}
1197
1198
1199
1200
1201
1202static inline void
1206{
1207 int i;
1208
1209
1212
1214 {
1216
1219 }
1221}
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247static void
1249{
1251 {
1253
1255
1257 {
1258
1259
1260
1261
1262
1264 }
1266 {
1268
1269
1271
1273 {
1275
1278 }
1279 }
1280 }
1281}
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292static void
1296{
1300 int aggno;
1301
1302
1303
1304
1305
1306 for (int transno = 0; transno < aggstate->numtrans; transno++)
1307 {
1310
1311 pergroupstate = &pergroup[transno];
1312
1314 {
1317
1320 pertrans,
1321 pergroupstate);
1322 else
1324 pertrans,
1325 pergroupstate);
1326 }
1328 {
1329 pertrans->haslast = false;
1330
1332 {
1335
1338 }
1339 else
1341 }
1342 }
1343
1344
1345
1346
1347 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1348 {
1350 int transno = peragg->transno;
1352
1353 pergroupstate = &pergroup[transno];
1354
1357 &aggvalues[aggno], &aggnulls[aggno]);
1358 else
1360 &aggvalues[aggno], &aggnulls[aggno]);
1361 }
1362}
1363
1364
1365
1366
1367
1368
1371{
1373
1374
1375
1376
1378 {
1379
1380
1381
1382
1384 }
1385 else
1387
1388 return NULL;
1389}
1390
1391
1392
1393
1394
1395static void
1397{
1400
1402 context.aggregated = NULL;
1403 context.unaggregated = NULL;
1404
1405
1408
1409
1410 for (int i = 0; i < agg->numCols; i++)
1411 context.unaggregated = bms_add_member(context.unaggregated,
1412 agg->grpColIdx[i]);
1413
1414 *aggregated = context.aggregated;
1415 *unaggregated = context.unaggregated;
1416}
1417
1418static bool
1420{
1421 if (node == NULL)
1422 return false;
1424 {
1426
1427
1433 else
1436 return false;
1437 }
1439 {
1444 return false;
1445 }
1447}
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465static void
1467{
1468 int setno;
1469
1470 for (setno = 0; setno < aggstate->num_hashes; ++setno)
1471 {
1473 long nbuckets;
1474 Size memory;
1475
1477 {
1479 continue;
1480 }
1481
1483
1485
1486
1489 memory);
1490
1491#ifdef USE_INJECTION_POINTS
1493 {
1496 }
1497#endif
1498
1500 }
1501
1503}
1504
1505
1506
1507
1508static void
1510{
1515 Size additionalsize;
1516
1519
1520
1521
1522
1523
1524
1525
1527
1535 perhash->aggnode->grpCollations,
1536 nbuckets,
1537 additionalsize,
1538 metacxt,
1539 tablecxt,
1540 tmpcxt,
1542}
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569static void
1571{
1576 int numHashes = aggstate->num_hashes;
1578 int j;
1579
1580
1581 find_cols(aggstate, &aggregated_colnos, &base_colnos);
1585
1586 for (int i = 0; i < scanDesc->natts; i++)
1587 {
1588 int colno = i + 1;
1589
1592 else
1594 }
1595
1596 for (j = 0; j < numHashes; ++j)
1597 {
1603 int maxCols;
1604 int i;
1605
1607
1608
1609
1610
1611
1612
1613
1614
1616 {
1619
1621 {
1623
1626 }
1627 }
1628
1629
1630
1631
1632
1633
1634
1636
1641
1642
1643 for (i = 0; i < perhash->numCols; i++)
1645
1646
1647
1648
1649
1650
1651
1652
1653 for (i = 0; i < perhash->numCols; i++)
1654 {
1658
1660 }
1661
1662
1663 i = -1;
1665 {
1668 }
1669
1670
1672 {
1674
1675 hashTlist = lappend(hashTlist, list_nth(outerTlist, varNumber));
1678 }
1679
1681
1683 perhash->aggnode->grpOperators,
1689
1692 }
1693
1695}
1696
1697
1698
1699
1702{
1703 Size tupleChunkSize;
1704 Size pergroupChunkSize;
1705 Size transitionChunkSize;
1707 tupleWidth);
1709
1710
1711
1712
1713
1714 tupleChunkSize = MAXALIGN(tupleSize);
1715 pergroupChunkSize = pergroupSize;
1716
1717
1718
1719
1720
1721 if (transitionSpace > 0)
1723 else
1724 transitionChunkSize = 0;
1725
1726 return
1728 tupleChunkSize +
1729 pergroupChunkSize +
1730 transitionChunkSize;
1731}
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751static void
1753{
1755 int i = minslot ? 1 : 0;
1756 int j = nullcheck ? 1 : 0;
1757
1760
1762 phase = &aggstate->phases[0];
1763 else
1764 phase = &aggstate->phases[1];
1765
1767 {
1770 bool dohash = true;
1771 bool dosort = false;
1772
1773
1774
1775
1776
1777
1779 dosort = true;
1780
1781
1782 if (minslot)
1783 {
1786 }
1787
1789 dosort, dohash,
1790 nullcheck);
1791
1792
1795 }
1796
1798}
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808void
1810 Size *mem_limit, uint64 *ngroups_limit,
1811 int *num_partitions)
1812{
1813 int npartitions;
1814 Size partition_mem;
1816
1817
1818 if (input_groups * hashentrysize <= hash_mem_limit)
1819 {
1820 if (num_partitions != NULL)
1821 *num_partitions = 0;
1822 *mem_limit = hash_mem_limit;
1823 *ngroups_limit = hash_mem_limit / hashentrysize;
1824 return;
1825 }
1826
1827
1828
1829
1830
1831
1833 hashentrysize,
1834 used_bits,
1835 NULL);
1836 if (num_partitions != NULL)
1837 *num_partitions = npartitions;
1838
1839 partition_mem =
1842
1843
1844
1845
1846
1847
1848 if (hash_mem_limit > 4 * partition_mem)
1849 *mem_limit = hash_mem_limit - partition_mem;
1850 else
1851 *mem_limit = hash_mem_limit * 0.75;
1852
1853 if (*mem_limit > hashentrysize)
1854 *ngroups_limit = *mem_limit / hashentrysize;
1855 else
1856 *ngroups_limit = 1;
1857}
1858
1859
1860
1861
1862
1863
1864
1865
1866static void
1868{
1871 true);
1873 true);
1875 true);
1876 Size total_mem = meta_mem + entry_mem + tval_mem;
1877 bool do_spill = false;
1878
1879#ifdef USE_INJECTION_POINTS
1880 if (ngroups >= 1000)
1881 {
1883 {
1884 do_spill = true;
1886 }
1887 }
1888#endif
1889
1890
1891
1892
1893
1897 {
1898 do_spill = true;
1899 }
1900
1901 if (do_spill)
1903}
1904
1905
1906
1907
1908
1909
1910static void
1912{
1916
1918 {
1921
1923
1925
1927
1928 for (int setno = 0; setno < aggstate->num_hashes; setno++)
1929 {
1932
1936 }
1937 }
1938}
1939
1940
1941
1942
1943
1944
1945
1946static void
1948{
1949 Size meta_mem;
1950 Size entry_mem;
1951 Size hashkey_mem;
1952 Size buffer_mem;
1953 Size total_mem;
1954
1957 return;
1958
1959
1961
1962
1964
1965
1967
1968
1970 if (from_tape)
1972
1973
1974 total_mem = meta_mem + entry_mem + hashkey_mem + buffer_mem;
1977
1978
1980 {
1982
1985 }
1986
1987
1989 {
1993 }
1994}
1995
1996
1997
1998
1999static void
2001{
2003
2004
2005
2006
2007
2009
2010
2011
2012
2013
2014
2015
2016
2017
2019 "HashAgg meta context",
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2039
2040
2042
2043
2045
2047 "HashAgg table context",
2050 maxBlockSize);
2051
2052}
2053
2054
2055
2056
2057static long
2059{
2060 long max_nbuckets;
2061 long nbuckets = ngroups;
2062
2063 max_nbuckets = memory / hashentrysize;
2064
2065
2066
2067
2068
2069 max_nbuckets >>= 1;
2070
2071 if (nbuckets > max_nbuckets)
2072 nbuckets = max_nbuckets;
2073
2074 return Max(nbuckets, 1);
2075}
2076
2077
2078
2079
2080
2081
2082static int
2084 int used_bits, int *log2_npartitions)
2085{
2087 double partition_limit;
2088 double mem_wanted;
2089 double dpartitions;
2090 int npartitions;
2091 int partition_bits;
2092
2093
2094
2095
2096
2097 partition_limit =
2100
2102
2103
2104 dpartitions = 1 + (mem_wanted / hash_mem_limit);
2105
2106 if (dpartitions > partition_limit)
2107 dpartitions = partition_limit;
2108
2113
2114
2115 npartitions = (int) dpartitions;
2116
2117
2118 partition_bits = my_log2(npartitions);
2119
2120
2121 if (partition_bits + used_bits >= 32)
2122 partition_bits = 32 - used_bits;
2123
2124 if (log2_npartitions != NULL)
2125 *log2_npartitions = partition_bits;
2126
2127
2128 npartitions = 1 << partition_bits;
2129
2130 return npartitions;
2131}
2132
2133
2134
2135
2136static void
2139{
2141 int transno;
2142
2145
2146
2147 if (aggstate->numtrans == 0)
2148 return;
2149
2151
2152
2153
2154
2155
2156 for (transno = 0; transno < aggstate->numtrans; transno++)
2157 {
2160
2162 }
2163}
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180static void
2182{
2185 int setno;
2186
2187 for (setno = 0; setno < aggstate->num_hashes; setno++)
2188 {
2194 bool isnew = false;
2195 bool *p_isnew;
2196
2197
2199
2202 outerslot,
2203 hashslot);
2204
2206 p_isnew, &hash);
2207
2208 if (entry != NULL)
2209 {
2210 if (isnew)
2213 }
2214 else
2215 {
2218
2223
2225 pergroup[setno] = NULL;
2226 }
2227 }
2228}
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2245{
2248
2250
2252 {
2253
2255 {
2259
2262 break;
2266 break;
2267 }
2268
2270 return result;
2271 }
2272
2273 return NULL;
2274}
2275
2276
2277
2278
2281{
2290 bool hasGroupingSets = aggstate->phase->numsets > 0;
2292 int currentSet;
2293 int nextSetSize;
2294 int numReset;
2295 int i;
2296
2297
2298
2299
2300
2301
2302
2303
2306
2307 peragg = aggstate->peragg;
2308 pergroups = aggstate->pergroups;
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2321 {
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2335
2336
2337
2338
2342 else
2343 numReset = numGroupingSets;
2344
2345
2346
2347
2348
2349
2350
2351
2352 for (i = 0; i < numReset; i++)
2353 {
2355 }
2356
2357
2358
2359
2360
2362 aggstate->projected_set >= (numGroupingSets - 1))
2363 {
2365 {
2371 numReset = numGroupingSets;
2372 }
2374 {
2375
2376
2377
2378
2385 }
2386 else
2387 {
2389 break;
2390 }
2391 }
2392
2393
2394
2395
2396
2397
2399 aggstate->projected_set < (numGroupingSets - 1))
2401 else
2402 nextSetSize = 0;
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2425 aggstate->projected_set < (numGroupingSets - 1) &&
2426 nextSetSize > 0 &&
2428 tmpcontext)))
2429 {
2431
2434 }
2435 else
2436 {
2437
2438
2439
2440
2441
2443
2444
2445
2446
2447
2449 {
2452 {
2453
2454
2455
2456
2458 }
2459 else
2460 {
2461
2462 if (hasGroupingSets)
2463 {
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2475
2477 {
2480 {
2481
2482
2483
2484
2485
2486
2487 break;
2488 }
2489 }
2490
2492 continue;
2493 }
2494 else
2495 {
2497
2499 return NULL;
2500 }
2501 }
2502 }
2503
2504
2505
2506
2508
2510 {
2511
2512
2513
2514
2515
2517 firstSlot, true);
2518 aggstate->grp_firstTuple = NULL;
2519
2520
2522
2523
2524
2525
2526
2527 for (;;)
2528 {
2529
2530
2531
2532
2535 {
2537 }
2538
2539
2541
2542
2544
2547 {
2548
2549
2550
2554
2555 if (hasGroupingSets)
2556 {
2558 break;
2559 }
2560 else
2561 {
2563 break;
2564 }
2565 }
2566
2568
2569
2570
2571
2572
2574 {
2577 tmpcontext))
2578 {
2580 break;
2581 }
2582 }
2583 }
2584 }
2585
2586
2587
2588
2589
2590
2591
2592
2593
2595 }
2596
2598
2600
2602
2604
2606 peragg,
2607 pergroups[currentSet]);
2608
2609
2610
2611
2612
2614 if (result)
2615 return result;
2616 }
2617
2618
2619 return NULL;
2620}
2621
2622
2623
2624
2625static void
2627{
2630
2631
2632
2633
2634
2635 for (;;)
2636 {
2639 break;
2640
2641
2643
2644
2646
2647
2649
2650
2651
2652
2653
2655 }
2656
2657
2659
2661
2665}
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679static bool
2681{
2686 bool spill_initialized = false;
2687
2689 return false;
2690
2691
2694
2698
2699
2700
2701
2702
2703
2704
2705
2708
2709
2712 for (int setno = 0; setno < aggstate->num_hashes; setno++)
2714
2716
2717
2718
2719
2720
2721
2724 {
2727 }
2728
2730
2732
2733
2734
2735
2736
2737
2738
2739
2741
2743 for (;;)
2744 {
2751 bool isnew = false;
2752 bool *p_isnew = aggstate->hash_spill_mode ? NULL : &isnew;
2753
2755
2757 if (tuple == NULL)
2758 break;
2759
2762
2765 hashslot);
2767 p_isnew, hash);
2768
2769 if (entry != NULL)
2770 {
2771 if (isnew)
2775 }
2776 else
2777 {
2778 if (!spill_initialized)
2779 {
2780
2781
2782
2783
2784 spill_initialized = true;
2787 }
2788
2790
2792 }
2793
2794
2795
2796
2797
2799 }
2800
2802
2803
2806
2807 if (spill_initialized)
2808 {
2811 }
2812 else
2814
2816
2817
2821
2823
2824 return true;
2825}
2826
2827
2828
2829
2830
2831
2832
2833
2836{
2838
2839 while (result == NULL)
2840 {
2842 if (result == NULL)
2843 {
2845 {
2847 break;
2848 }
2849 }
2850 }
2851
2852 return result;
2853}
2854
2855
2856
2857
2858
2861{
2869
2870
2871
2872
2873
2874
2876 peragg = aggstate->peragg;
2878
2879
2880
2881
2882
2884
2885
2886
2887
2888
2889 for (;;)
2890 {
2893 int i;
2894
2896
2897
2898
2899
2901 if (entry == NULL)
2902 {
2903 int nextset = aggstate->current_set + 1;
2904
2905 if (nextset < aggstate->num_hashes)
2906 {
2907
2908
2909
2910
2912
2914
2916
2917 continue;
2918 }
2919 else
2920 {
2921 return NULL;
2922 }
2923 }
2924
2925
2926
2927
2928
2929
2930
2931
2933
2934
2935
2936
2937
2940
2944
2946 {
2948
2951 }
2953
2955
2956
2957
2958
2959
2961
2965
2967
2969 if (result)
2970 return result;
2971 }
2972
2973
2974 return NULL;
2975}
2976
2977
2978
2979
2980
2981
2982
2983static void
2985 double input_groups, double hashentrysize)
2986{
2987 int npartitions;
2988 int partition_bits;
2989
2991 used_bits, &partition_bits);
2992
2993#ifdef USE_INJECTION_POINTS
2995 {
2996 npartitions = 1;
2997 partition_bits = 0;
2999 }
3000#endif
3001
3005
3006 for (int i = 0; i < npartitions; i++)
3008
3009 spill->shift = 32 - used_bits - partition_bits;
3010 if (spill->shift < 32)
3011 spill->mask = (npartitions - 1) << spill->shift;
3012 else
3013 spill->mask = 0;
3015
3016 for (int i = 0; i < npartitions; i++)
3018}
3019
3020
3021
3022
3023
3024
3025
3029{
3031 int partition;
3034 int total_written = 0;
3035 bool shouldFree;
3036
3038
3039
3041 {
3046 {
3048 {
3051 }
3052 else
3054 }
3056 }
3057 else
3058 spillslot = inputslot;
3059
3061
3062 if (spill->shift < 32)
3063 partition = (hash & spill->mask) >> spill->shift;
3064 else
3065 partition = 0;
3066
3067 spill->ntuples[partition]++;
3068
3069
3070
3071
3072
3073
3075
3076 tape = spill->partitions[partition];
3077
3079 total_written += sizeof(uint32);
3080
3082 total_written += tuple->t_len;
3083
3084 if (shouldFree)
3086
3087 return total_written;
3088}
3089
3090
3091
3092
3093
3094
3095
3098 int64 input_tuples, double input_card, int used_bits)
3099{
3101
3102 batch->setno = setno;
3107
3108 return batch;
3109}
3110
3111
3112
3113
3114
3117{
3121 size_t nread;
3123
3125 if (nread == 0)
3126 return NULL;
3127 if (nread != sizeof(uint32))
3130 errmsg_internal("unexpected EOF for tape %p: requested %zu bytes, read %zu bytes",
3131 tape, sizeof(uint32), nread)));
3132 if (hashp != NULL)
3133 *hashp = hash;
3134
3136 if (nread != sizeof(uint32))
3139 errmsg_internal("unexpected EOF for tape %p: requested %zu bytes, read %zu bytes",
3140 tape, sizeof(uint32), nread)));
3141
3143 tuple->t_len = t_len;
3144
3146 (char *) tuple + sizeof(uint32),
3147 t_len - sizeof(uint32));
3148 if (nread != t_len - sizeof(uint32))
3151 errmsg_internal("unexpected EOF for tape %p: requested %zu bytes, read %zu bytes",
3152 tape, t_len - sizeof(uint32), nread)));
3153
3154 return tuple;
3155}
3156
3157
3158
3159
3160
3161
3162
3163
3164static void
3166{
3167 int setno;
3168 int total_npartitions = 0;
3169
3171 {
3172 for (setno = 0; setno < aggstate->num_hashes; setno++)
3173 {
3175
3176 total_npartitions += spill->npartitions;
3178 }
3179
3180
3181
3182
3183
3184
3187 }
3188
3191}
3192
3193
3194
3195
3196
3197
3198static void
3200{
3201 int i;
3202 int used_bits = 32 - spill->shift;
3203
3205 return;
3206
3208 {
3211 double cardinality;
3212
3213
3215 continue;
3216
3219
3220
3222
3224 spill->ntuples[i], cardinality,
3225 used_bits);
3228 }
3229
3233}
3234
3235
3236
3237
3238static void
3240{
3241
3243 {
3244 int setno;
3245
3246 for (setno = 0; setno < aggstate->num_hashes; setno++)
3247 {
3249
3252 }
3255 }
3256
3257
3260
3261
3263 {
3266 }
3267}
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3280{
3288 int max_aggno;
3289 int max_transno;
3290 int numaggrefs;
3291 int numaggs;
3292 int numtrans;
3293 int phase;
3294 int phaseidx;
3296 Bitmapset *all_grouped_cols = NULL;
3297 int numGroupingSets = 1;
3298 int numPhases;
3299 int numHashes;
3300 int i = 0;
3301 int j = 0;
3304
3305
3307
3308
3309
3310
3315
3324 aggstate->peragg = NULL;
3332 aggstate->sort_in = NULL;
3334
3335
3336
3337
3338 numPhases = (use_hashing ? 1 : 2);
3339 numHashes = (use_hashing ? 1 : 0);
3340
3341
3342
3343
3344
3345
3347 {
3349
3350 foreach(l, node->chain)
3351 {
3353
3354 numGroupingSets = Max(numGroupingSets,
3356
3357
3358
3359
3360
3362 ++numPhases;
3363 else
3364 ++numHashes;
3365 }
3366 }
3367
3368 aggstate->maxsets = numGroupingSets;
3369 aggstate->numphases = numPhases;
3370
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3390
3391 for (i = 0; i < numGroupingSets; ++i)
3392 {
3395 }
3396
3397 if (use_hashing)
3399
3401
3402
3403
3404
3405
3406
3407
3409 eflags &= ~EXEC_FLAG_REWIND;
3412
3413
3414
3415
3420
3424
3425
3426
3427
3428
3429 if (numPhases > 2)
3430 {
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3451 }
3452
3453
3454
3455
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3474
3475
3476
3477
3479 max_aggno = -1;
3480 max_transno = -1;
3481 foreach(l, aggstate->aggs)
3482 {
3484
3485 max_aggno = Max(max_aggno, aggref->aggno);
3486 max_transno = Max(max_transno, aggref->aggtransno);
3487 }
3488 aggstate->numaggs = numaggs = max_aggno + 1;
3489 aggstate->numtrans = numtrans = max_transno + 1;
3490
3491
3492
3493
3494
3496
3498 if (numHashes)
3499 {
3504 }
3505
3506 phase = 0;
3507 for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
3508 {
3509 Agg *aggnode;
3510 Sort *sortnode;
3511
3512 if (phaseidx > 0)
3513 {
3516 }
3517 else
3518 {
3519 aggnode = node;
3520 sortnode = NULL;
3521 }
3522
3523 Assert(phase <= 1 || sortnode);
3524
3527 {
3531
3534 perhash = &aggstate->perhash[i];
3535
3536
3537 phasedata->aggnode = node;
3539
3540
3541 perhash->aggnode = aggnode;
3542
3544
3545 for (j = 0; j < aggnode->numCols; ++j)
3547
3549
3550 all_grouped_cols = bms_add_members(all_grouped_cols, cols);
3551 continue;
3552 }
3553 else
3554 {
3556 int num_sets;
3557
3559
3560 if (num_sets)
3561 {
3564
3565 i = 0;
3567 {
3570
3571
3572 for (j = 0; j < current_length; ++j)
3574
3577
3578 ++i;
3579 }
3580
3583 }
3584 else
3585 {
3586 Assert(phaseidx == 0);
3587
3590 }
3591
3592
3593
3594
3596 {
3597
3598
3599
3600
3603
3604
3605 for (int k = 0; k < phasedata->numsets; k++)
3606 {
3608
3609
3610 if (length == 0)
3611 continue;
3612
3613
3614 if (phasedata->eqfunctions[length - 1] != NULL)
3615 continue;
3616
3619 length,
3620 aggnode->grpColIdx,
3621 aggnode->grpOperators,
3622 aggnode->grpCollations,
3624 }
3625
3626
3627 if (aggnode->numCols > 0 &&
3629 {
3633 aggnode->grpColIdx,
3634 aggnode->grpOperators,
3635 aggnode->grpCollations,
3637 }
3638 }
3639
3640 phasedata->aggnode = aggnode;
3642 phasedata->sortnode = sortnode;
3643 }
3644 }
3645
3646
3647
3648
3649 i = -1;
3652
3653
3654
3655
3656
3660
3663
3664 aggstate->peragg = peraggs;
3665 aggstate->pertrans = pertransstates;
3666
3667
3670 * (numGroupingSets + numHashes));
3672
3674 {
3675 for (i = 0; i < numGroupingSets; i++)
3676 {
3678 * numaggs);
3679 }
3680
3681 aggstate->pergroups = pergroups;
3682 pergroups += numGroupingSets;
3683 }
3684
3685
3686
3687
3688 if (use_hashing)
3689 {
3691 uint64 totalGroups = 0;
3692
3697
3698
3700
3704
3705
3706
3707
3708
3709
3710
3711 for (int k = 0; k < aggstate->num_hashes; k++)
3713
3719
3720
3723
3725
3726
3728 }
3729
3730
3731
3732
3733
3734
3735
3737 {
3741 }
3742 else
3743 {
3747 }
3748
3749
3750
3751
3752
3753 foreach(l, aggstate->aggs)
3754 {
3759 int numAggTransFnArgs;
3760 int numDirectArgs;
3764 Oid finalfn_oid;
3765 Oid serialfn_oid,
3766 deserialfn_oid;
3767 Oid aggOwner;
3768 Expr *finalfnexpr;
3769 Oid aggtranstype;
3770
3771
3772 Assert(aggref->agglevelsup == 0);
3773
3775
3776 peragg = &peraggs[aggref->aggno];
3777
3778
3779 if (peragg->aggref != NULL)
3780 continue;
3781
3782 peragg->aggref = aggref;
3783 peragg->transno = aggref->aggtransno;
3784
3785
3789 elog(ERROR, "cache lookup failed for aggregate %u",
3792
3793
3800
3801
3802 aggtranstype = aggref->aggtranstype;
3804
3805
3808 else
3809 peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
3810
3813
3814
3815
3816
3817
3818 if (aggtranstype == INTERNALOID)
3819 {
3820
3821
3822
3823
3824
3826 {
3827
3829
3830 if ((aggform->aggserialfn))
3831 elog(ERROR, "serialfunc not provided for serialization aggregation");
3832 serialfn_oid = aggform->aggserialfn;
3833 }
3834
3835
3837 {
3838
3840
3841 if ((aggform->aggdeserialfn))
3842 elog(ERROR, "deserialfunc not provided for deserialization aggregation");
3843 deserialfn_oid = aggform->aggdeserialfn;
3844 }
3845 }
3846
3847
3848 {
3850
3854 elog(ERROR, "cache lookup failed for function %u",
3858
3860 {
3861 aclresult = object_aclcheck(ProcedureRelationId, finalfn_oid, aggOwner,
3867 }
3869 {
3870 aclresult = object_aclcheck(ProcedureRelationId, serialfn_oid, aggOwner,
3876 }
3878 {
3879 aclresult = object_aclcheck(ProcedureRelationId, deserialfn_oid, aggOwner,
3885 }
3886 }
3887
3888
3889
3890
3891
3892
3894 aggTransFnInputTypes);
3895
3896
3898
3899
3900 if (aggform->aggfinalextra)
3901 peragg->numFinalArgs = numAggTransFnArgs + 1;
3902 else
3904
3905
3908
3909
3910
3911
3912
3914 {
3917 aggtranstype,
3918 aggref->aggtype,
3919 aggref->inputcollid,
3920 finalfn_oid,
3921 &finalfnexpr);
3924 }
3925
3926
3930
3931
3932
3933
3934
3935 pertrans = &pertransstates[aggref->aggtransno];
3936 if (pertrans->aggref == NULL)
3937 {
3938 Datum textInitVal;
3940 bool initValueIsNull;
3941 Oid transfn_oid;
3942
3943
3944
3945
3946
3947
3949 {
3950 transfn_oid = aggform->aggcombinefn;
3951
3952
3954 elog(ERROR, "combinefn not set for aggregate function");
3955 }
3956 else
3957 transfn_oid = aggform->aggtransfn;
3958
3964
3965
3966
3967
3968
3970 Anum_pg_aggregate_agginitval,
3971 &initValueIsNull);
3972 if (initValueIsNull)
3974 else
3976
3978 {
3979 Oid combineFnInputTypes[] = {aggtranstype,
3980 aggtranstype};
3981
3982
3983
3984
3985
3986
3988
3989
3991 aggref, transfn_oid, aggtranstype,
3992 serialfn_oid, deserialfn_oid,
3994 combineFnInputTypes, 2);
3995
3996
3997
3998
3999
4000
4001
4002 if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
4004 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
4005 errmsg("combine function with transition type %s must not be declared STRICT",
4007 }
4008 else
4009 {
4010
4011 if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
4013 else
4015
4017 aggref, transfn_oid, aggtranstype,
4018 serialfn_oid, deserialfn_oid,
4020 aggTransFnInputTypes,
4021 numAggTransFnArgs);
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4033 {
4034 if (numAggTransFnArgs <= numDirectArgs ||
4036 aggtranstype))
4038 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
4039 errmsg("aggregate %u needs to have compatible input type and transition type",
4041 }
4042 }
4043 }
4044 else
4047 }
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4061 (errcode(ERRCODE_GROUPING_ERROR),
4062 errmsg("aggregate function calls cannot be nested")));
4063
4064
4065
4066
4067
4068
4069
4070
4071 for (phaseidx = 0; phaseidx < aggstate->numphases; phaseidx++)
4072 {
4074 bool dohash = false;
4075 bool dosort = false;
4076
4077
4079 continue;
4080
4082 {
4083
4084
4085
4086
4087 dohash = true;
4088 dosort = true;
4089 }
4091 {
4092
4093
4094
4095
4096
4097 continue;
4098 }
4101 {
4102 dohash = false;
4103 dosort = true;
4104 }
4106 {
4107 dohash = true;
4108 dosort = false;
4109 }
4110 else
4112
4114 false);
4115
4116
4118 }
4119
4120 return aggstate;
4121}
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133static void
4137 Oid transfn_oid, Oid aggtranstype,
4138 Oid aggserialfn, Oid aggdeserialfn,
4140 Oid *inputTypes, int numArguments)
4141{
4142 int numGroupingSets = Max(aggstate->maxsets, 1);
4143 Expr *transfnexpr;
4144 int numTransArgs;
4145 Expr *serialfnexpr = NULL;
4146 Expr *deserialfnexpr = NULL;
4148 int numInputs;
4149 int numDirectArgs;
4150 List *sortlist;
4151 int numSortCols;
4152 int numDistinctCols;
4153 int i;
4154
4155
4156 pertrans->aggref = aggref;
4158 pertrans->aggCollation = aggref->inputcollid;
4164
4165
4167
4168
4170
4172
4173
4175
4176
4177
4178
4179
4181 numArguments,
4182 numDirectArgs,
4183 aggref->aggvariadic,
4184 aggtranstype,
4185 aggref->inputcollid,
4186 transfn_oid,
4188 &transfnexpr,
4189 NULL);
4190
4193
4198 numTransArgs,
4200 (Node *) aggstate, NULL);
4201
4202
4206
4208 {
4210 &serialfnexpr);
4213
4218 1,
4220 (Node *) aggstate, NULL);
4221 }
4222
4224 {
4226 &deserialfnexpr);
4229
4234 2,
4236 (Node *) aggstate, NULL);
4237 }
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254 if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
4255 {
4256 sortlist = NIL;
4257 numSortCols = numDistinctCols = 0;
4259 }
4260 else if (aggref->aggpresorted && aggref->aggdistinct == NIL)
4261 {
4262 sortlist = NIL;
4263 numSortCols = numDistinctCols = 0;
4265 }
4267 {
4269 numSortCols = numDistinctCols = list_length(sortlist);
4272 }
4273 else
4274 {
4275 sortlist = aggref->aggorder;
4277 numDistinctCols = 0;
4279 }
4280
4283
4284
4285
4286
4287
4288
4289 if (numSortCols > 0 || aggref->aggfilter)
4290 {
4295 }
4296
4297 if (numSortCols > 0)
4298 {
4299
4300
4301
4302
4304
4305
4307
4308
4309 if (numInputs == 1)
4310 {
4314 }
4315 else if (numDistinctCols > 0)
4316 {
4317
4321 }
4322
4323
4331 (bool *) palloc(numSortCols * sizeof(bool));
4332
4333 i = 0;
4334 foreach(lc, sortlist)
4335 {
4338
4339
4341
4346 i++;
4347 }
4348 Assert(i == numSortCols);
4349 }
4350
4352 {
4353 Oid *ops;
4354
4355 Assert(numArguments > 0);
4357
4358 ops = palloc(numDistinctCols * sizeof(Oid));
4359
4360 i = 0;
4363
4364
4365 if (numDistinctCols == 1)
4367 else
4370 numDistinctCols,
4372 ops,
4376 }
4377
4380}
4381
4382
4385{
4386 Oid typinput,
4387 typioparam;
4388 char *strInitVal;
4390
4394 typioparam, -1);
4395 pfree(strInitVal);
4396 return initVal;
4397}
4398
4399void
4401{
4403 int transno;
4404 int numGroupingSets = Max(node->maxsets, 1);
4405 int setno;
4406
4407
4408
4409
4410
4411
4413 {
4415
4416 Assert(ParallelWorkerNumber <= node->shared_info->num_workers);
4421 }
4422
4423
4424
4429
4431
4433 {
4436 }
4438 {
4441 }
4442
4443
4444 for (transno = 0; transno < node->numtrans; transno++)
4445 {
4447
4448 for (setno = 0; setno < numGroupingSets; setno++)
4449 {
4452 }
4453 }
4454
4455
4456 for (setno = 0; setno < numGroupingSets; setno++)
4460
4463}
4464
4465void
4467{
4471 int transno;
4472 int numGroupingSets = Max(node->maxsets, 1);
4473 int setno;
4474
4476
4478 {
4479
4480
4481
4482
4483
4484
4486 return;
4487
4488
4489
4490
4491
4492
4493
4494
4497 {
4501 return;
4502 }
4503 }
4504
4505
4506 for (transno = 0; transno < node->numtrans; transno++)
4507 {
4508 for (setno = 0; setno < numGroupingSets; setno++)
4509 {
4511
4513 {
4516 }
4517 }
4518 }
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528 for (setno = 0; setno < numGroupingSets; setno++)
4529 {
4531 }
4532
4533
4535 {
4538 }
4540
4541
4544
4545
4546
4547
4548
4549
4551 {
4553
4557
4560
4563
4564
4566 }
4567
4569 {
4570
4571
4572
4573 for (setno = 0; setno < numGroupingSets; setno++)
4574 {
4577 }
4578
4579
4581
4584 }
4585
4586 if (outerPlan->chgParam == NULL)
4588}
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613int
4615{
4617 {
4618 if (aggcontext)
4619 {
4622
4624 }
4626 }
4628 {
4629 if (aggcontext)
4632 }
4633
4634
4635 if (aggcontext)
4636 *aggcontext = NULL;
4637 return 0;
4638}
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4659{
4661 {
4665
4666
4667 curperagg = aggstate->curperagg;
4668
4669 if (curperagg)
4670 return curperagg->aggref;
4671
4672
4674
4675 if (curpertrans)
4676 return curpertrans->aggref;
4677 }
4678 return NULL;
4679}
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4693{
4695 {
4697
4699 }
4700 return NULL;
4701}
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717bool
4719{
4721 {
4725
4726
4727 curperagg = aggstate->curperagg;
4728
4729 if (curperagg)
4731
4732
4734
4735 if (curpertrans)
4737 }
4738 return true;
4739}
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756void
4760{
4762 {
4765
4767
4768 return;
4769 }
4770 elog(ERROR, "aggregate function cannot register a callback in this context");
4771}
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785void
4787{
4789
4790
4792 return;
4793
4798}
4799
4800
4801
4802
4803
4804
4805
4806void
4808{
4810
4811
4813 return;
4814
4818
4823}
4824
4825
4826
4827
4828
4829
4830
4831void
4833{
4836}
4837
4838
4839
4840
4841
4842
4843
4844void
4846{
4849
4851 return;
4852
4858}
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
int bms_next_member(const Bitmapset *a, int prevbit)
Bitmapset * bms_del_member(Bitmapset *a, int x)
void bms_free(Bitmapset *a)
int bms_num_members(const Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_copy(const Bitmapset *a)
#define TextDatumGetCString(d)
MemoryContext BumpContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
#define MemSet(start, val, len)
#define OidIsValid(objectId)
Datum datumCopy(Datum value, bool typByVal, int typLen)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void ExecReScan(PlanState *node)
Datum ExecAggCopyTransValue(AggState *aggstate, AggStatePerTrans pertrans, Datum newValue, bool newValueIsNull, Datum oldValue, bool oldValueIsNull)
ExprState * ExecInitQual(List *qual, PlanState *parent)
List * ExecInitExprList(List *nodes, PlanState *parent)
ExprState * ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
void execTuplesHashPrepare(int numCols, const Oid *eqOperators, Oid **eqFuncOids, FmgrInfo **hashFunctions)
TupleHashEntry LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash)
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 *hash)
TupleHashTable BuildTupleHashTable(PlanState *parent, TupleDesc inputDesc, const TupleTableSlotOps *inputOps, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, long nbuckets, Size additionalsize, MemoryContext metacxt, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
void ResetTupleHashTable(TupleHashTable hashtable)
void ExecEndNode(PlanState *node)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
const TupleTableSlotOps TTSOpsVirtual
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
TupleTableSlot * ExecAllocTableSlot(List **tupleTable, TupleDesc desc, const TupleTableSlotOps *tts_ops)
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsMinimalTuple
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
TupleDesc ExecTypeFromTL(List *targetList)
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
TupleDesc ExecGetResultType(PlanState *planstate)
void ReScanExprContext(ExprContext *econtext)
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
ExprContext * CreateWorkExprContext(EState *estate)
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
void(* ExprContextCallbackFunction)(Datum arg)
#define InstrCountFiltered1(node, delta)
#define outerPlanState(node)
#define ScanTupleHashTable(htable, iter)
#define ResetTupleHashIterator(htable, iter)
struct AggStatePerGroupData * AggStatePerGroup
struct AggStatePerTransData * AggStatePerTrans
struct AggregateInstrumentation AggregateInstrumentation
struct AggStatePerAggData * AggStatePerAgg
static MinimalTuple TupleHashEntryGetTuple(TupleHashEntry entry)
#define EXEC_FLAG_BACKWARD
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
static void * TupleHashEntryGetAdditional(TupleHashTable hashtable, TupleHashEntry entry)
#define ResetExprContext(econtext)
static bool ExecQual(ExprState *state, ExprContext *econtext)
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
static size_t TupleHashEntrySize(void)
static TupleTableSlot * ExecProcNode(PlanState *node)
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
static void ExecEvalExprNoReturnSwitchContext(ExprState *state, ExprContext *econtext)
#define EXEC_FLAG_EXPLAIN_ONLY
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
#define SizeForFunctionCallInfo(nargs)
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
#define AGG_CONTEXT_WINDOW
#define LOCAL_FCINFO(name, nargs)
#define AGG_CONTEXT_AGGREGATE
struct FunctionCallInfoBaseData * FunctionCallInfo
#define FunctionCallInvoke(fcinfo)
#define fmgr_info_set_expr(expr, finfo)
char * format_type_be(Oid type_oid)
uint32 hash_bytes_uint32(uint32 k)
Assert(PointerIsAligned(start, uint64))
void heap_freetuple(HeapTuple htup)
MinimalTupleData * MinimalTuple
#define HeapTupleIsValid(tuple)
#define SizeofMinimalTupleHeader
static void * GETSTRUCT(const HeapTupleData *tuple)
void initHyperLogLog(hyperLogLogState *cState, uint8 bwidth)
double estimateHyperLogLog(hyperLogLogState *cState)
void addHyperLogLog(hyperLogLogState *cState, uint32 hash)
void freeHyperLogLog(hyperLogLogState *cState)
#define IsParallelWorker()
static int initValue(long lng_val)
#define INJECTION_POINT(name)
#define INJECTION_POINT_CACHED(name)
#define IS_INJECTION_POINT_ATTACHED(name)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
List * lcons_int(int datum, List *list)
List * list_delete_last(List *list)
void list_free(List *list)
void list_free_deep(List *list)
void LogicalTapeRewindForRead(LogicalTape *lt, size_t buffer_size)
size_t LogicalTapeRead(LogicalTape *lt, void *ptr, size_t size)
int64 LogicalTapeSetBlocks(LogicalTapeSet *lts)
void LogicalTapeClose(LogicalTape *lt)
void LogicalTapeSetClose(LogicalTapeSet *lts)
LogicalTapeSet * LogicalTapeSetCreate(bool preallocate, SharedFileSet *fileset, int worker)
void LogicalTapeWrite(LogicalTape *lt, const void *ptr, size_t size)
LogicalTape * LogicalTapeCreate(LogicalTapeSet *lts)
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
RegProcedure get_opcode(Oid opno)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
char * get_func_name(Oid funcid)
void MemoryContextReset(MemoryContext context)
void pfree(void *pointer)
void * palloc0(Size size)
Size MemoryContextMemAllocated(MemoryContext context, bool recurse)
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_MAXSIZE
#define ALLOCSET_DEFAULT_MINSIZE
#define ALLOCSET_DEFAULT_SIZES
#define ALLOCSET_DEFAULT_INITSIZE
#define CHECK_FOR_INTERRUPTS()
static void hashagg_finish_initial_spills(AggState *aggstate)
static long hash_choose_num_buckets(double hashentrysize, long ngroups, Size memory)
static void hash_agg_check_limits(AggState *aggstate)
static void initialize_hash_entry(AggState *aggstate, TupleHashTable hashtable, TupleHashEntry entry)
static void find_hash_columns(AggState *aggstate)
static bool agg_refill_hash_table(AggState *aggstate)
static void build_hash_table(AggState *aggstate, int setno, long nbuckets)
void ExecAggEstimate(AggState *node, ParallelContext *pcxt)
struct FindColsContext FindColsContext
static void hash_agg_enter_spill_mode(AggState *aggstate)
struct HashAggBatch HashAggBatch
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
static void find_cols(AggState *aggstate, Bitmapset **aggregated, Bitmapset **unaggregated)
void AggRegisterCallback(FunctionCallInfo fcinfo, ExprContextCallbackFunction func, Datum arg)
#define HASHAGG_HLL_BIT_WIDTH
static void agg_fill_hash_table(AggState *aggstate)
Aggref * AggGetAggref(FunctionCallInfo fcinfo)
static void initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
static TupleTableSlot * fetch_input_tuple(AggState *aggstate)
static void hashagg_spill_finish(AggState *aggstate, HashAggSpill *spill, int setno)
static bool find_cols_walker(Node *node, FindColsContext *context)
void ExecAggInitializeWorker(AggState *node, ParallelWorkerContext *pwcxt)
void ExecAggRetrieveInstrumentation(AggState *node)
static TupleTableSlot * project_aggregates(AggState *aggstate)
static MinimalTuple hashagg_batch_read(HashAggBatch *batch, uint32 *hashp)
struct HashAggSpill HashAggSpill
static void process_ordered_aggregate_multi(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
void ExecReScanAgg(AggState *node)
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
static void advance_transition_function(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
static void hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions)
static void finalize_aggregates(AggState *aggstate, AggStatePerAgg peraggs, AggStatePerGroup pergroup)
static void initialize_phase(AggState *aggstate, int newphase)
Size hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace)
static void initialize_aggregates(AggState *aggstate, AggStatePerGroup *pergroups, int numReset)
static TupleTableSlot * agg_retrieve_hash_table_in_memory(AggState *aggstate)
void ExecAggInitializeDSM(AggState *node, ParallelContext *pcxt)
static void finalize_aggregate(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull)
#define HASHAGG_MAX_PARTITIONS
static void lookup_hash_entries(AggState *aggstate)
static TupleTableSlot * agg_retrieve_direct(AggState *aggstate)
static void hashagg_recompile_expressions(AggState *aggstate, bool minslot, bool nullcheck)
static void prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet)
bool AggStateIsShared(FunctionCallInfo fcinfo)
static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggstate, EState *estate, Aggref *aggref, Oid transfn_oid, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, Oid *inputTypes, int numArguments)
static TupleTableSlot * agg_retrieve_hash_table(AggState *aggstate)
static void process_ordered_aggregate_single(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
static void advance_aggregates(AggState *aggstate)
static TupleTableSlot * ExecAgg(PlanState *pstate)
static void prepare_hash_slot(AggStatePerHash perhash, TupleTableSlot *inputslot, TupleTableSlot *hashslot)
static void build_hash_tables(AggState *aggstate)
void ExecEndAgg(AggState *node)
#define HASHAGG_READ_BUFFER_SIZE
static void hashagg_reset_spill_state(AggState *aggstate)
static Size hashagg_spill_tuple(AggState *aggstate, HashAggSpill *spill, TupleTableSlot *inputslot, uint32 hash)
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
static void finalize_partialaggregate(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull)
AggState * ExecInitAgg(Agg *node, EState *estate, int eflags)
static void hashagg_spill_init(HashAggSpill *spill, LogicalTapeSet *tapeset, int used_bits, double input_groups, double hashentrysize)
#define HASHAGG_MIN_PARTITIONS
void hash_agg_set_limits(double hashentrysize, double input_groups, int used_bits, Size *mem_limit, uint64 *ngroups_limit, int *num_partitions)
MemoryContext AggGetTempMemoryContext(FunctionCallInfo fcinfo)
#define HASHAGG_PARTITION_FACTOR
static HashAggBatch * hashagg_batch_new(LogicalTape *input_tape, int setno, int64 input_tuples, double input_card, int used_bits)
#define HASHAGG_WRITE_BUFFER_SIZE
static void hash_create_memory(AggState *aggstate)
static int hash_choose_num_partitions(double input_groups, double hashentrysize, int used_bits, int *log2_npartitions)
struct AggStatePerGroupData AggStatePerGroupData
Oid exprCollation(const Node *expr)
#define expression_tree_walker(n, w, c)
size_t get_hash_memory_limit(void)
#define DO_AGGSPLIT_SKIPFINAL(as)
#define IsA(nodeptr, _type_)
#define DO_AGGSPLIT_DESERIALIZE(as)
#define DO_AGGSPLIT_COMBINE(as)
#define DO_AGGSPLIT_SERIALIZE(as)
#define castNode(_type_, nodeptr)
#define InvokeFunctionExecuteHook(objectId)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
void build_aggregate_finalfn_expr(Oid *agg_input_types, int num_finalfn_inputs, Oid agg_state_type, Oid agg_result_type, Oid agg_input_collation, Oid finalfn_oid, Expr **finalfnexpr)
void build_aggregate_deserialfn_expr(Oid deserialfn_oid, Expr **deserialfnexpr)
void build_aggregate_transfn_expr(Oid *agg_input_types, int agg_num_inputs, int agg_num_direct_inputs, bool agg_variadic, Oid agg_state_type, Oid agg_input_collation, Oid transfn_oid, Oid invtransfn_oid, Expr **transfnexpr, Expr **invtransfnexpr)
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
void build_aggregate_serialfn_expr(Oid serialfn_oid, Expr **serialfnexpr)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
FormData_pg_aggregate * Form_pg_aggregate
FormData_pg_attribute * Form_pg_attribute
#define pg_nextpower2_size_t
#define pg_prevpower2_size_t
static int list_length(const List *l)
static void * list_nth(const List *list, int n)
#define list_nth_node(type, list, n)
FormData_pg_proc * Form_pg_proc
static bool DatumGetBool(Datum X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
static unsigned hash(unsigned *uv, int n)
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
#define shm_toc_estimate_chunk(e, sz)
#define shm_toc_estimate_keys(e, cnt)
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
TupleTableSlot * hashslot
TupleHashIterator hashiter
AttrNumber * hashGrpColIdxHash
AttrNumber * hashGrpColIdxInput
Bitmapset ** grouped_cols
ExprState * evaltrans_cache[2][2]
TupleTableSlot * sortslot
Tuplesortstate ** sortstates
TupleTableSlot * uniqslot
FunctionCallInfo deserialfn_fcinfo
FunctionCallInfo serialfn_fcinfo
FunctionCallInfo transfn_fcinfo
MemoryContext hash_metacxt
Tuplesortstate * sort_out
AggStatePerGroup * all_pergroups
AggStatePerGroup * hash_pergroup
int hash_planned_partitions
ExprContext * curaggcontext
MemoryContext hash_tablecxt
AggStatePerTrans curpertrans
AggStatePerTrans pertrans
struct LogicalTapeSet * hash_tapeset
ExprContext * hashcontext
SharedAggInfo * shared_info
uint64 hash_ngroups_limit
AggStatePerGroup * pergroups
uint64 hash_ngroups_current
TupleTableSlot * hash_spill_wslot
struct HashAggSpill * hash_spills
TupleTableSlot * sort_slot
TupleTableSlot * hash_spill_rslot
ExprContext ** aggcontexts
Bitmapset * colnos_needed
MemoryContext es_query_cxt
MemoryContext ecxt_per_tuple_memory
TupleTableSlot * ecxt_innertuple
TupleTableSlot * ecxt_outertuple
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
hyperLogLogState * hll_card
LogicalTape ** partitions
shm_toc_estimator estimator
Instrumentation * instrument
const TupleTableSlotOps * outerops
ExprContext * ps_ExprContext
ProjectionInfo * ps_ProjInfo
ExecProcNodeMtd ExecProcNode
TupleTableSlot * ss_ScanTupleSlot
TupleDesc tts_tupleDescriptor
const TupleTableSlotOps *const tts_ops
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
void tuplesort_performsort(Tuplesortstate *state)
void tuplesort_end(Tuplesortstate *state)
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, SortCoordinate coordinate, int sortopt)
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, TupleTableSlot *slot, Datum *abbrev)
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, int sortopt)
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, bool copy, Datum *val, bool *isNull, Datum *abbrev)
static void slot_getsomeattrs(TupleTableSlot *slot, int attnum)
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
static void slot_getallattrs(TupleTableSlot *slot)