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{

337 uint32 mask;

338 int shift;

341

342

343

344

345

346

347

348

349

350

352{

353 int setno;

354 int used_bits;

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 {

1425 Var *var = (Var *) node;

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 (OidIsValid(aggform->aggserialfn))

3831 elog(ERROR, "serialfunc not provided for serialization aggregation");

3832 serialfn_oid = aggform->aggserialfn;

3833 }

3834

3835

3837 {

3838

3840

3841 if (OidIsValid(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,

4374 &aggstate->ss.ps);

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)