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{
74
75
76
77
78
79
80
83
84
85
86
87
89{
90
93
95
97
99
100
101
102
103
106
110
113
114
115
116
118{
119
123
124
125
126
127
128
132
133 int numFinalArgs;
134
135
136
137
140
141
142
143
146
147
148
149
150
157
159
160
162
163
166
168
169
172
185 Datum *result, bool *isnull);
186
190 Datum *result, bool *isnull);
191
195
201
206
211
213 int relpos, int seektype,
214 bool set_mark, bool *isnull,
215 bool *isout);
217 int64 abs_pos, bool *isnull,
218 bool *isout);
222 int64 pos, int argno);
224 int64 pos, int argno);
226 int64 pos, int argno, bool isnull);
227
228
229
230
231#define NN_UNKNOWN 0x00
232#define NN_NULL 0x01
233#define NN_NOTNULL 0x02
234#define NN_MASK 0x03
235#define NN_BITS_PER_MEMBER 2
236
237#define NN_ITEM_PER_VAR (BITS_PER_BYTE / NN_BITS_PER_MEMBER)
238
239#define NN_POS_TO_BYTES(pos) ((pos) / NN_ITEM_PER_VAR)
240
241#define NN_BYTES_TO_POS(bytes) ((bytes) * NN_ITEM_PER_VAR)
242
243#define NN_SHIFT(pos) ((pos) % NN_ITEM_PER_VAR) * NN_BITS_PER_MEMBER
244
245
246
247
248
249static void
253{
255
256
257
258
259
260
263
266 else
267 {
273 }
278}
279
280
281
282
283
284static void
288{
291 int numArguments = perfuncstate->numArguments;
294 int i;
298
300
301
302 if (filter)
303 {
304 bool isnull;
306
308 {
310 return;
311 }
312 }
313
314
315 i = 1;
316 foreach(arg, wfuncstate->args)
317 {
319
320 fcinfo->args[i].value = ExecEvalExpr(argstate, econtext,
321 &fcinfo->args[i].isnull);
322 i++;
323 }
324
326 {
327
328
329
330
331
332 for (i = 1; i <= numArguments; i++)
333 {
334 if (fcinfo->args[i].isnull)
335 {
337 return;
338 }
339 }
340
341
342
343
344
345
346
347
348
349
351 {
359 return;
360 }
361
363 {
364
365
366
367
368
369
370
371
374 return;
375 }
376 }
377
378
379
380
381
383 numArguments + 1,
385 (Node *) winstate, NULL);
386 fcinfo->args[0].value = peraggstate->transValue;
391
392
393
394
395
398 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
399 errmsg("moving-aggregate transition function must not return null")));
400
401
402
403
404
405
406
408
409
410
411
412
413
414
415
416
419 {
420 if (!fcinfo->isnull)
421 {
424 false,
427 ;
428 else
432 }
434 {
436 false,
439 else
441 }
442 }
443
447}
448
449
450
451
452
453
454
455
456
457
458
459
460
461static bool
465{
468 int numArguments = perfuncstate->numArguments;
471 int i;
475
477
478
479 if (filter)
480 {
481 bool isnull;
483
485 {
487 return true;
488 }
489 }
490
491
492 i = 1;
493 foreach(arg, wfuncstate->args)
494 {
496
497 fcinfo->args[i].value = ExecEvalExpr(argstate, econtext,
498 &fcinfo->args[i].isnull);
499 i++;
500 }
501
503 {
504
505
506
507
508
509 for (i = 1; i <= numArguments; i++)
510 {
511 if (fcinfo->args[i].isnull)
512 {
514 return true;
515 }
516 }
517 }
518
519
521
522
523
524
525
526
527
528
529
531 elog(ERROR, "aggregate transition value is NULL before inverse transition");
532
533
534
535
536
537
538
540 {
544 peraggstate);
545 return true;
546 }
547
548
549
550
551
552
554 numArguments + 1,
556 (Node *) winstate, NULL);
557 fcinfo->args[0].value = peraggstate->transValue;
562
563
564
565
566 if (fcinfo->isnull)
567 {
569 return false;
570 }
571
572
574
575
576
577
578
579
580
581
582
583
584
585
588 {
589 if (!fcinfo->isnull)
590 {
593 false,
596 ;
597 else
601 }
603 {
605 false,
608 else
610 }
611 }
612
616
617 return true;
618}
619
620
621
622
623
624static void
628 Datum *result, bool *isnull)
629{
631
633
634
635
636
638 {
640 int numFinalArgs = peraggstate->numFinalArgs;
641 bool anynull;
642 int i;
643
645 numFinalArgs,
647 (Node *) winstate, NULL);
648 fcinfo->args[0].value =
654
655
656 for (i = 1; i < numFinalArgs; i++)
657 {
658 fcinfo->args[i].value = (Datum) 0;
659 fcinfo->args[i].isnull = true;
660 anynull = true;
661 }
662
663 if (fcinfo->flinfo->fn_strict && anynull)
664 {
665
666 *result = (Datum) 0;
667 *isnull = true;
668 }
669 else
670 {
672
673 winstate->curaggcontext = peraggstate->aggcontext;
675 winstate->curaggcontext = NULL;
676 *isnull = fcinfo->isnull;
678 fcinfo->isnull,
680 }
681 }
682 else
683 {
684 *result =
689 }
690
692}
693
694
695
696
697
698
699
700
701
702
703
704
705static void
707{
709 int wfuncno,
710 numaggs,
711 numaggs_restart,
712 i;
713 int64 aggregatedupto_nonrestarted;
719
720 numaggs = winstate->numaggs;
721 if (numaggs == 0)
722 return;
723
724
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
781 elog(ERROR, "window frame head moved backward");
782
783
784
785
786
787
788
789
790
791
792
793
800 {
801 for (i = 0; i < numaggs; i++)
802 {
803 peraggstate = &winstate->peragg[i];
804 wfuncno = peraggstate->wfuncno;
807 }
808 return;
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826 numaggs_restart = 0;
827 for (i = 0; i < numaggs; i++)
828 {
829 peraggstate = &winstate->peragg[i];
835 {
836 peraggstate->restart = true;
837 numaggs_restart++;
838 }
839 else
840 peraggstate->restart = false;
841 }
842
843
844
845
846
847
848
849
850 while (numaggs_restart < numaggs &&
852 {
853
854
855
856
858 temp_slot))
859 elog(ERROR, "could not re-fetch previously fetched frame row");
860
861
863
864
865
866
867
868 for (i = 0; i < numaggs; i++)
869 {
870 bool ok;
871
872 peraggstate = &winstate->peragg[i];
873 if (peraggstate->restart)
874 continue;
875
876 wfuncno = peraggstate->wfuncno;
878 &winstate->perfunc[wfuncno],
879 peraggstate);
880 if (!ok)
881 {
882
883 peraggstate->restart = true;
884 numaggs_restart++;
885 }
886 }
887
888
890
891
894 }
895
896
897
898
899
900
902
903
904
905
906
907 if (agg_winobj->markptr >= 0)
909
910
911
912
913
914
915
916
917
918
919
920 if (numaggs_restart > 0)
922 for (i = 0; i < numaggs; i++)
923 {
924 peraggstate = &winstate->peragg[i];
925
926
928 numaggs_restart == 0 ||
930
931 if (peraggstate->restart)
932 {
933 wfuncno = peraggstate->wfuncno;
935 &winstate->perfunc[wfuncno],
936 peraggstate);
937 }
939 {
944 }
945 }
946
947
948
949
950
951
952
953
954
955
956
957 aggregatedupto_nonrestarted = winstate->aggregatedupto;
958 if (numaggs_restart > 0 &&
960 {
963 }
964
965
966
967
968
969
970
971
972 for (;;)
973 {
974 int ret;
975
976
978 {
980 agg_row_slot))
981 break;
982 }
983
984
985
986
987
989 agg_row_slot, false);
990 if (ret < 0)
991 break;
992 if (ret == 0)
993 goto next_tuple;
994
995
997
998
999 for (i = 0; i < numaggs; i++)
1000 {
1001 peraggstate = &winstate->peragg[i];
1002
1003
1004 if (!peraggstate->restart &&
1005 winstate->aggregatedupto < aggregatedupto_nonrestarted)
1006 continue;
1007
1008 wfuncno = peraggstate->wfuncno;
1010 &winstate->perfunc[wfuncno],
1011 peraggstate);
1012 }
1013
1014next_tuple:
1015
1017
1018
1021 }
1022
1023
1024 Assert(aggregatedupto_nonrestarted <= winstate->aggregatedupto);
1025
1026
1027
1028
1029 for (i = 0; i < numaggs; i++)
1030 {
1032 bool *isnull;
1033
1034 peraggstate = &winstate->peragg[i];
1035 wfuncno = peraggstate->wfuncno;
1039 &winstate->perfunc[wfuncno],
1040 peraggstate,
1041 result, isnull);
1042
1043
1044
1045
1046
1047
1048
1049
1051 {
1058 }
1059 else
1060 {
1062 }
1064 }
1065}
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076static void
1078 Datum *result, bool *isnull)
1079{
1082
1084
1085
1086
1087
1088
1089
1090
1094 (Node *) perfuncstate->winobj, NULL);
1095
1096 for (int argno = 0; argno < perfuncstate->numArguments; argno++)
1097 fcinfo->args[argno].isnull = true;
1098
1100
1102 *isnull = fcinfo->isnull;
1103
1104
1105
1106
1107
1108
1109
1110
1111 if (!perfuncstate->resulttypeByVal && !fcinfo->isnull &&
1116
1118}
1119
1120
1121
1122
1123
1124
1125
1126
1127
1130{
1133 int numfuncs = winstate->numfuncs;
1134
1135
1137
1138
1140
1141
1142
1143
1144
1145
1146 winstate->current_ptr = 0;
1147
1148
1150
1151
1152 if (winstate->numaggs > 0)
1153 {
1155 int readptr_flags = 0;
1156
1157
1158
1159
1160
1163 {
1164
1166
1168 }
1169
1171 readptr_flags);
1172 }
1173
1174
1175 for (int i = 0; i < numfuncs; i++)
1176 {
1178
1180 {
1182
1184 0);
1187 }
1188 }
1189
1190
1191
1192
1193
1194
1195
1196
1197
1199
1201 {
1212 }
1213
1214
1215
1216
1217
1218
1219
1220
1222
1226 {
1229 }
1230}
1231
1232
1233
1234
1235
1236static void
1238{
1240 int numfuncs = winstate->numfuncs;
1241
1254 winstate->grouptailpos = -1;
1260
1261
1262
1263
1264
1266 {
1268
1271 else
1272 {
1273
1276 return;
1277 }
1278 }
1279
1280
1283
1285
1286 if (winstate->numaggs > 0)
1287 {
1289
1290
1291 agg_winobj->markpos = -1;
1292 agg_winobj->seekpos = -1;
1293
1294
1297 }
1298
1299
1300 for (int i = 0; i < numfuncs; i++)
1301 {
1303
1305 {
1307
1310
1311
1314 {
1316
1317 for (int j = 0; j < numargs; j++)
1318 {
1320
1321 if (n > 0)
1324 }
1325 }
1326 }
1327 }
1328
1329
1330
1331
1332
1335}
1336
1337
1338
1339
1340
1341static void
1343{
1348
1350 return;
1352 return;
1353
1354
1355
1356
1357
1358
1359
1361 {
1364
1365 pos = -1;
1366 }
1367
1368
1369
1370
1371
1372
1373
1374
1375
1377 pos = -1;
1378
1380
1381
1383
1384 while (winstate->spooled_rows <= pos || pos == -1)
1385 {
1388 {
1389
1392 break;
1393 }
1394
1396 {
1398
1401
1402
1404 {
1405
1406
1407
1411 break;
1412 }
1413 }
1414
1415
1416
1417
1418
1420 {
1421
1424 }
1425 }
1426
1428}
1429
1430
1431
1432
1433
1434
1435static void
1437{
1438 int i;
1439
1440 for (i = 0; i < winstate->numfuncs; i++)
1441 {
1443
1444
1445 if (perfuncstate->winobj)
1447 }
1448
1449
1450
1451
1452
1453
1454
1457 for (i = 0; i < winstate->numaggs; i++)
1458 {
1461 }
1462
1463 if (winstate->buffer)
1467}
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485static int
1487 bool fetch_tuple)
1488{
1491
1492 Assert(pos >= 0);
1493
1494
1495
1496
1497
1499 if (pos < winstate->frameheadpos)
1500 return 0;
1501
1502
1503
1504
1505
1506
1508 {
1510 {
1511
1513 return -1;
1514 }
1516 {
1517
1519 {
1520 if (fetch_tuple)
1522 return -1;
1524 return -1;
1525 }
1526 }
1527 else
1529 }
1531 {
1533 {
1535
1536
1538 offset = -offset;
1539
1540 if (pos > winstate->currentpos + offset)
1541 return -1;
1542 }
1544 {
1545
1548 return -1;
1549 }
1550 else
1552 }
1553
1554
1556 {
1558 return 0;
1559 }
1563 {
1565
1566
1568 return 0;
1569
1571 {
1573 if (pos < winstate->grouptailpos)
1574 return 0;
1575 }
1576 }
1577
1578
1579 return 1;
1580}
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592static void
1594{
1598
1600 return;
1601
1602
1604
1606 {
1607
1610 }
1612 {
1614 {
1615
1618 }
1620 {
1621
1623 {
1627 return;
1628 }
1629
1630
1631
1632
1633
1634
1635
1636
1641 {
1642
1645 elog(ERROR, "unexpected end of tuplestore");
1646 }
1647
1649 {
1652 break;
1653
1658 break;
1659 }
1661 }
1662 else
1664 }
1666 {
1668 {
1669
1671
1673 offset = -offset;
1674
1676
1680 {
1681
1685 }
1687 }
1689 {
1690
1691
1692
1693
1694
1695
1696
1697
1698 int sortCol = node->ordColIdx[0];
1699 bool sub,
1700 less;
1701
1702
1704
1705
1707 sub = true;
1708 else
1709 sub = false;
1710 less = false;
1711
1713 {
1714 sub = !sub;
1715 less = true;
1716 }
1717
1722 {
1723
1726 elog(ERROR, "unexpected end of tuplestore");
1727 }
1728
1730 {
1732 currval;
1733 bool headisnull,
1734 currisnull;
1735
1737 &headisnull);
1739 &currisnull);
1740 if (headisnull || currisnull)
1741 {
1742
1744 {
1745
1746 if (!headisnull || currisnull)
1747 break;
1748 }
1749 else
1750 {
1751
1752 if (headisnull || !currisnull)
1753 break;
1754 }
1755 }
1756 else
1757 {
1760 headval,
1761 currval,
1765 break;
1766 }
1767
1772 break;
1773 }
1775 }
1777 {
1778
1779
1780
1781
1782
1783
1784
1785
1787 int64 minheadgroup;
1788
1790 minheadgroup = winstate->currentgroup - offset;
1791 else
1792 minheadgroup = winstate->currentgroup + offset;
1793
1798 {
1799
1802 elog(ERROR, "unexpected end of tuplestore");
1803 }
1804
1806 {
1808 break;
1810
1815 break;
1819 }
1822 }
1823 else
1825 }
1826 else
1828
1830}
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842static void
1844{
1848
1850 return;
1851
1852
1854
1856 {
1857
1861 }
1863 {
1865 {
1866
1869 }
1871 {
1872
1874 {
1879 return;
1880 }
1881
1882
1883
1884
1885
1886
1887
1888
1889
1894 {
1895
1898 elog(ERROR, "unexpected end of tuplestore");
1899 }
1900
1902 {
1906 break;
1907
1912 break;
1913 }
1915 }
1916 else
1918 }
1920 {
1922 {
1923
1925
1927 offset = -offset;
1928
1930
1934 {
1935
1939 }
1941 }
1943 {
1944
1945
1946
1947
1948
1949
1950
1951
1952 int sortCol = node->ordColIdx[0];
1953 bool sub,
1954 less;
1955
1956
1958
1959
1961 sub = true;
1962 else
1963 sub = false;
1964 less = true;
1965
1967 {
1968 sub = !sub;
1969 less = false;
1970 }
1971
1976 {
1977
1980 elog(ERROR, "unexpected end of tuplestore");
1981 }
1982
1984 {
1986 currval;
1987 bool tailisnull,
1988 currisnull;
1989
1991 &tailisnull);
1993 &currisnull);
1994 if (tailisnull || currisnull)
1995 {
1996
1998 {
1999
2000 if (!tailisnull)
2001 break;
2002 }
2003 else
2004 {
2005
2006 if (!currisnull)
2007 break;
2008 }
2009 }
2010 else
2011 {
2014 tailval,
2015 currval,
2019 break;
2020 }
2021
2026 break;
2027 }
2029 }
2031 {
2032
2033
2034
2035
2036
2037
2038
2039
2041 int64 maxtailgroup;
2042
2044 maxtailgroup = winstate->currentgroup - offset;
2045 else
2046 maxtailgroup = winstate->currentgroup + offset;
2047
2052 {
2053
2056 elog(ERROR, "unexpected end of tuplestore");
2057 }
2058
2060 {
2062 break;
2064
2069 break;
2073 }
2076 }
2077 else
2079 }
2080 else
2082
2084}
2085
2086
2087
2088
2089
2090
2091
2092static void
2094{
2097
2099 return;
2100
2101
2103
2104
2106 {
2111 return;
2112 }
2113
2114
2115
2116
2117
2118
2119
2120
2124 for (;;)
2125 {
2126
2131 break;
2135 break;
2136 }
2139
2141}
2142
2143
2144
2145
2146
2147
2150{
2155 bool isnull;
2157 bool byval;
2158
2159
2161
2163
2165 {
2168 econtext,
2169 &isnull);
2170 if (isnull)
2172 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2173 errmsg("frame starting offset must not be null")));
2174
2177 &byval);
2180 {
2181
2183
2184 if (offset < 0)
2186 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2187 errmsg("frame starting offset must not be negative")));
2188 }
2189 }
2190
2192 {
2195 econtext,
2196 &isnull);
2197 if (isnull)
2199 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2200 errmsg("frame ending offset must not be null")));
2201
2204 &byval);
2207 {
2208
2210
2211 if (offset < 0)
2213 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2214 errmsg("frame ending offset must not be negative")));
2215 }
2216 }
2218}
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2231{
2235 int i;
2236 int numfuncs;
2237
2239
2241 return NULL;
2242
2243
2244
2245
2246
2247
2250
2251
2252 for (;;)
2253 {
2255 {
2256
2258
2259 }
2260 else
2261 {
2262
2264
2267
2268 }
2269
2270
2271
2272
2273
2275
2276
2279 {
2281
2283 {
2286
2287
2289 }
2290 else
2291 {
2292
2294 return NULL;
2295 }
2296 }
2297
2298
2300
2301
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2324 {
2328 elog(ERROR, "unexpected end of tuplestore");
2331 {
2335 }
2337 }
2338 else
2339 {
2342 elog(ERROR, "unexpected end of tuplestore");
2343 }
2344
2345
2347 {
2348
2349
2350
2351 numfuncs = winstate->numfuncs;
2352 for (i = 0; i < numfuncs; i++)
2353 {
2355
2357 continue;
2361 }
2362
2363
2364
2365
2366 if (winstate->numaggs > 0)
2368 }
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2386
2387
2388
2389
2391
2392
2393
2394
2395
2396
2398
2400
2402 {
2404
2405
2406
2407
2408
2410 {
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2422 {
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433 numfuncs = winstate->numfuncs;
2434 for (i = 0; i < numfuncs; i++)
2435 {
2438 }
2439
2440
2441
2442
2443
2444
2445
2447 {
2449 continue;
2450 }
2451 else
2452 {
2454 }
2455 }
2456 else
2457 {
2458
2459
2460
2461
2463 return NULL;
2464 }
2465 }
2466
2467
2468
2469
2471 {
2473 continue;
2474 }
2475
2476 break;
2477 }
2478
2479
2480
2481
2482
2484 break;
2485 }
2486
2487 return slot;
2488}
2489
2490
2491
2492
2493
2494
2495
2496
2499{
2507 int numfuncs,
2508 wfuncno,
2509 numaggs,
2510 aggno;
2513
2514
2516
2517
2518
2519
2524
2525
2527
2528
2529
2530
2531
2532
2537
2538
2541 "WindowAgg Partition",
2543
2544
2545
2546
2547
2548
2549
2552 "WindowAgg Aggregates",
2554
2555
2557
2558
2561
2562
2563
2564
2565
2566
2567
2568
2571
2572
2573
2574
2575
2576
2578
2579
2581
2582
2583
2584
2587
2588
2589
2590
2591
2594
2595
2599
2600
2601
2602
2611
2612
2613
2614
2615
2616
2618
2620 {
2631 }
2632
2633
2634
2635
2638
2639
2644 node->partColIdx,
2645 node->partOperators,
2646 node->partCollations,
2648
2653 node->ordColIdx,
2654 node->ordOperators,
2655 node->ordCollations,
2657
2658
2659
2660
2661 numfuncs = winstate->numfuncs;
2662 numaggs = winstate->numaggs;
2666
2667
2668
2669
2672 winstate->perfunc = perfunc;
2673 winstate->peragg = peragg;
2674
2675 wfuncno = -1;
2676 aggno = -1;
2677 foreach(l, winstate->funcs)
2678 {
2683 int i;
2684
2685 if (wfunc->winref != node->winref)
2686 elog(ERROR, "WindowFunc with winref %u assigned to WindowAgg with winref %u",
2688
2689
2690
2691
2692
2693 for (i = 0; i <= wfuncno; i++)
2694 {
2695 if (equal(wfunc, perfunc[i].wfunc) &&
2697 break;
2698 }
2699 if (i <= wfuncno && wfunc->ignore_nulls == perfunc[i].ignore_nulls)
2700 {
2701
2703 continue;
2704 }
2705
2706
2707 perfuncstate = &perfunc[++wfuncno];
2708
2709
2710 wfuncstate->wfuncno = wfuncno;
2711
2712
2719
2720
2721 perfuncstate->wfuncstate = wfuncstate;
2722 perfuncstate->wfunc = wfunc;
2724 perfuncstate->winCollation = wfunc->inputcollid;
2725
2729
2730
2731
2732
2733
2734 perfuncstate->plain_agg = wfunc->winagg;
2735 if (wfunc->winagg)
2736 {
2738
2739 perfuncstate->aggno = ++aggno;
2740 peraggstate = &winstate->peragg[aggno];
2742 peraggstate->wfuncno = wfuncno;
2743 }
2744 else
2745 {
2747
2748 winobj->winstate = winstate;
2751 perfuncstate->winobj = winobj;
2754
2755
2759 }
2760 }
2761
2762
2763 winstate->numfuncs = wfuncno + 1;
2764 winstate->numaggs = aggno + 1;
2765
2766
2767 if (winstate->numaggs > 0)
2768 {
2770
2771 agg_winobj->winstate = winstate;
2773 agg_winobj->localmem = NULL;
2774
2775 agg_winobj->markptr = -1;
2776 agg_winobj->readptr = -1;
2778 }
2779
2780
2782
2783
2788
2789
2797
2802
2803 return winstate;
2804}
2805
2806
2807
2808
2809
2810void
2812{
2814 int i;
2815
2816 if (node->buffer != NULL)
2817 {
2819
2820
2821 node->buffer = NULL;
2822 }
2823
2825
2827 {
2830 }
2833
2836
2839}
2840
2841
2842
2843
2844
2845void
2847{
2850
2853
2854
2856
2857
2867
2868
2871
2872
2873
2874
2875
2876 if (outerPlan->chgParam == NULL)
2878}
2879
2880
2881
2882
2883
2884
2888{
2890 int numArguments;
2893 Oid aggtranstype;
2896 bool use_ma_code;
2897 Oid transfn_oid,
2898 invtransfn_oid,
2899 finalfn_oid;
2900 bool finalextra;
2901 char finalmodify;
2902 Expr *transfnexpr,
2903 *invtransfnexpr,
2904 *finalfnexpr;
2905 Datum textInitVal;
2906 int i;
2908
2910
2911 i = 0;
2912 foreach(lc, wfunc->args)
2913 {
2915 }
2916
2919 elog(ERROR, "cache lookup failed for aggregate %u",
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941 if ((aggform->aggminvtransfn))
2942 use_ma_code = false;
2943 else if (aggform->aggmfinalmodify == AGGMODIFY_READ_ONLY &&
2944 aggform->aggfinalmodify != AGGMODIFY_READ_ONLY)
2945 use_ma_code = true;
2947 use_ma_code = false;
2949 use_ma_code = false;
2951 use_ma_code = false;
2952 else
2953 use_ma_code = true;
2954 if (use_ma_code)
2955 {
2956 peraggstate->transfn_oid = transfn_oid = aggform->aggmtransfn;
2957 peraggstate->invtransfn_oid = invtransfn_oid = aggform->aggminvtransfn;
2958 peraggstate->finalfn_oid = finalfn_oid = aggform->aggmfinalfn;
2959 finalextra = aggform->aggmfinalextra;
2960 finalmodify = aggform->aggmfinalmodify;
2961 aggtranstype = aggform->aggmtranstype;
2962 initvalAttNo = Anum_pg_aggregate_aggminitval;
2963 }
2964 else
2965 {
2966 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
2968 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
2969 finalextra = aggform->aggfinalextra;
2970 finalmodify = aggform->aggfinalmodify;
2971 aggtranstype = aggform->aggtranstype;
2972 initvalAttNo = Anum_pg_aggregate_agginitval;
2973 }
2974
2975
2976
2977
2978
2979
2980
2981 {
2983 Oid aggOwner;
2984
2988 elog(ERROR, "cache lookup failed for function %u",
2992
2993 aclresult = object_aclcheck(ProcedureRelationId, transfn_oid, aggOwner,
2999
3001 {
3002 aclresult = object_aclcheck(ProcedureRelationId, invtransfn_oid, aggOwner,
3008 }
3009
3011 {
3012 aclresult = object_aclcheck(ProcedureRelationId, finalfn_oid, aggOwner,
3018 }
3019 }
3020
3021
3022
3023
3024
3025
3026 if (finalmodify != AGGMODIFY_READ_ONLY)
3028 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3029 errmsg("aggregate function %s does not support use as a window function",
3031
3032
3033 if (finalextra)
3034 peraggstate->numFinalArgs = numArguments + 1;
3035 else
3037
3038
3040 aggtranstype,
3041 inputTypes,
3042 numArguments);
3043
3044
3046 numArguments,
3047 0,
3048 false,
3049 aggtranstype,
3050 wfunc->inputcollid,
3051 transfn_oid,
3052 invtransfn_oid,
3053 &transfnexpr,
3054 &invtransfnexpr);
3055
3056
3059
3061 {
3064 }
3065
3067 {
3070 aggtranstype,
3071 wfunc->wintype,
3072 wfunc->inputcollid,
3073 finalfn_oid,
3074 &finalfnexpr);
3077 }
3078
3079
3086
3087
3088
3089
3090
3091 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple, initvalAttNo,
3093
3096 else
3098 aggtranstype);
3099
3100
3101
3102
3103
3104
3105
3106
3108 {
3109 if (numArguments < 1 ||
3112 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3113 errmsg("aggregate %u needs to have compatible input type and transition type",
3115 }
3116
3117
3118
3119
3120
3121
3122
3123
3124
3128 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3129 errmsg("strictness of aggregate's forward and inverse transition functions must match")));
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3148 "WindowAgg Per Aggregate",
3150 else
3152
3154
3155 return peraggstate;
3156}
3157
3160{
3161 Oid typinput,
3162 typioparam;
3163 char *strInitVal;
3165
3169 typioparam, -1);
3170 pfree(strInitVal);
3171 return initVal;
3172}
3173
3174
3175
3176
3177
3178
3179
3180static bool
3183{
3186
3187
3189 return true;
3190
3191 econtext->ecxt_outertuple = slot1;
3192 econtext->ecxt_innertuple = slot2;
3194}
3195
3196
3197
3198
3199
3200
3201
3202
3203static bool
3205{
3208
3209
3211
3212
3213 if (pos < 0)
3214 return false;
3215
3216
3218
3220 return false;
3221
3222 if (pos < winobj->markpos)
3223 elog(ERROR, "cannot fetch row before WindowObject's mark position");
3224
3226
3228
3229
3230
3231
3232 if (winobj->seekpos < pos - 1)
3233 {
3235 pos - 1 - winobj->seekpos,
3236 true))
3237 elog(ERROR, "unexpected end of tuplestore");
3238 winobj->seekpos = pos - 1;
3239 }
3240 else if (winobj->seekpos > pos + 1)
3241 {
3243 winobj->seekpos - (pos + 1),
3244 false))
3245 elog(ERROR, "unexpected end of tuplestore");
3246 winobj->seekpos = pos + 1;
3247 }
3248 else if (winobj->seekpos == pos)
3249 {
3250
3251
3252
3253
3254
3255
3256
3259 }
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269 if (winobj->seekpos > pos)
3270 {
3272 elog(ERROR, "unexpected end of tuplestore");
3274 }
3275 else
3276 {
3278 elog(ERROR, "unexpected end of tuplestore");
3280 }
3281
3283
3285
3286 return true;
3287}
3288
3289
3290
3291
3292
3295 int64 abs_pos, bool *isnull, bool *isout)
3296{
3300
3301 winstate = winobj->winstate;
3304 {
3305
3306 if (isout)
3307 *isout = true;
3308 *isnull = true;
3309 return (Datum) 0;
3310 }
3311
3312 if (isout)
3313 *isout = false;
3318 econtext, isnull);
3319}
3320
3321
3322
3323
3324
3325
3328 int relpos, int seektype, bool set_mark,
3329 bool *isnull, bool *isout)
3330{
3337 int notnull_offset;
3338 int notnull_relpos;
3339 int forward;
3340
3342 winstate = winobj->winstate;
3345 datum = (Datum) 0;
3346 notnull_offset = 0;
3347 notnull_relpos = abs(relpos);
3348
3349 switch (seektype)
3350 {
3352 elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame");
3353 abs_pos = mark_pos = 0;
3354 break;
3356
3357 if (relpos < 0)
3358 goto out_of_frame;
3362 forward = 1;
3363 break;
3365
3366 if (relpos > 0)
3367 goto out_of_frame;
3370 mark_pos = 0;
3371 forward = -1;
3372 break;
3373 default:
3374 elog(ERROR, "unrecognized window seek type: %d", seektype);
3375 abs_pos = mark_pos = 0;
3376 break;
3377 }
3378
3379
3380
3381
3382
3383 do
3384 {
3385 int inframe;
3386 int v;
3387
3388
3389
3390
3391
3392
3393 if (abs_pos < 0)
3394 goto out_of_frame;
3395
3396
3398 if (inframe == -1)
3399 goto out_of_frame;
3400 else if (inframe == 0)
3401 goto advance;
3402
3403 if (isout)
3404 *isout = false;
3405
3407 if (v == NN_NULL)
3408 goto advance;
3409
3410 else if (v == NN_UNKNOWN)
3411 {
3413 goto out_of_frame;
3414
3418 argno), econtext,
3419 isnull);
3420 if (!*isnull)
3421 notnull_offset++;
3422
3423
3425 }
3426 else
3427 {
3428 notnull_offset++;
3429 if (notnull_offset > notnull_relpos)
3430 {
3431
3433 goto out_of_frame;
3434
3439 econtext, isnull);
3440 }
3441 }
3442advance:
3443 abs_pos += forward;
3444 } while (notnull_offset <= notnull_relpos);
3445
3446 if (set_mark)
3448
3449 return datum;
3450
3451out_of_frame:
3452 if (isout)
3453 *isout = true;
3454 *isnull = true;
3455 return (Datum) 0;
3456}
3457
3458
3459
3460
3461
3462
3463static void
3465{
3467
3469 {
3472 }
3473}
3474
3475
3476
3477
3478
3479
3480
3481static void
3483{
3484
3485#define INIT_NOT_NULL_INFO_NUM 128
3486
3488 {
3489
3492
3493 for (;;)
3494 {
3497 Size newsize;
3498
3499 if (oldsize == 0)
3500
3501 {
3504 }
3505 else
3506 {
3507 newsize = oldsize * 2;
3510 }
3513 break;
3514 }
3516 }
3517}
3518
3519
3520
3521
3522
3523
3524
3527{
3531
3535 mb = mbp[bpos];
3537}
3538
3539
3540
3541
3542
3543
3544
3545
3546static void
3548{
3553 int shift;
3554
3558 mb = mbp[bpos];
3560 mb &= ~(NN_MASK << shift);
3561 mb |= (val << shift);
3562 mbp[bpos] = mb;
3563}
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577void
3579 bool allowNullTreatment,
3581{
3584 {
3586
3588 elog(ERROR, "could not get function name");
3590 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3591 errmsg("function %s does not allow RESPECT/IGNORE NULLS",
3593 }
3596}
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610void *
3612{
3614 if (winobj->localmem == NULL)
3618}
3619
3620
3621
3622
3623
3624
3627{
3630}
3631
3632
3633
3634
3635
3636
3637
3638
3639
3642{
3646}
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658void
3660{
3662
3664 winstate = winobj->winstate;
3665
3666 if (markpos < winobj->markpos)
3667 elog(ERROR, "cannot move WindowObject's mark position backward");
3669 if (markpos > winobj->markpos)
3670 {
3672 markpos - winobj->markpos,
3673 true);
3674 winobj->markpos = markpos;
3675 }
3677 if (markpos > winobj->seekpos)
3678 {
3680 markpos - winobj->seekpos,
3681 true);
3682 winobj->seekpos = markpos;
3683 }
3684}
3685
3686
3687
3688
3689
3690
3691
3692
3693bool
3695{
3700 bool res;
3701
3703 winstate = winobj->winstate;
3705
3706
3708 return true;
3709
3710
3711
3712
3713
3716
3719 pos1);
3722 pos2);
3723
3724 res = are_peers(winstate, slot1, slot2);
3725
3728
3729 return res;
3730}
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3752 int relpos, int seektype, bool set_mark,
3753 bool *isnull, bool *isout)
3754{
3759 bool null_treatment;
3760 int notnull_offset;
3761 int notnull_relpos;
3762 int forward;
3763 bool myisout;
3764
3766 winstate = winobj->winstate;
3767
3769
3770 switch (seektype)
3771 {
3773 if (null_treatment)
3775 else
3776 abs_pos = winstate->currentpos + relpos;
3777 break;
3779 if (null_treatment)
3780 abs_pos = 0;
3781 else
3782 abs_pos = relpos;
3783 break;
3786 abs_pos = winstate->spooled_rows - 1 + relpos;
3787 break;
3788 default:
3789 elog(ERROR, "unrecognized window seek type: %d", seektype);
3790 abs_pos = 0;
3791 break;
3792 }
3793
3794
3795 if (!null_treatment)
3796 {
3797
3799 abs_pos, isnull, &myisout);
3800 if (!myisout && set_mark)
3802 if (isout)
3803 *isout = myisout;
3804 return datum;
3805 }
3806
3807
3808 notnull_offset = 0;
3809 notnull_relpos = abs(relpos);
3810 forward = relpos > 0 ? 1 : -1;
3811 myisout = false;
3812 datum = 0;
3813
3814
3815
3816
3817
3818
3819
3820
3821
3824 else
3825 {
3826
3827
3828
3829
3830
3831 mark_pos = 0;
3832 }
3833
3834
3835
3836
3837
3838
3839 do
3840 {
3841 int nn_info;
3842
3843 abs_pos += forward;
3844 if (abs_pos < 0)
3845 break;
3846
3847
3849 if (nn_info == NN_NOTNULL)
3850 notnull_offset++;
3851 else if (nn_info == NN_NULL)
3852 continue;
3853 else
3854 {
3855
3856
3857
3858
3859
3860
3861
3863 abs_pos, isnull, &myisout);
3864 if (myisout)
3865 break;
3866 if (!*isnull)
3867 notnull_offset++;
3868
3870 }
3871 } while (notnull_offset < notnull_relpos);
3872
3873
3875 abs_pos, isnull, &myisout);
3876 if (!myisout && set_mark)
3878 if (isout)
3879 *isout = myisout;
3880
3881 return datum;
3882}
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3919 int relpos, int seektype, bool set_mark,
3920 bool *isnull, bool *isout)
3921{
3927
3929 winstate = winobj->winstate;
3932
3935 set_mark, isnull, isout);
3936
3937 switch (seektype)
3938 {
3940 elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame");
3941 abs_pos = mark_pos = 0;
3942 break;
3944
3945 if (relpos < 0)
3946 goto out_of_frame;
3949 mark_pos = abs_pos;
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3964 {
3965 case 0:
3966
3967 break;
3969 if (abs_pos >= winstate->currentpos &&
3971 abs_pos++;
3972 break;
3977 {
3980
3981 abs_pos += winstate->grouptailpos - overlapstart;
3982 }
3983 break;
3988 {
3991
3992 if (abs_pos == overlapstart)
3994 else
3995 abs_pos += winstate->grouptailpos - overlapstart - 1;
3996 }
3997 break;
3998 default:
3999 elog(ERROR, "unrecognized frame option state: 0x%x",
4001 break;
4002 }
4003 break;
4005
4006 if (relpos > 0)
4007 goto out_of_frame;
4009 abs_pos = winstate->frametailpos - 1 + relpos;
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4021 {
4022 case 0:
4023
4024 mark_pos = abs_pos;
4025 break;
4027 if (abs_pos <= winstate->currentpos &&
4029 abs_pos--;
4031 if (abs_pos < winstate->frameheadpos)
4032 goto out_of_frame;
4034 break;
4037 if (abs_pos < winstate->grouptailpos &&
4039 {
4042
4043 abs_pos -= overlapend - winstate->groupheadpos;
4044 }
4046 if (abs_pos < winstate->frameheadpos)
4047 goto out_of_frame;
4049 break;
4052 if (abs_pos < winstate->grouptailpos &&
4054 {
4057
4058 if (abs_pos == overlapend - 1)
4060 else
4061 abs_pos -= overlapend - 1 - winstate->groupheadpos;
4062 }
4064 if (abs_pos < winstate->frameheadpos)
4065 goto out_of_frame;
4067 break;
4068 default:
4069 elog(ERROR, "unrecognized frame option state: 0x%x",
4071 mark_pos = 0;
4072 break;
4073 }
4074 break;
4075 default:
4076 elog(ERROR, "unrecognized window seek type: %d", seektype);
4077 abs_pos = mark_pos = 0;
4078 break;
4079 }
4080
4082 goto out_of_frame;
4083
4084
4086 goto out_of_frame;
4087
4088 if (isout)
4089 *isout = false;
4090 if (set_mark)
4094 econtext, isnull);
4095
4096out_of_frame:
4097 if (isout)
4098 *isout = true;
4099 *isnull = true;
4100 return (Datum) 0;
4101}
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4118{
4121
4123 winstate = winobj->winstate;
4124
4126
4129 econtext, isnull);
4130}
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)
#define InstrCountFiltered1(node, delta)
#define outerPlanState(node)
@ WINDOWAGG_PASSTHROUGH_STRICT
#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)
#define palloc0_array(type, count)
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 * repalloc0(void *pointer, Size oldsize, Size size)
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 grow_notnull_info(WindowObject winobj, int64 pos, int argno)
#define INIT_NOT_NULL_INFO_NUM
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 void init_notnull_info(WindowObject winobj, WindowStatePerFunc perfuncstate)
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)
void ExecEndWindowAgg(WindowAggState *node)
static void eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, Datum *result, bool *isnull)
struct WindowStatePerFuncData WindowStatePerFuncData
static void put_notnull_info(WindowObject winobj, int64 pos, int argno, bool isnull)
static Datum ignorenulls_getfuncarginframe(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
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)
#define NN_BYTES_TO_POS(bytes)
void WinSetMarkPosition(WindowObject winobj, int64 markpos)
static void eval_windowaggregates(WindowAggState *winstate)
static uint8 get_notnull_info(WindowObject winobj, int64 pos, int argno)
#define NN_POS_TO_BYTES(pos)
static int row_is_in_frame(WindowObject winobj, int64 pos, TupleTableSlot *slot, bool fetch_tuple)
static void release_partition(WindowAggState *winstate)
static Datum gettuple_eval_partition(WindowObject winobj, int argno, int64 abs_pos, bool *isnull, bool *isout)
static void update_frametailpos(WindowAggState *winstate)
static void update_frameheadpos(WindowAggState *winstate)
static void initialize_windowaggregate(WindowAggState *winstate, WindowStatePerFunc perfuncstate, WindowStatePerAgg peraggstate)
void WinCheckAndInitializeNullTreatment(WindowObject winobj, bool allowNullTreatment, FunctionCallInfo fcinfo)
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)
#define PARSER_IGNORE_NULLS
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