PostgreSQL Source Code: src/backend/executor/nodeWindowAgg.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

35

57

58

59

60

61

63{

67 void *localmem;

68 int markptr;

69 int readptr;

70 int64 markpos;

71 int64 seekpos;

73

74

75

76

77

79{

80

83

85

87

89

90

91

92

93

96

97 bool plain_agg;

98 int aggno;

99

102

103

104

105

107{

108

112

113

114

115

116

117

121

122 int numFinalArgs;

123

124

125

126

129

130

131

132

135

136

137

138

139

146

147 int wfuncno;

148

149

151

152

155

157

158

159 bool restart;

161

174 Datum *result, bool *isnull);

175

179 Datum *result, bool *isnull);

180

184

190

195

200

201

202

203

204

205

206static void

210{

212

213

214

215

216

217

220

223 else

224 {

230 }

235}

236

237

238

239

240

241static void

245{

248 int numArguments = perfuncstate->numArguments;

251 int i;

255

257

258

259 if (filter)

260 {

261 bool isnull;

263

265 {

267 return;

268 }

269 }

270

271

272 i = 1;

273 foreach(arg, wfuncstate->args)

274 {

276

277 fcinfo->args[i].value = ExecEvalExpr(argstate, econtext,

278 &fcinfo->args[i].isnull);

279 i++;

280 }

281

283 {

284

285

286

287

288

289 for (i = 1; i <= numArguments; i++)

290 {

291 if (fcinfo->args[i].isnull)

292 {

294 return;

295 }

296 }

297

298

299

300

301

302

303

304

305

306

308 {

316 return;

317 }

318

320 {

321

322

323

324

325

326

327

328

331 return;

332 }

333 }

334

335

336

337

338

340 numArguments + 1,

342 (Node *) winstate, NULL);

343 fcinfo->args[0].value = peraggstate->transValue;

348

349

350

351

352

355 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),

356 errmsg("moving-aggregate transition function must not return null")));

357

358

359

360

361

362

363

365

366

367

368

369

370

371

372

373

376 {

377 if (!fcinfo->isnull)

378 {

381 false,

384 ;

385 else

389 }

391 {

393 false,

396 else

398 }

399 }

400

404}

405

406

407

408

409

410

411

412

413

414

415

416

417

418static bool

422{

425 int numArguments = perfuncstate->numArguments;

428 int i;

432

434

435

436 if (filter)

437 {

438 bool isnull;

440

442 {

444 return true;

445 }

446 }

447

448

449 i = 1;

450 foreach(arg, wfuncstate->args)

451 {

453

454 fcinfo->args[i].value = ExecEvalExpr(argstate, econtext,

455 &fcinfo->args[i].isnull);

456 i++;

457 }

458

460 {

461

462

463

464

465

466 for (i = 1; i <= numArguments; i++)

467 {

468 if (fcinfo->args[i].isnull)

469 {

471 return true;

472 }

473 }

474 }

475

476

478

479

480

481

482

483

484

485

486

488 elog(ERROR, "aggregate transition value is NULL before inverse transition");

489

490

491

492

493

494

495

497 {

501 peraggstate);

502 return true;

503 }

504

505

506

507

508

509

511 numArguments + 1,

513 (Node *) winstate, NULL);

514 fcinfo->args[0].value = peraggstate->transValue;

519

520

521

522

523 if (fcinfo->isnull)

524 {

526 return false;

527 }

528

529

531

532

533

534

535

536

537

538

539

540

541

542

545 {

546 if (!fcinfo->isnull)

547 {

550 false,

553 ;

554 else

558 }

560 {

562 false,

565 else

567 }

568 }

569

573

574 return true;

575}

576

577

578

579

580

581static void

585 Datum *result, bool *isnull)

586{

588

590

591

592

593

595 {

597 int numFinalArgs = peraggstate->numFinalArgs;

598 bool anynull;

599 int i;

600

602 numFinalArgs,

604 (Node *) winstate, NULL);

605 fcinfo->args[0].value =

611

612

613 for (i = 1; i < numFinalArgs; i++)

614 {

615 fcinfo->args[i].value = (Datum) 0;

616 fcinfo->args[i].isnull = true;

617 anynull = true;

618 }

619

620 if (fcinfo->flinfo->fn_strict && anynull)

621 {

622

623 *result = (Datum) 0;

624 *isnull = true;

625 }

626 else

627 {

629

630 winstate->curaggcontext = peraggstate->aggcontext;

632 winstate->curaggcontext = NULL;

633 *isnull = fcinfo->isnull;

635 fcinfo->isnull,

637 }

638 }

639 else

640 {

641 *result =

646 }

647

649}

650

651

652

653

654

655

656

657

658

659

660

661

662static void

664{

666 int wfuncno,

667 numaggs,

668 numaggs_restart,

669 i;

670 int64 aggregatedupto_nonrestarted;

676

677 numaggs = winstate->numaggs;

678 if (numaggs == 0)

679 return;

680

681

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

738 elog(ERROR, "window frame head moved backward");

739

740

741

742

743

744

745

746

747

748

749

750

757 {

758 for (i = 0; i < numaggs; i++)

759 {

760 peraggstate = &winstate->peragg[i];

761 wfuncno = peraggstate->wfuncno;

764 }

765 return;

766 }

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783 numaggs_restart = 0;

784 for (i = 0; i < numaggs; i++)

785 {

786 peraggstate = &winstate->peragg[i];

792 {

793 peraggstate->restart = true;

794 numaggs_restart++;

795 }

796 else

797 peraggstate->restart = false;

798 }

799

800

801

802

803

804

805

806

807 while (numaggs_restart < numaggs &&

809 {

810

811

812

813

815 temp_slot))

816 elog(ERROR, "could not re-fetch previously fetched frame row");

817

818

820

821

822

823

824

825 for (i = 0; i < numaggs; i++)

826 {

827 bool ok;

828

829 peraggstate = &winstate->peragg[i];

830 if (peraggstate->restart)

831 continue;

832

833 wfuncno = peraggstate->wfuncno;

835 &winstate->perfunc[wfuncno],

836 peraggstate);

837 if (!ok)

838 {

839

840 peraggstate->restart = true;

841 numaggs_restart++;

842 }

843 }

844

845

847

848

851 }

852

853

854

855

856

857

859

860

861

862

863

864 if (agg_winobj->markptr >= 0)

866

867

868

869

870

871

872

873

874

875

876

877 if (numaggs_restart > 0)

879 for (i = 0; i < numaggs; i++)

880 {

881 peraggstate = &winstate->peragg[i];

882

883

885 numaggs_restart == 0 ||

887

888 if (peraggstate->restart)

889 {

890 wfuncno = peraggstate->wfuncno;

892 &winstate->perfunc[wfuncno],

893 peraggstate);

894 }

896 {

901 }

902 }

903

904

905

906

907

908

909

910

911

912

913

914 aggregatedupto_nonrestarted = winstate->aggregatedupto;

915 if (numaggs_restart > 0 &&

917 {

920 }

921

922

923

924

925

926

927

928

929 for (;;)

930 {

931 int ret;

932

933

935 {

937 agg_row_slot))

938 break;

939 }

940

941

942

943

944

946 if (ret < 0)

947 break;

948 if (ret == 0)

949 goto next_tuple;

950

951

953

954

955 for (i = 0; i < numaggs; i++)

956 {

957 peraggstate = &winstate->peragg[i];

958

959

960 if (!peraggstate->restart &&

961 winstate->aggregatedupto < aggregatedupto_nonrestarted)

962 continue;

963

964 wfuncno = peraggstate->wfuncno;

966 &winstate->perfunc[wfuncno],

967 peraggstate);

968 }

969

970next_tuple:

971

973

974

977 }

978

979

980 Assert(aggregatedupto_nonrestarted <= winstate->aggregatedupto);

981

982

983

984

985 for (i = 0; i < numaggs; i++)

986 {

988 bool *isnull;

989

990 peraggstate = &winstate->peragg[i];

991 wfuncno = peraggstate->wfuncno;

995 &winstate->perfunc[wfuncno],

996 peraggstate,

997 result, isnull);

998

999

1000

1001

1002

1003

1004

1005

1007 {

1014 }

1015 else

1016 {

1018 }

1020 }

1021}

1022

1023

1024

1025

1026

1027

1028

1029

1030

1031

1032static void

1034 Datum *result, bool *isnull)

1035{

1038

1040

1041

1042

1043

1044

1045

1046

1050 (Node *) perfuncstate->winobj, NULL);

1051

1052 for (int argno = 0; argno < perfuncstate->numArguments; argno++)

1053 fcinfo->args[argno].isnull = true;

1054

1056

1058 *isnull = fcinfo->isnull;

1059

1060

1061

1062

1063

1064

1065

1066

1067 if (!perfuncstate->resulttypeByVal && !fcinfo->isnull &&

1072

1074}

1075

1076

1077

1078

1079

1080

1081

1082

1083

1086{

1089 int numfuncs = winstate->numfuncs;

1090

1091

1093

1094

1096

1097

1098

1099

1100

1101

1102 winstate->current_ptr = 0;

1103

1104

1106

1107

1108 if (winstate->numaggs > 0)

1109 {

1111 int readptr_flags = 0;

1112

1113

1114

1115

1116

1119 {

1120

1122

1124 }

1125

1127 readptr_flags);

1128 }

1129

1130

1131 for (int i = 0; i < numfuncs; i++)

1132 {

1134

1136 {

1138

1140 0);

1143 }

1144 }

1145

1146

1147

1148

1149

1150

1151

1152

1153

1155

1157 {

1168 }

1169

1170

1171

1172

1173

1174

1175

1176

1178

1182 {

1185 }

1186}

1187

1188

1189

1190

1191

1192static void

1194{

1196 int numfuncs = winstate->numfuncs;

1197

1210 winstate->grouptailpos = -1;

1216

1217

1218

1219

1220

1222 {

1224

1227 else

1228 {

1229

1232 return;

1233 }

1234 }

1235

1236

1239

1241

1242 if (winstate->numaggs > 0)

1243 {

1245

1246

1247 agg_winobj->markpos = -1;

1248 agg_winobj->seekpos = -1;

1249

1250

1253 }

1254

1255

1256 for (int i = 0; i < numfuncs; i++)

1257 {

1259

1261 {

1263

1266 }

1267 }

1268

1269

1270

1271

1272

1275}

1276

1277

1278

1279

1280

1281static void

1283{

1288

1290 return;

1292 return;

1293

1294

1295

1296

1297

1298

1299

1301 {

1304

1305 pos = -1;

1306 }

1307

1308

1309

1310

1311

1312

1313

1314

1315

1317 pos = -1;

1318

1320

1321

1323

1324 while (winstate->spooled_rows <= pos || pos == -1)

1325 {

1328 {

1329

1332 break;

1333 }

1334

1336 {

1338

1341

1342

1344 {

1345

1346

1347

1351 break;

1352 }

1353 }

1354

1355

1356

1357

1358

1360 {

1361

1364 }

1365 }

1366

1368}

1369

1370

1371

1372

1373

1374

1375static void

1377{

1378 int i;

1379

1380 for (i = 0; i < winstate->numfuncs; i++)

1381 {

1383

1384

1385 if (perfuncstate->winobj)

1387 }

1388

1389

1390

1391

1392

1393

1394

1397 for (i = 0; i < winstate->numaggs; i++)

1398 {

1401 }

1402

1403 if (winstate->buffer)

1407}

1408

1409

1410

1411

1412

1413

1414

1415

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425static int

1427{

1429

1430 Assert(pos >= 0);

1431

1432

1433

1434

1435

1437 if (pos < winstate->frameheadpos)

1438 return 0;

1439

1440

1441

1442

1443

1444

1446 {

1448 {

1449

1451 return -1;

1452 }

1454 {

1455

1458 return -1;

1459 }

1460 else

1462 }

1464 {

1466 {

1468

1469

1471 offset = -offset;

1472

1473 if (pos > winstate->currentpos + offset)

1474 return -1;

1475 }

1477 {

1478

1481 return -1;

1482 }

1483 else

1485 }

1486

1487

1489 {

1491 return 0;

1492 }

1496 {

1498

1499

1501 return 0;

1502

1504 {

1506 if (pos < winstate->grouptailpos)

1507 return 0;

1508 }

1509 }

1510

1511

1512 return 1;

1513}

1514

1515

1516

1517

1518

1519

1520

1521

1522

1523

1524

1525static void

1527{

1531

1533 return;

1534

1535

1537

1539 {

1540

1543 }

1545 {

1547 {

1548

1551 }

1553 {

1554

1556 {

1560 return;

1561 }

1562

1563

1564

1565

1566

1567

1568

1569

1574 {

1575

1578 elog(ERROR, "unexpected end of tuplestore");

1579 }

1580

1582 {

1585 break;

1586

1591 break;

1592 }

1594 }

1595 else

1597 }

1599 {

1601 {

1602

1604

1606 offset = -offset;

1607

1609

1613 {

1614

1618 }

1620 }

1622 {

1623

1624

1625

1626

1627

1628

1629

1630

1631 int sortCol = node->ordColIdx[0];

1632 bool sub,

1633 less;

1634

1635

1637

1638

1640 sub = true;

1641 else

1642 sub = false;

1643 less = false;

1644

1646 {

1647 sub = !sub;

1648 less = true;

1649 }

1650

1655 {

1656

1659 elog(ERROR, "unexpected end of tuplestore");

1660 }

1661

1663 {

1665 currval;

1666 bool headisnull,

1667 currisnull;

1668

1670 &headisnull);

1672 &currisnull);

1673 if (headisnull || currisnull)

1674 {

1675

1677 {

1678

1679 if (!headisnull || currisnull)

1680 break;

1681 }

1682 else

1683 {

1684

1685 if (headisnull || !currisnull)

1686 break;

1687 }

1688 }

1689 else

1690 {

1693 headval,

1694 currval,

1698 break;

1699 }

1700

1705 break;

1706 }

1708 }

1710 {

1711

1712

1713

1714

1715

1716

1717

1718

1720 int64 minheadgroup;

1721

1723 minheadgroup = winstate->currentgroup - offset;

1724 else

1725 minheadgroup = winstate->currentgroup + offset;

1726

1731 {

1732

1735 elog(ERROR, "unexpected end of tuplestore");

1736 }

1737

1739 {

1741 break;

1743

1748 break;

1752 }

1755 }

1756 else

1758 }

1759 else

1761

1763}

1764

1765

1766

1767

1768

1769

1770

1771

1772

1773

1774

1775static void

1777{

1781

1783 return;

1784

1785

1787

1789 {

1790

1794 }

1796 {

1798 {

1799

1802 }

1804 {

1805

1807 {

1812 return;

1813 }

1814

1815

1816

1817

1818

1819

1820

1821

1822

1827 {

1828

1831 elog(ERROR, "unexpected end of tuplestore");

1832 }

1833

1835 {

1839 break;

1840

1845 break;

1846 }

1848 }

1849 else

1851 }

1853 {

1855 {

1856

1858

1860 offset = -offset;

1861

1863

1867 {

1868

1872 }

1874 }

1876 {

1877

1878

1879

1880

1881

1882

1883

1884

1885 int sortCol = node->ordColIdx[0];

1886 bool sub,

1887 less;

1888

1889

1891

1892

1894 sub = true;

1895 else

1896 sub = false;

1897 less = true;

1898

1900 {

1901 sub = !sub;

1902 less = false;

1903 }

1904

1909 {

1910

1913 elog(ERROR, "unexpected end of tuplestore");

1914 }

1915

1917 {

1919 currval;

1920 bool tailisnull,

1921 currisnull;

1922

1924 &tailisnull);

1926 &currisnull);

1927 if (tailisnull || currisnull)

1928 {

1929

1931 {

1932

1933 if (!tailisnull)

1934 break;

1935 }

1936 else

1937 {

1938

1939 if (!currisnull)

1940 break;

1941 }

1942 }

1943 else

1944 {

1947 tailval,

1948 currval,

1952 break;

1953 }

1954

1959 break;

1960 }

1962 }

1964 {

1965

1966

1967

1968

1969

1970

1971

1972

1974 int64 maxtailgroup;

1975

1977 maxtailgroup = winstate->currentgroup - offset;

1978 else

1979 maxtailgroup = winstate->currentgroup + offset;

1980

1985 {

1986

1989 elog(ERROR, "unexpected end of tuplestore");

1990 }

1991

1993 {

1995 break;

1997

2002 break;

2006 }

2009 }

2010 else

2012 }

2013 else

2015

2017}

2018

2019

2020

2021

2022

2023

2024

2025static void

2027{

2030

2032 return;

2033

2034

2036

2037

2039 {

2044 return;

2045 }

2046

2047

2048

2049

2050

2051

2052

2053

2057 for (;;)

2058 {

2059

2064 break;

2068 break;

2069 }

2072

2074}

2075

2076

2077

2078

2079

2080

2083{

2088 bool isnull;

2090 bool byval;

2091

2092

2094

2096

2098 {

2101 econtext,

2102 &isnull);

2103 if (isnull)

2105 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),

2106 errmsg("frame starting offset must not be null")));

2107

2110 &byval);

2113 {

2114

2116

2117 if (offset < 0)

2119 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),

2120 errmsg("frame starting offset must not be negative")));

2121 }

2122 }

2123

2125 {

2128 econtext,

2129 &isnull);

2130 if (isnull)

2132 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),

2133 errmsg("frame ending offset must not be null")));

2134

2137 &byval);

2140 {

2141

2143

2144 if (offset < 0)

2146 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),

2147 errmsg("frame ending offset must not be negative")));

2148 }

2149 }

2151}

2152

2153

2154

2155

2156

2157

2158

2159

2160

2161

2164{

2168 int i;

2169 int numfuncs;

2170

2172

2174 return NULL;

2175

2176

2177

2178

2179

2180

2183

2184

2185 for (;;)

2186 {

2188 {

2189

2191

2192 }

2193 else

2194 {

2195

2197

2200

2201 }

2202

2203

2204

2205

2206

2208

2209

2212 {

2214

2216 {

2219

2220

2222 }

2223 else

2224 {

2225

2227 return NULL;

2228 }

2229 }

2230

2231

2233

2234

2236

2237

2238

2239

2240

2241

2242

2243

2244

2245

2246

2247

2248

2249

2250

2251

2257 {

2261 elog(ERROR, "unexpected end of tuplestore");

2264 {

2268 }

2270 }

2271 else

2272 {

2275 elog(ERROR, "unexpected end of tuplestore");

2276 }

2277

2278

2280 {

2281

2282

2283

2284 numfuncs = winstate->numfuncs;

2285 for (i = 0; i < numfuncs; i++)

2286 {

2288

2290 continue;

2294 }

2295

2296

2297

2298

2299 if (winstate->numaggs > 0)

2301 }

2302

2303

2304

2305

2306

2307

2308

2309

2310

2311

2312

2319

2320

2321

2322

2324

2325

2326

2327

2328

2329

2331

2333

2335 {

2337

2338

2339

2340

2341

2343 {

2344

2345

2346

2347

2348

2349

2350

2351

2352

2353

2355 {

2356

2357

2358

2359

2360

2361

2362

2363

2364

2365

2366 numfuncs = winstate->numfuncs;

2367 for (i = 0; i < numfuncs; i++)

2368 {

2371 }

2372

2373

2374

2375

2376

2377

2378

2380 {

2382 continue;

2383 }

2384 else

2385 {

2387 }

2388 }

2389 else

2390 {

2391

2392

2393

2394

2396 return NULL;

2397 }

2398 }

2399

2400

2401

2402

2404 {

2406 continue;

2407 }

2408

2409 break;

2410 }

2411

2412

2413

2414

2415

2417 break;

2418 }

2419

2420 return slot;

2421}

2422

2423

2424

2425

2426

2427

2428

2429

2432{

2440 int numfuncs,

2441 wfuncno,

2442 numaggs,

2443 aggno;

2446

2447

2449

2450

2451

2452

2457

2458

2460

2461

2462

2463

2464

2465

2470

2471

2474 "WindowAgg Partition",

2476

2477

2478

2479

2480

2481

2482

2485 "WindowAgg Aggregates",

2487

2488

2490

2491

2494

2495

2496

2497

2498

2499

2500

2501

2504

2505

2506

2507

2508

2509

2511

2512

2514

2515

2516

2517

2520

2521

2522

2523

2524

2527

2528

2532

2533

2534

2535

2544

2545

2546

2547

2548

2549

2551

2553 {

2564 }

2565

2566

2567

2568

2571

2572

2577 node->partColIdx,

2578 node->partOperators,

2579 node->partCollations,

2580 &winstate->ss.ps);

2581

2586 node->ordColIdx,

2587 node->ordOperators,

2588 node->ordCollations,

2589 &winstate->ss.ps);

2590

2591

2592

2593

2594 numfuncs = winstate->numfuncs;

2595 numaggs = winstate->numaggs;

2599

2600

2601

2602

2605 winstate->perfunc = perfunc;

2606 winstate->peragg = peragg;

2607

2608 wfuncno = -1;

2609 aggno = -1;

2610 foreach(l, winstate->funcs)

2611 {

2616 int i;

2617

2618 if (wfunc->winref != node->winref)

2619 elog(ERROR, "WindowFunc with winref %u assigned to WindowAgg with winref %u",

2621

2622

2623 for (i = 0; i <= wfuncno; i++)

2624 {

2625 if (equal(wfunc, perfunc[i].wfunc) &&

2627 break;

2628 }

2629 if (i <= wfuncno)

2630 {

2631

2633 continue;

2634 }

2635

2636

2637 perfuncstate = &perfunc[++wfuncno];

2638

2639

2640 wfuncstate->wfuncno = wfuncno;

2641

2642

2649

2650

2651 perfuncstate->wfuncstate = wfuncstate;

2652 perfuncstate->wfunc = wfunc;

2654 perfuncstate->winCollation = wfunc->inputcollid;

2655

2659

2660

2661

2662

2663

2664 perfuncstate->plain_agg = wfunc->winagg;

2665 if (wfunc->winagg)

2666 {

2668

2669 perfuncstate->aggno = ++aggno;

2670 peraggstate = &winstate->peragg[aggno];

2672 peraggstate->wfuncno = wfuncno;

2673 }

2674 else

2675 {

2677

2678 winobj->winstate = winstate;

2681 perfuncstate->winobj = winobj;

2682

2683

2687 }

2688 }

2689

2690

2691 winstate->numfuncs = wfuncno + 1;

2692 winstate->numaggs = aggno + 1;

2693

2694

2695 if (winstate->numaggs > 0)

2696 {

2698

2699 agg_winobj->winstate = winstate;

2701 agg_winobj->localmem = NULL;

2702

2703 agg_winobj->markptr = -1;

2704 agg_winobj->readptr = -1;

2706 }

2707

2708

2710

2711

2716

2717

2725

2730

2731 return winstate;

2732}

2733

2734

2735

2736

2737

2738void

2740{

2742 int i;

2743

2744 if (node->buffer != NULL)

2745 {

2747

2748

2749 node->buffer = NULL;

2750 }

2751

2753

2755 {

2758 }

2761

2764

2767}

2768

2769

2770

2771

2772

2773void

2775{

2778

2781

2782

2784

2785

2795

2796

2799

2800

2801

2802

2803

2804 if (outerPlan->chgParam == NULL)

2806}

2807

2808

2809

2810

2811

2812

2816{

2818 int numArguments;

2821 Oid aggtranstype;

2824 bool use_ma_code;

2825 Oid transfn_oid,

2826 invtransfn_oid,

2827 finalfn_oid;

2828 bool finalextra;

2829 char finalmodify;

2830 Expr *transfnexpr,

2831 *invtransfnexpr,

2832 *finalfnexpr;

2833 Datum textInitVal;

2834 int i;

2836

2838

2839 i = 0;

2840 foreach(lc, wfunc->args)

2841 {

2843 }

2844

2847 elog(ERROR, "cache lookup failed for aggregate %u",

2850

2851

2852

2853

2854

2855

2856

2857

2858

2859

2860

2861

2862

2863

2864

2865

2866

2867

2868

2869 if (OidIsValid(aggform->aggminvtransfn))

2870 use_ma_code = false;

2871 else if (aggform->aggmfinalmodify == AGGMODIFY_READ_ONLY &&

2872 aggform->aggfinalmodify != AGGMODIFY_READ_ONLY)

2873 use_ma_code = true;

2875 use_ma_code = false;

2877 use_ma_code = false;

2879 use_ma_code = false;

2880 else

2881 use_ma_code = true;

2882 if (use_ma_code)

2883 {

2884 peraggstate->transfn_oid = transfn_oid = aggform->aggmtransfn;

2885 peraggstate->invtransfn_oid = invtransfn_oid = aggform->aggminvtransfn;

2886 peraggstate->finalfn_oid = finalfn_oid = aggform->aggmfinalfn;

2887 finalextra = aggform->aggmfinalextra;

2888 finalmodify = aggform->aggmfinalmodify;

2889 aggtranstype = aggform->aggmtranstype;

2890 initvalAttNo = Anum_pg_aggregate_aggminitval;

2891 }

2892 else

2893 {

2894 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;

2896 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;

2897 finalextra = aggform->aggfinalextra;

2898 finalmodify = aggform->aggfinalmodify;

2899 aggtranstype = aggform->aggtranstype;

2900 initvalAttNo = Anum_pg_aggregate_agginitval;

2901 }

2902

2903

2904

2905

2906

2907

2908

2909 {

2911 Oid aggOwner;

2912

2916 elog(ERROR, "cache lookup failed for function %u",

2920

2921 aclresult = object_aclcheck(ProcedureRelationId, transfn_oid, aggOwner,

2927

2929 {

2930 aclresult = object_aclcheck(ProcedureRelationId, invtransfn_oid, aggOwner,

2936 }

2937

2939 {

2940 aclresult = object_aclcheck(ProcedureRelationId, finalfn_oid, aggOwner,

2946 }

2947 }

2948

2949

2950

2951

2952

2953

2954 if (finalmodify != AGGMODIFY_READ_ONLY)

2956 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

2957 errmsg("aggregate function %s does not support use as a window function",

2959

2960

2961 if (finalextra)

2962 peraggstate->numFinalArgs = numArguments + 1;

2963 else

2965

2966

2968 aggtranstype,

2969 inputTypes,

2970 numArguments);

2971

2972

2974 numArguments,

2975 0,

2976 false,

2977 aggtranstype,

2978 wfunc->inputcollid,

2979 transfn_oid,

2980 invtransfn_oid,

2981 &transfnexpr,

2982 &invtransfnexpr);

2983

2984

2987

2989 {

2992 }

2993

2995 {

2998 aggtranstype,

2999 wfunc->wintype,

3000 wfunc->inputcollid,

3001 finalfn_oid,

3002 &finalfnexpr);

3005 }

3006

3007

3014

3015

3016

3017

3018

3019 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple, initvalAttNo,

3021

3024 else

3026 aggtranstype);

3027

3028

3029

3030

3031

3032

3033

3034

3036 {

3037 if (numArguments < 1 ||

3040 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

3041 errmsg("aggregate %u needs to have compatible input type and transition type",

3043 }

3044

3045

3046

3047

3048

3049

3050

3051

3052

3056 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

3057 errmsg("strictness of aggregate's forward and inverse transition functions must match")));

3058

3059

3060

3061

3062

3063

3064

3065

3066

3067

3068

3069

3070

3071

3072

3076 "WindowAgg Per Aggregate",

3078 else

3080

3082

3083 return peraggstate;

3084}

3085

3088{

3089 Oid typinput,

3090 typioparam;

3091 char *strInitVal;

3093

3097 typioparam, -1);

3098 pfree(strInitVal);

3099 return initVal;

3100}

3101

3102

3103

3104

3105

3106

3107

3108static bool

3111{

3114

3115

3117 return true;

3118

3119 econtext->ecxt_outertuple = slot1;

3120 econtext->ecxt_innertuple = slot2;

3122}

3123

3124

3125

3126

3127

3128

3129

3130

3131static bool

3133{

3136

3137

3139

3140

3141 if (pos < 0)

3142 return false;

3143

3144

3146

3148 return false;

3149

3150 if (pos < winobj->markpos)

3151 elog(ERROR, "cannot fetch row before WindowObject's mark position");

3152

3154

3156

3157

3158

3159

3160 if (winobj->seekpos < pos - 1)

3161 {

3163 pos - 1 - winobj->seekpos,

3164 true))

3165 elog(ERROR, "unexpected end of tuplestore");

3166 winobj->seekpos = pos - 1;

3167 }

3168 else if (winobj->seekpos > pos + 1)

3169 {

3171 winobj->seekpos - (pos + 1),

3172 false))

3173 elog(ERROR, "unexpected end of tuplestore");

3174 winobj->seekpos = pos + 1;

3175 }

3176 else if (winobj->seekpos == pos)

3177 {

3178

3179

3180

3181

3182

3183

3184

3187 }

3188

3189

3190

3191

3192

3193

3194

3195

3196

3197 if (winobj->seekpos > pos)

3198 {

3200 elog(ERROR, "unexpected end of tuplestore");

3202 }

3203 else

3204 {

3206 elog(ERROR, "unexpected end of tuplestore");

3208 }

3209

3211

3213

3214 return true;

3215}

3216

3217

3218

3219

3220

3221

3222

3223

3224

3225

3226

3227

3228

3229

3230

3231

3232

3233

3234

3235void *

3237{

3239 if (winobj->localmem == NULL)

3243}

3244

3245

3246

3247

3248

3249

3252{

3255}

3256

3257

3258

3259

3260

3261

3262

3263

3264

3267{

3271}

3272

3273

3274

3275

3276

3277

3278

3279

3280

3281

3282

3283void

3285{

3287

3289 winstate = winobj->winstate;

3290

3291 if (markpos < winobj->markpos)

3292 elog(ERROR, "cannot move WindowObject's mark position backward");

3294 if (markpos > winobj->markpos)

3295 {

3297 markpos - winobj->markpos,

3298 true);

3299 winobj->markpos = markpos;

3300 }

3302 if (markpos > winobj->seekpos)

3303 {

3305 markpos - winobj->seekpos,

3306 true);

3307 winobj->seekpos = markpos;

3308 }

3309}

3310

3311

3312

3313

3314

3315

3316

3317

3318bool

3320{

3325 bool res;

3326

3328 winstate = winobj->winstate;

3330

3331

3333 return true;

3334

3335

3336

3337

3338

3341

3344 pos1);

3347 pos2);

3348

3349 res = are_peers(winstate, slot1, slot2);

3350

3353

3354 return res;

3355}

3356

3357

3358

3359

3360

3361

3362

3363

3364

3365

3366

3367

3368

3369

3370

3371

3372

3373

3374

3377 int relpos, int seektype, bool set_mark,

3378 bool *isnull, bool *isout)

3379{

3383 bool gottuple;

3385

3387 winstate = winobj->winstate;

3390

3391 switch (seektype)

3392 {

3394 abs_pos = winstate->currentpos + relpos;

3395 break;

3397 abs_pos = relpos;

3398 break;

3401 abs_pos = winstate->spooled_rows - 1 + relpos;

3402 break;

3403 default:

3404 elog(ERROR, "unrecognized window seek type: %d", seektype);

3405 abs_pos = 0;

3406 break;

3407 }

3408

3410

3411 if (!gottuple)

3412 {

3413 if (isout)

3414 *isout = true;

3415 *isnull = true;

3416 return (Datum) 0;

3417 }

3418 else

3419 {

3420 if (isout)

3421 *isout = false;

3422 if (set_mark)

3426 econtext, isnull);

3427 }

3428}

3429

3430

3431

3432

3433

3434

3435

3436

3437

3438

3439

3440

3441

3442

3443

3444

3445

3446

3447

3448

3449

3450

3451

3452

3453

3454

3455

3456

3457

3458

3459

3460

3461

3462

3465 int relpos, int seektype, bool set_mark,

3466 bool *isnull, bool *isout)

3467{

3473

3475 winstate = winobj->winstate;

3478

3479 switch (seektype)

3480 {

3482 elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame");

3483 abs_pos = mark_pos = 0;

3484 break;

3486

3487 if (relpos < 0)

3488 goto out_of_frame;

3491 mark_pos = abs_pos;

3492

3493

3494

3495

3496

3497

3498

3499

3500

3501

3502

3503

3504

3506 {

3507 case 0:

3508

3509 break;

3511 if (abs_pos >= winstate->currentpos &&

3513 abs_pos++;

3514 break;

3519 {

3522

3523 abs_pos += winstate->grouptailpos - overlapstart;

3524 }

3525 break;

3530 {

3533

3534 if (abs_pos == overlapstart)

3536 else

3537 abs_pos += winstate->grouptailpos - overlapstart - 1;

3538 }

3539 break;

3540 default:

3541 elog(ERROR, "unrecognized frame option state: 0x%x",

3543 break;

3544 }

3545 break;

3547

3548 if (relpos > 0)

3549 goto out_of_frame;

3551 abs_pos = winstate->frametailpos - 1 + relpos;

3552

3553

3554

3555

3556

3557

3558

3559

3560

3561

3563 {

3564 case 0:

3565

3566 mark_pos = abs_pos;

3567 break;

3569 if (abs_pos <= winstate->currentpos &&

3571 abs_pos--;

3573 if (abs_pos < winstate->frameheadpos)

3574 goto out_of_frame;

3576 break;

3579 if (abs_pos < winstate->grouptailpos &&

3581 {

3584

3585 abs_pos -= overlapend - winstate->groupheadpos;

3586 }

3588 if (abs_pos < winstate->frameheadpos)

3589 goto out_of_frame;

3591 break;

3594 if (abs_pos < winstate->grouptailpos &&

3596 {

3599

3600 if (abs_pos == overlapend - 1)

3602 else

3603 abs_pos -= overlapend - 1 - winstate->groupheadpos;

3604 }

3606 if (abs_pos < winstate->frameheadpos)

3607 goto out_of_frame;

3609 break;

3610 default:

3611 elog(ERROR, "unrecognized frame option state: 0x%x",

3613 mark_pos = 0;

3614 break;

3615 }

3616 break;

3617 default:

3618 elog(ERROR, "unrecognized window seek type: %d", seektype);

3619 abs_pos = mark_pos = 0;

3620 break;

3621 }

3622

3624 goto out_of_frame;

3625

3626

3628 goto out_of_frame;

3629

3630 if (isout)

3631 *isout = false;

3632 if (set_mark)

3636 econtext, isnull);

3637

3638out_of_frame:

3639 if (isout)

3640 *isout = true;

3641 *isnull = true;

3642 return (Datum) 0;

3643}

3644

3645

3646

3647

3648

3649

3650

3651

3652

3653

3654

3655

3656

3657

3660{

3663

3665 winstate = winobj->winstate;

3666

3668

3671 econtext, isnull);

3672}

void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)

AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)

#define TextDatumGetCString(d)

#define MemSet(start, val, len)

#define OidIsValid(objectId)

bool contain_subplans(Node *clause)

bool contain_volatile_functions(Node *clause)

Datum datumCopy(Datum value, bool typByVal, int typLen)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

bool equal(const void *a, const void *b)

void ExecReScan(PlanState *node)

ExprState * ExecInitExpr(Expr *node, PlanState *parent)

ExprState * ExecInitQual(List *qual, PlanState *parent)

ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)

void ExecEndNode(PlanState *node)

PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)

const TupleTableSlotOps TTSOpsVirtual

TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)

void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)

const TupleTableSlotOps TTSOpsMinimalTuple

void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)

void ExecAssignExprContext(EState *estate, PlanState *planstate)

void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)

struct WindowStatePerAggData * WindowStatePerAgg

#define InstrCountFiltered1(node, delta)

#define outerPlanState(node)

@ WINDOWAGG_PASSTHROUGH_STRICT

struct WindowStatePerFuncData * WindowStatePerFunc

#define EXEC_FLAG_BACKWARD

static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)

#define ResetExprContext(econtext)

static bool ExecQual(ExprState *state, ExprContext *econtext)

static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)

static TupleTableSlot * ExecProcNode(PlanState *node)

static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)

static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)

ExpandedObjectHeader * DatumGetEOHP(Datum d)

void DeleteExpandedObject(Datum d)

#define MakeExpandedObjectReadOnly(d, isnull, typlen)

#define DatumIsReadWriteExpandedObject(d, isnull, typlen)

void fmgr_info(Oid functionId, FmgrInfo *finfo)

Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)

Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5)

void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)

#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)

#define LOCAL_FCINFO(name, nargs)

#define FunctionCallInvoke(fcinfo)

#define fmgr_info_set_expr(expr, finfo)

Assert(PointerIsAligned(start, uint64))

#define HeapTupleIsValid(tuple)

static void * GETSTRUCT(const HeapTupleData *tuple)

if(TABLE==NULL||TABLE_index==NULL)

void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)

void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)

char * get_func_name(Oid funcid)

void MemoryContextReset(MemoryContext context)

void * MemoryContextAllocZero(MemoryContext context, Size size)

void pfree(void *pointer)

void * palloc0(Size size)

MemoryContext CurrentMemoryContext

MemoryContext MemoryContextGetParent(MemoryContext context)

void MemoryContextDelete(MemoryContext context)

#define AllocSetContextCreate

#define ALLOCSET_DEFAULT_SIZES

#define CHECK_FOR_INTERRUPTS()

Oid exprType(const Node *expr)

Datum WinGetFuncArgInPartition(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)

void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)

static void begin_partition(WindowAggState *winstate)

struct WindowObjectData WindowObjectData

static void update_grouptailpos(WindowAggState *winstate)

Datum WinGetFuncArgInFrame(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)

static TupleTableSlot * ExecWindowAgg(PlanState *pstate)

struct WindowStatePerAggData WindowStatePerAggData

static Datum GetAggInitVal(Datum textInitVal, Oid transtype)

static void spool_tuples(WindowAggState *winstate, int64 pos)

static void advance_windowaggregate(WindowAggState *winstate, WindowStatePerFunc perfuncstate, WindowStatePerAgg peraggstate)

static int row_is_in_frame(WindowAggState *winstate, int64 pos, TupleTableSlot *slot)

void ExecEndWindowAgg(WindowAggState *node)

static void eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, Datum *result, bool *isnull)

struct WindowStatePerFuncData WindowStatePerFuncData

static WindowStatePerAggData * initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, WindowStatePerAgg peraggstate)

static void finalize_windowaggregate(WindowAggState *winstate, WindowStatePerFunc perfuncstate, WindowStatePerAgg peraggstate, Datum *result, bool *isnull)

static bool advance_windowaggregate_base(WindowAggState *winstate, WindowStatePerFunc perfuncstate, WindowStatePerAgg peraggstate)

static bool window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot)

static pg_noinline void prepare_tuplestore(WindowAggState *winstate)

void ExecReScanWindowAgg(WindowAggState *node)

int64 WinGetCurrentPosition(WindowObject winobj)

WindowAggState * ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)

bool WinRowsArePeers(WindowObject winobj, int64 pos1, int64 pos2)

static pg_noinline void calculate_frame_offsets(PlanState *pstate)

void WinSetMarkPosition(WindowObject winobj, int64 markpos)

static void eval_windowaggregates(WindowAggState *winstate)

static void release_partition(WindowAggState *winstate)

static void update_frametailpos(WindowAggState *winstate)

static void update_frameheadpos(WindowAggState *winstate)

static void initialize_windowaggregate(WindowAggState *winstate, WindowStatePerFunc perfuncstate, WindowStatePerAgg peraggstate)

static bool are_peers(WindowAggState *winstate, TupleTableSlot *slot1, TupleTableSlot *slot2)

Datum WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)

int64 WinGetPartitionRowCount(WindowObject winobj)

#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)

Oid resolve_aggregate_transtype(Oid aggfuncid, Oid aggtranstype, Oid *inputTypes, int numArguments)

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)

bool IsBinaryCoercible(Oid srctype, Oid targettype)

#define FRAMEOPTION_END_CURRENT_ROW

#define FRAMEOPTION_END_OFFSET

#define FRAMEOPTION_EXCLUDE_CURRENT_ROW

#define FRAMEOPTION_END_OFFSET_PRECEDING

#define FRAMEOPTION_START_UNBOUNDED_PRECEDING

#define FRAMEOPTION_START_CURRENT_ROW

#define FRAMEOPTION_START_OFFSET

#define FRAMEOPTION_EXCLUDE_TIES

#define FRAMEOPTION_RANGE

#define FRAMEOPTION_EXCLUDE_GROUP

#define FRAMEOPTION_GROUPS

#define FRAMEOPTION_END_UNBOUNDED_FOLLOWING

#define FRAMEOPTION_START_OFFSET_PRECEDING

#define FRAMEOPTION_EXCLUSION

FormData_pg_aggregate * Form_pg_aggregate

static int list_length(const List *l)

static void * list_nth(const List *list, int n)

FormData_pg_proc * Form_pg_proc

static bool DatumGetBool(Datum X)

static int64 DatumGetInt64(Datum X)

static Datum BoolGetDatum(bool X)

static Datum ObjectIdGetDatum(Oid X)

static Pointer DatumGetPointer(Datum X)

char * format_procedure(Oid procedure_oid)

MemoryContext ecxt_per_tuple_memory

TupleTableSlot * ecxt_innertuple

TupleTableSlot * ecxt_scantuple

MemoryContext ecxt_per_query_memory

TupleTableSlot * ecxt_outertuple

const TupleTableSlotOps * outerops

ExprContext * ps_ExprContext

ProjectionInfo * ps_ProjInfo

ExecProcNodeMtd ExecProcNode

TupleTableSlot * ss_ScanTupleSlot

TupleDesc tts_tupleDescriptor

MemoryContext partcontext

TupleTableSlot * framehead_slot

FmgrInfo startInRangeFunc

TupleTableSlot * frametail_slot

ExprState * ordEqfunction

TupleTableSlot * temp_slot_2

TupleTableSlot * agg_row_slot

struct WindowObjectData * agg_winobj

WindowStatePerFunc perfunc

MemoryContext curaggcontext

ExprState * partEqfunction

TupleTableSlot * first_part_slot

TupleTableSlot * temp_slot_1

WindowAggState * winstate

WindowFuncExprState * wfuncstate

void ReleaseSysCache(HeapTuple tuple)

HeapTuple SearchSysCache1(int cacheId, Datum key1)

Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)

bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)

void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)

void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)

void tuplestore_clear(Tuplestorestate *state)

int tuplestore_alloc_read_pointer(Tuplestorestate *state, int eflags)

Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)

void tuplestore_trim(Tuplestorestate *state)

bool tuplestore_advance(Tuplestorestate *state, bool forward)

bool tuplestore_in_memory(Tuplestorestate *state)

void tuplestore_end(Tuplestorestate *state)

void tuplestore_set_eflags(Tuplestorestate *state, int eflags)

bool tuplestore_skiptuples(Tuplestorestate *state, int64 ntuples, bool forward)

static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)

static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)

static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)

#define WindowObjectIsValid(winobj)

#define WINDOW_SEEK_CURRENT