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{
73
74
75
76
77
79{
80
83
85
87
89
90
91
92
93
96
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
148
149
151
152
155
157
158
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,
2581
2586 node->ordColIdx,
2587 node->ordOperators,
2588 node->ordCollations,
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 ((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