src/backend/executor/nodeWindowAgg.c - Coverage Report

← Back to Overview

# src/backend/executor/nodeWindowAgg.c

Coverage: 441/471 lines (93.6%)
Total Lines
471
modified
Covered
441
93.6%
Uncovered
30
6.4%
Keyboard navigation
eval_windowaggregates() lines 732-1134
Modified Lines Coverage: 14/14 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
732 | - | eval_windowaggregates(WindowAggState *winstate) | -
733 | - | { | -
734 | - | WindowStatePerAgg peraggstate; | -
735 | - | int wfuncno, | -
736 | - | numaggs, | -
737 | - | numaggs_restart, | -
738 | - | i; | -
739 | - | int64 aggregatedupto_nonrestarted; | -
740 | - | MemoryContext oldContext; | -
741 | - | ExprContext *econtext; | -
742 | - | WindowObject agg_winobj; | -
743 | - | TupleTableSlot *agg_row_slot; | -
744 | - | TupleTableSlot *temp_slot; | -
745 | - |  | -
746 | - | numaggs = winstate->numaggs; | -
747 | - | if (numaggs == 0) | -
748 | - | return; /* nothing to do */ | -
749 | - |  | -
750 | - | /* final output execution is in ps_ExprContext */ | -
751 | - | econtext = winstate->ss.ps.ps_ExprContext; | -
752 | - | agg_winobj = winstate->agg_winobj; | -
753 | - | agg_row_slot = winstate->agg_row_slot; | -
754 | - | temp_slot = winstate->temp_slot_1; | -
755 | - |  | -
756 | - | /* | -
757 | - | * If the window's frame start clause is UNBOUNDED_PRECEDING and no | -
758 | - | * exclusion clause is specified, then the window frame consists of a | -
759 | - | * contiguous group of rows extending forward from the start of the | -
760 | - | * partition, and rows only enter the frame, never exit it, as the current | -
761 | - | * row advances forward. This makes it possible to use an incremental | -
762 | - | * strategy for evaluating aggregates: we run the transition function for | -
763 | - | * each row added to the frame, and run the final function whenever we | -
764 | - | * need the current aggregate value. This is considerably more efficient | -
765 | - | * than the naive approach of re-running the entire aggregate calculation | -
766 | - | * for each current row. It does assume that the final function doesn't | -
767 | - | * damage the running transition value, but we have the same assumption in | -
768 | - | * nodeAgg.c too (when it rescans an existing hash table). | -
769 | - | * | -
770 | - | * If the frame start does sometimes move, we can still optimize as above | -
771 | - | * whenever successive rows share the same frame head, but if the frame | -
772 | - | * head moves beyond the previous head we try to remove those rows using | -
773 | - | * the aggregate's inverse transition function. This function restores | -
774 | - | * the aggregate's current state to what it would be if the removed row | -
775 | - | * had never been aggregated in the first place. Inverse transition | -
776 | - | * functions may optionally return NULL, indicating that the function was | -
777 | - | * unable to remove the tuple from aggregation. If this happens, or if | -
778 | - | * the aggregate doesn't have an inverse transition function at all, we | -
779 | - | * must perform the aggregation all over again for all tuples within the | -
780 | - | * new frame boundaries. | -
781 | - | * | -
782 | - | * If there's any exclusion clause, then we may have to aggregate over a | -
783 | - | * non-contiguous set of rows, so we punt and recalculate for every row. | -
784 | - | * (For some frame end choices, it might be that the frame is always | -
785 | - | * contiguous anyway, but that's an optimization to investigate later.) | -
786 | - | * | -
787 | - | * In many common cases, multiple rows share the same frame and hence the | -
788 | - | * same aggregate value. (In particular, if there's no ORDER BY in a RANGE | -
789 | - | * window, then all rows are peers and so they all have window frame equal | -
790 | - | * to the whole partition.) We optimize such cases by calculating the | -
791 | - | * aggregate value once when we reach the first row of a peer group, and | -
792 | - | * then returning the saved value for all subsequent rows. | -
793 | - | * | -
794 | - | * 'aggregatedupto' keeps track of the first row that has not yet been | -
795 | - | * accumulated into the aggregate transition values. Whenever we start a | -
796 | - | * new peer group, we accumulate forward to the end of the peer group. | -
797 | - | */ | -
798 | - |  | -
799 | - | /* | -
800 | - | * First, update the frame head position. | -
801 | - | * | -
802 | - | * The frame head should never move backwards, and the code below wouldn't | -
803 | - | * cope if it did, so for safety we complain if it does. | -
804 | - | */ | -
805 | - | update_frameheadpos(winstate); | -
806 | - | if (winstate->frameheadpos < winstate->aggregatedbase) | -
807 | - | elog(ERROR, "window frame head moved backward"); | -
808 | - |  | -
809 | - | /* | -
810 | - | * If the frame didn't change compared to the previous row, we can re-use | -
811 | - | * the result values that were previously saved at the bottom of this | -
812 | - | * function. Since we don't know the current frame's end yet, this is not | -
813 | - | * possible to check for fully. But if the frame end mode is UNBOUNDED | -
814 | - | * FOLLOWING or CURRENT ROW, no exclusion clause is specified, and the | -
815 | - | * current row lies within the previous row's frame, then the two frames' | -
816 | - | * ends must coincide. Note that on the first row aggregatedbase == | -
817 | - | * aggregatedupto, meaning this test must fail, so we don't need to check | -
818 | - | * the "there was no previous row" case explicitly here. | -
819 | - | */ | -
820 | - | if (winstate->aggregatedbase == winstate->frameheadpos && | -
821 | - | (winstate->frameOptions & (FRAMEOPTION_END_UNBOUNDED_FOLLOWING | | -
822 | - | FRAMEOPTION_END_CURRENT_ROW)) && | -
823 | - | !(winstate->frameOptions & FRAMEOPTION_EXCLUSION) && | -
824 | - | winstate->aggregatedbase <= winstate->currentpos && | -
825 | - | winstate->aggregatedupto > winstate->currentpos) | -
826 | - | { | -
827 | - | for (i = 0; i < numaggs; i++) | -
828 | - | { | -
829 | - | peraggstate = &winstate->peragg[i]; | -
830 | - | wfuncno = peraggstate->wfuncno; | -
831 | - | econtext->ecxt_aggvalues[wfuncno] = peraggstate->resultValue; | -
832 | - | econtext->ecxt_aggnulls[wfuncno] = peraggstate->resultValueIsNull; | -
833 | - | } | -
834 | - | return; | -
835 | - | } | -
836 | - |  | -
837 | - | /*---------- | -
838 | - | * Initialize restart flags. | -
839 | - | * | -
840 | - | * We restart the aggregation: | -
841 | - | * - if we're processing the first row in the partition, or | -
842 | - | * - if the frame's head moved and we cannot use an inverse | -
843 | - | * transition function, or | -
844 | - | * - we have an EXCLUSION clause, or | -
845 | - | * - if the new frame doesn't overlap the old one | -
846 | - | * - if RPR (Row Pattern Recognition) is enabled, because the reduced | 24cfb8dRow pattern recognition patch (executor and commands).
847 | - | * frame depends on pattern matching results which can differ entirely | 24cfb8dRow pattern recognition patch (executor and commands).
848 | - | * from row to row, making inverse transition optimization inapplicable | 24cfb8dRow pattern recognition patch (executor and commands).
849 | - | * | -
850 | - | * Note that we don't strictly need to restart in the last case, but if | -
851 | - | * we're going to remove all rows from the aggregation anyway, a restart | -
852 | - | * surely is faster. | -
853 | - | *---------- | -
854 | - | */ | -
855 | - | numaggs_restart = 0; | -
856 | - | for (i = 0; i < numaggs; i++) | -
857 | - | { | -
858 | - | peraggstate = &winstate->peragg[i]; | -
859 | - | if (winstate->currentpos == 0 || | -
860 | - | (winstate->aggregatedbase != winstate->frameheadpos && | -
861 | - | !OidIsValid(peraggstate->invtransfn_oid)) || | -
862 | - | (winstate->frameOptions & FRAMEOPTION_EXCLUSION) || | -
863 | 973700 | winstate->aggregatedupto <= winstate->frameheadpos || | 24cfb8dRow pattern recognition patch (executor and commands).
864 | 15848 | rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
865 | - | { | -
866 | - | peraggstate->restart = true; | -
867 | - | numaggs_restart++; | -
868 | - | } | -
869 | - | else | -
870 | - | peraggstate->restart = false; | -
871 | - | } | -
872 | - |  | -
873 | - | /* | -
874 | - | * If we have any possibly-moving aggregates, attempt to advance | -
875 | - | * aggregatedbase to match the frame's head by removing input rows that | -
876 | - | * fell off the top of the frame from the aggregations. This can fail, | -
877 | - | * i.e. advance_windowaggregate_base() can return false, in which case | -
878 | - | * we'll restart that aggregate below. | -
879 | - | */ | -
880 | - | while (numaggs_restart < numaggs && | -
881 | - | winstate->aggregatedbase < winstate->frameheadpos) | -
882 | - | { | -
883 | - | /* | -
884 | - | * Fetch the next tuple of those being removed. This should never fail | -
885 | - | * as we should have been here before. | -
886 | - | */ | -
887 | - | if (!window_gettupleslot(agg_winobj, winstate->aggregatedbase, | -
888 | - | temp_slot)) | -
889 | - | elog(ERROR, "could not re-fetch previously fetched frame row"); | -
890 | - |  | -
891 | - | /* Set tuple context for evaluation of aggregate arguments */ | -
892 | - | winstate->tmpcontext->ecxt_outertuple = temp_slot; | -
893 | - |  | -
894 | - | /* | -
895 | - | * Perform the inverse transition for each aggregate function in the | -
896 | - | * window, unless it has already been marked as needing a restart. | -
897 | - | */ | -
898 | - | for (i = 0; i < numaggs; i++) | -
899 | - | { | -
900 | - | bool ok; | -
901 | - |  | -
902 | - | peraggstate = &winstate->peragg[i]; | -
903 | - | if (peraggstate->restart) | -
904 | - | continue; | -
905 | - |  | -
906 | - | wfuncno = peraggstate->wfuncno; | -
907 | - | ok = advance_windowaggregate_base(winstate, | -
908 | - | &winstate->perfunc[wfuncno], | -
909 | - | peraggstate); | -
910 | - | if (!ok) | -
911 | - | { | -
912 | - | /* Inverse transition function has failed, must restart */ | -
913 | - | peraggstate->restart = true; | -
914 | - | numaggs_restart++; | -
915 | - | } | -
916 | - | } | -
917 | - |  | -
918 | - | /* Reset per-input-tuple context after each tuple */ | -
919 | - | ResetExprContext(winstate->tmpcontext); | -
920 | - |  | -
921 | - | /* And advance the aggregated-row state */ | -
922 | - | winstate->aggregatedbase++; | -
923 | - | ExecClearTuple(temp_slot); | -
924 | - | } | -
925 | - |  | -
926 | - | /* | -
927 | - | * If we successfully advanced the base rows of all the aggregates, | -
928 | - | * aggregatedbase now equals frameheadpos; but if we failed for any, we | -
929 | - | * must forcibly update aggregatedbase. | -
930 | - | */ | -
931 | - | winstate->aggregatedbase = winstate->frameheadpos; | -
932 | - |  | -
933 | - | /* | -
934 | - | * If we created a mark pointer for aggregates, keep it pushed up to frame | -
935 | - | * head, so that tuplestore can discard unnecessary rows. | -
936 | - | */ | -
937 | - | if (agg_winobj->markptr >= 0) | -
938 | - | WinSetMarkPosition(agg_winobj, winstate->frameheadpos); | -
939 | - |  | -
940 | - | /* | -
941 | - | * Now restart the aggregates that require it. | -
942 | - | * | -
943 | - | * We assume that aggregates using the shared context always restart if | -
944 | - | * *any* aggregate restarts, and we may thus clean up the shared | -
945 | - | * aggcontext if that is the case. Private aggcontexts are reset by | -
946 | - | * initialize_windowaggregate() if their owning aggregate restarts. If we | -
947 | - | * aren't restarting an aggregate, we need to free any previously saved | -
948 | - | * result for it, else we'll leak memory. | -
949 | - | */ | -
950 | - | if (numaggs_restart > 0) | -
951 | - | MemoryContextReset(winstate->aggcontext); | -
952 | - | for (i = 0; i < numaggs; i++) | -
953 | - | { | -
954 | - | peraggstate = &winstate->peragg[i]; | -
955 | - |  | -
956 | - | /* Aggregates using the shared ctx must restart if *any* agg does */ | -
957 | - | Assert(peraggstate->aggcontext != winstate->aggcontext || | -
958 | - | numaggs_restart == 0 || | -
959 | - | peraggstate->restart); | -
960 | - |  | -
961 | - | if (peraggstate->restart) | -
962 | - | { | -
963 | - | wfuncno = peraggstate->wfuncno; | -
964 | - | initialize_windowaggregate(winstate, | -
965 | - | &winstate->perfunc[wfuncno], | -
966 | - | peraggstate); | -
967 | - | } | -
968 | - | else if (!peraggstate->resultValueIsNull) | -
969 | - | { | -
970 | - | if (!peraggstate->resulttypeByVal) | -
971 | - | pfree(DatumGetPointer(peraggstate->resultValue)); | -
972 | - | peraggstate->resultValue = (Datum) 0; | -
973 | - | peraggstate->resultValueIsNull = true; | -
974 | - | } | -
975 | - | } | -
976 | - |  | -
977 | - | /* | -
978 | - | * Non-restarted aggregates now contain the rows between aggregatedbase | -
979 | - | * (i.e., frameheadpos) and aggregatedupto, while restarted aggregates | -
980 | - | * contain no rows. If there are any restarted aggregates, we must thus | -
981 | - | * begin aggregating anew at frameheadpos, otherwise we may simply | -
982 | - | * continue at aggregatedupto. We must remember the old value of | -
983 | - | * aggregatedupto to know how long to skip advancing non-restarted | -
984 | - | * aggregates. If we modify aggregatedupto, we must also clear | -
985 | - | * agg_row_slot, per the loop invariant below. | -
986 | - | */ | -
987 | - | aggregatedupto_nonrestarted = winstate->aggregatedupto; | -
988 | - | if (numaggs_restart > 0 && | -
989 | - | winstate->aggregatedupto != winstate->frameheadpos) | -
990 | - | { | -
991 | - | winstate->aggregatedupto = winstate->frameheadpos; | -
992 | - | ExecClearTuple(agg_row_slot); | -
993 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
994 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
995 | - | * If RPR is defined, we do not use aggregatedupto_nonrestarted. To | 24cfb8dRow pattern recognition patch (executor and commands).
996 | - | * avoid assertion failure below, we reset aggregatedupto_nonrestarted | 24cfb8dRow pattern recognition patch (executor and commands).
997 | - | * to frameheadpos. | 24cfb8dRow pattern recognition patch (executor and commands).
998 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
999 | 947530 | if (rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
1000 | 946556 | aggregatedupto_nonrestarted = winstate->frameheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
1001 | - | } | -
1002 | - |  | -
1003 | - | /* | -
1004 | - | * Advance until we reach a row not in frame (or end of partition). | -
1005 | - | * | -
1006 | - | * Note the loop invariant: agg_row_slot is either empty or holds the row | -
1007 | - | * at position aggregatedupto. We advance aggregatedupto after processing | -
1008 | - | * a row. | -
1009 | - | */ | -
1010 | - | for (;;) | -
1011 | - | { | -
1012 | 1991685 | int64 ret; | 24cfb8dRow pattern recognition patch (executor and commands).
1013 | - |  | -
1014 | - | /* Fetch next row if we didn't already */ | -
1015 | - | if (TupIsNull(agg_row_slot)) | -
1016 | - | { | -
1017 | - | if (!window_gettupleslot(agg_winobj, winstate->aggregatedupto, | -
1018 | - | agg_row_slot)) | -
1019 | - | break; /* must be end of partition */ | -
1020 | - | } | -
1021 | - |  | -
1022 | - | /* | -
1023 | - | * Exit loop if no more rows can be in frame. Skip aggregation if | -
1024 | - | * current row is not in frame but there might be more in the frame. | -
1025 | - | */ | -
1026 | - | ret = row_is_in_frame(agg_winobj, winstate->aggregatedupto, | -
1027 | - | agg_row_slot, false); | -
1028 | - | if (ret < 0) | -
1029 | - | break; | -
1030 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1031 | - | if (ret == 0) | -
1032 | - | goto next_tuple; | -
1033 | - |  | -
1034 | 1982926 | if (rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
1035 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
1036 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
1037 | - | * If currentpos is already decided but aggregatedupto is not yet | 24cfb8dRow pattern recognition patch (executor and commands).
1038 | - | * determined, we've passed the last reduced frame. | 24cfb8dRow pattern recognition patch (executor and commands).
1039 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
1040 | 1866344 | if (get_reduced_frame_status(winstate, winstate->currentpos) | 24cfb8dRow pattern recognition patch (executor and commands).
1041 | 1866344 | != RF_NOT_DETERMINED && | 24cfb8dRow pattern recognition patch (executor and commands).
1042 | 1866344 | get_reduced_frame_status(winstate, winstate->aggregatedupto) | 24cfb8dRow pattern recognition patch (executor and commands).
1043 | - | == RF_NOT_DETERMINED) | 24cfb8dRow pattern recognition patch (executor and commands).
1044 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
1045 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1046 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
1047 | - | * Calculate the reduced frame for aggregatedupto. | 24cfb8dRow pattern recognition patch (executor and commands).
1048 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
1049 | 1834752 | ret = row_is_in_reduced_frame(winstate->agg_winobj, | 24cfb8dRow pattern recognition patch (executor and commands).
1050 | - | winstate->aggregatedupto); | 24cfb8dRow pattern recognition patch (executor and commands).
1051 | 1834752 | if (ret == -1) /* unmatched row */ | 24cfb8dRow pattern recognition patch (executor and commands).
1052 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
1053 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1054 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
1055 | - | * Check if current row is inside a match but not the head | 24cfb8dRow pattern recognition patch (executor and commands).
1056 | - | * (skipped), and it's the base row for aggregation. | 24cfb8dRow pattern recognition patch (executor and commands).
1057 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
1058 | 1746500 | if (get_reduced_frame_status(winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
1059 | 1713716 | winstate->aggregatedupto) == RF_SKIPPED && | 24cfb8dRow pattern recognition patch (executor and commands).
1060 | 1713716 | winstate->aggregatedupto == winstate->aggregatedbase) | 24cfb8dRow pattern recognition patch (executor and commands).
1061 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
1062 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
1063 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1064 | - | /* Set tuple context for evaluation of aggregate arguments */ | -
1065 | - | winstate->tmpcontext->ecxt_outertuple = agg_row_slot; | -
1066 | - |  | -
1067 | - | /* Accumulate row into the aggregates */ | -
1068 | - | for (i = 0; i < numaggs; i++) | -
1069 | - | { | -
1070 | - | peraggstate = &winstate->peragg[i]; | -
1071 | - |  | -
1072 | - | /* Non-restarted aggs skip until aggregatedupto_nonrestarted */ | -
1073 | - | if (!peraggstate->restart && | -
1074 | - | winstate->aggregatedupto < aggregatedupto_nonrestarted) | -
1075 | - | continue; | -
1076 | - |  | -
1077 | - | wfuncno = peraggstate->wfuncno; | -
1078 | - | advance_windowaggregate(winstate, | -
1079 | - | &winstate->perfunc[wfuncno], | -
1080 | - | peraggstate); | -
1081 | - | } | -
1082 | - |  | -
1083 | - | next_tuple: | -
1084 | - | /* Reset per-input-tuple context after each tuple */ | -
1085 | - | ResetExprContext(winstate->tmpcontext); | -
1086 | - |  | -
1087 | - | /* And advance the aggregated-row state */ | -
1088 | - | winstate->aggregatedupto++; | -
1089 | - | ExecClearTuple(agg_row_slot); | -
1090 | - | } | -
1091 | - |  | -
1092 | - | /* The frame's end is not supposed to move backwards, ever */ | -
1093 | - | Assert(aggregatedupto_nonrestarted <= winstate->aggregatedupto); | -
1094 | - |  | -
1095 | - | /* | -
1096 | - | * finalize aggregates and fill result/isnull fields. | -
1097 | - | */ | -
1098 | - | for (i = 0; i < numaggs; i++) | -
1099 | - | { | -
1100 | - | Datum *result; | -
1101 | - | bool *isnull; | -
1102 | - |  | -
1103 | - | peraggstate = &winstate->peragg[i]; | -
1104 | - | wfuncno = peraggstate->wfuncno; | -
1105 | - | result = &econtext->ecxt_aggvalues[wfuncno]; | -
1106 | - | isnull = &econtext->ecxt_aggnulls[wfuncno]; | -
1107 | - | finalize_windowaggregate(winstate, | -
1108 | - | &winstate->perfunc[wfuncno], | -
1109 | - | peraggstate, | -
1110 | - | result, isnull); | -
1111 | - |  | -
1112 | - | /* | -
1113 | - | * save the result in case next row shares the same frame. | -
1114 | - | * | -
1115 | - | * XXX in some framing modes, eg ROWS/END_CURRENT_ROW, we can know in | -
1116 | - | * advance that the next row can't possibly share the same frame. Is | -
1117 | - | * it worth detecting that and skipping this code? | -
1118 | - | */ | -
1119 | - | if (!peraggstate->resulttypeByVal && !*isnull) | -
1120 | - | { | -
1121 | - | oldContext = MemoryContextSwitchTo(peraggstate->aggcontext); | -
1122 | - | peraggstate->resultValue = | -
1123 | - | datumCopy(*result, | -
1124 | - | peraggstate->resulttypeByVal, | -
1125 | - | peraggstate->resulttypeLen); | -
1126 | - | MemoryContextSwitchTo(oldContext); | -
1127 | - | } | -
1128 | - | else | -
1129 | - | { | -
1130 | - | peraggstate->resultValue = *result; | -
1131 | - | } | -
1132 | - | peraggstate->resultValueIsNull = *isnull; | -
1133 | - | } | -
1134 | - | } | -

prepare_tuplestore() lines 1198-1321
Modified Lines Coverage: 6/6 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
1198 | - | prepare_tuplestore(WindowAggState *winstate) | -
1199 | - | { | -
1200 | - | WindowAgg *node = (WindowAgg *) winstate->ss.ps.plan; | -
1201 | - | int frameOptions = winstate->frameOptions; | -
1202 | - | int numfuncs = winstate->numfuncs; | -
1203 | - |  | -
1204 | - | /* we shouldn't be called if this was done already */ | -
1205 | - | Assert(winstate->buffer == NULL); | -
1206 | - |  | -
1207 | - | /* Create new tuplestore */ | -
1208 | - | winstate->buffer = tuplestore_begin_heap(false, false, work_mem); | -
1209 | - |  | -
1210 | - | /* | -
1211 | - | * Set up read pointers for the tuplestore. The current pointer doesn't | -
1212 | - | * need BACKWARD capability, but the per-window-function read pointers do, | -
1213 | - | * and the aggregate pointer does if we might need to restart aggregation. | -
1214 | - | */ | -
1215 | - | winstate->current_ptr = 0; /* read pointer 0 is pre-allocated */ | -
1216 | - |  | -
1217 | - | /* reset default REWIND capability bit for current ptr */ | -
1218 | - | tuplestore_set_eflags(winstate->buffer, 0); | -
1219 | - |  | -
1220 | - | /* create read pointers for aggregates, if needed */ | -
1221 | - | if (winstate->numaggs > 0) | -
1222 | - | { | -
1223 | - | WindowObject agg_winobj = winstate->agg_winobj; | -
1224 | - | int readptr_flags = 0; | -
1225 | - |  | -
1226 | - | /* | -
1227 | - | * If the frame head is potentially movable, or we have an EXCLUSION | -
1228 | - | * clause, we might need to restart aggregation ... | -
1229 | - | */ | -
1230 | - | if (!(frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) || | -
1231 | - | (frameOptions & FRAMEOPTION_EXCLUSION)) | -
1232 | - | { | -
1233 | - | /* ... so create a mark pointer to track the frame head */ | -
1234 | - | agg_winobj->markptr = tuplestore_alloc_read_pointer(winstate->buffer, 0); | -
1235 | - | /* and the read pointer will need BACKWARD capability */ | -
1236 | - | readptr_flags |= EXEC_FLAG_BACKWARD; | -
1237 | - | } | -
1238 | - |  | -
1239 | - | agg_winobj->readptr = tuplestore_alloc_read_pointer(winstate->buffer, | -
1240 | - | readptr_flags); | -
1241 | - | } | -
1242 | - |  | -
1243 | - | /* create mark and read pointers for each real window function */ | -
1244 | - | for (int i = 0; i < numfuncs; i++) | -
1245 | - | { | -
1246 | - | WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]); | -
1247 | - |  | -
1248 | - | if (!perfuncstate->plain_agg) | -
1249 | - | { | -
1250 | - | WindowObject winobj = perfuncstate->winobj; | -
1251 | - |  | -
1252 | - | winobj->markptr = tuplestore_alloc_read_pointer(winstate->buffer, | -
1253 | - | 0); | -
1254 | - | winobj->readptr = tuplestore_alloc_read_pointer(winstate->buffer, | -
1255 | - | EXEC_FLAG_BACKWARD); | -
1256 | - | } | -
1257 | - | } | -
1258 | - |  | -
1259 | - | /* Create read/mark pointers for RPR navigation if needed */ | 24cfb8dRow pattern recognition patch (executor and commands).
1260 | 3997 | if (winstate->nav_winobj) | 24cfb8dRow pattern recognition patch (executor and commands).
1261 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
1262 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
1263 | - | * Allocate mark and read pointers for RPR navigation. | 24cfb8dRow pattern recognition patch (executor and commands).
1264 | - | * | 24cfb8dRow pattern recognition patch (executor and commands).
1265 | - | * If navMaxOffsetKind == RPR_NAV_OFFSET_FIXED, we advance the mark | 24cfb8dRow pattern recognition patch (executor and commands).
1266 | - | * based on (currentpos - navMaxOffset) and optionally | 24cfb8dRow pattern recognition patch (executor and commands).
1267 | - | * (nfaContext->matchStartRow + navFirstOffset), allowing | 24cfb8dRow pattern recognition patch (executor and commands).
1268 | - | * tuplestore_trim() to free rows that are no longer reachable. | 24cfb8dRow pattern recognition patch (executor and commands).
1269 | - | * | 24cfb8dRow pattern recognition patch (executor and commands).
1270 | - | * RPR_NAV_OFFSET_NEEDS_EVAL is resolved at executor init; by this | 24cfb8dRow pattern recognition patch (executor and commands).
1271 | - | * point it is either FIXED or RETAIN_ALL. | 24cfb8dRow pattern recognition patch (executor and commands).
1272 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
1273 | 4832 | winstate->nav_winobj->markptr = | 24cfb8dRow pattern recognition patch (executor and commands).
1274 | 2416 | tuplestore_alloc_read_pointer(winstate->buffer, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
1275 | 4832 | winstate->nav_winobj->readptr = | 24cfb8dRow pattern recognition patch (executor and commands).
1276 | 2416 | tuplestore_alloc_read_pointer(winstate->buffer, | 24cfb8dRow pattern recognition patch (executor and commands).
1277 | - | EXEC_FLAG_BACKWARD); | 24cfb8dRow pattern recognition patch (executor and commands).
1278 | 2416 | winstate->nav_winobj->markpos = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
1279 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
1280 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1281 | - | /* | -
1282 | - | * If we are in RANGE or GROUPS mode, then determining frame boundaries | -
1283 | - | * requires physical access to the frame endpoint rows, except in certain | -
1284 | - | * degenerate cases. We create read pointers to point to those rows, to | -
1285 | - | * simplify access and ensure that the tuplestore doesn't discard the | -
1286 | - | * endpoint rows prematurely. (Must create pointers in exactly the same | -
1287 | - | * cases that update_frameheadpos and update_frametailpos need them.) | -
1288 | - | */ | -
1289 | - | winstate->framehead_ptr = winstate->frametail_ptr = -1; /* if not used */ | -
1290 | - |  | -
1291 | - | if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS)) | -
1292 | - | { | -
1293 | - | if (((frameOptions & FRAMEOPTION_START_CURRENT_ROW) && | -
1294 | - | node->ordNumCols != 0) || | -
1295 | - | (frameOptions & FRAMEOPTION_START_OFFSET)) | -
1296 | - | winstate->framehead_ptr = | -
1297 | - | tuplestore_alloc_read_pointer(winstate->buffer, 0); | -
1298 | - | if (((frameOptions & FRAMEOPTION_END_CURRENT_ROW) && | -
1299 | - | node->ordNumCols != 0) || | -
1300 | - | (frameOptions & FRAMEOPTION_END_OFFSET)) | -
1301 | - | winstate->frametail_ptr = | -
1302 | - | tuplestore_alloc_read_pointer(winstate->buffer, 0); | -
1303 | - | } | -
1304 | - |  | -
1305 | - | /* | -
1306 | - | * If we have an exclusion clause that requires knowing the boundaries of | -
1307 | - | * the current row's peer group, we create a read pointer to track the | -
1308 | - | * tail position of the peer group (i.e., first row of the next peer | -
1309 | - | * group). The head position does not require its own pointer because we | -
1310 | - | * maintain that as a side effect of advancing the current row. | -
1311 | - | */ | -
1312 | - | winstate->grouptail_ptr = -1; | -
1313 | - |  | -
1314 | - | if ((frameOptions & (FRAMEOPTION_EXCLUDE_GROUP | | -
1315 | - | FRAMEOPTION_EXCLUDE_TIES)) && | -
1316 | - | node->ordNumCols != 0) | -
1317 | - | { | -
1318 | - | winstate->grouptail_ptr = | -
1319 | - | tuplestore_alloc_read_pointer(winstate->buffer, 0); | -
1320 | - | } | -
1321 | - | } | -

begin_partition() lines 1328-1435
Modified Lines Coverage: 5/5 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
1328 | - | begin_partition(WindowAggState *winstate) | -
1329 | - | { | -
1330 | - | PlanState *outerPlan = outerPlanState(winstate); | -
1331 | - | int numfuncs = winstate->numfuncs; | -
1332 | - |  | -
1333 | - | winstate->partition_spooled = false; | -
1334 | - | winstate->framehead_valid = false; | -
1335 | - | winstate->frametail_valid = false; | -
1336 | - | winstate->grouptail_valid = false; | -
1337 | 12651 | if (rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
1338 | 10192 | clear_reduced_frame(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
1339 | - | winstate->spooled_rows = 0; | -
1340 | - | winstate->currentpos = 0; | -
1341 | - | winstate->frameheadpos = 0; | -
1342 | - | winstate->frametailpos = 0; | -
1343 | - | winstate->currentgroup = 0; | -
1344 | - | winstate->frameheadgroup = 0; | -
1345 | - | winstate->frametailgroup = 0; | -
1346 | - | winstate->groupheadpos = 0; | -
1347 | - | winstate->grouptailpos = -1; /* see update_grouptailpos */ | -
1348 | - | ExecClearTuple(winstate->agg_row_slot); | -
1349 | - | if (winstate->framehead_slot) | -
1350 | - | ExecClearTuple(winstate->framehead_slot); | -
1351 | - | if (winstate->frametail_slot) | -
1352 | - | ExecClearTuple(winstate->frametail_slot); | -
1353 | - |  | -
1354 | - | /* | -
1355 | - | * If this is the very first partition, we need to fetch the first input | -
1356 | - | * row to store in first_part_slot. | -
1357 | - | */ | -
1358 | - | if (TupIsNull(winstate->first_part_slot)) | -
1359 | - | { | -
1360 | - | TupleTableSlot *outerslot = ExecProcNode(outerPlan); | -
1361 | - |  | -
1362 | - | if (!TupIsNull(outerslot)) | -
1363 | - | ExecCopySlot(winstate->first_part_slot, outerslot); | -
1364 | - | else | -
1365 | - | { | -
1366 | - | /* outer plan is empty, so we have nothing to do */ | -
1367 | - | winstate->partition_spooled = true; | -
1368 | - | winstate->more_partitions = false; | -
1369 | - | return; | -
1370 | - | } | -
1371 | - | } | -
1372 | - |  | -
1373 | - | /* Create new tuplestore if not done already. */ | -
1374 | - | if (unlikely(winstate->buffer == NULL)) | -
1375 | - | prepare_tuplestore(winstate); | -
1376 | - |  | -
1377 | - | winstate->next_partition = false; | -
1378 | - |  | -
1379 | - | if (winstate->numaggs > 0) | -
1380 | - | { | -
1381 | - | WindowObject agg_winobj = winstate->agg_winobj; | -
1382 | - |  | -
1383 | - | /* reset mark and see positions for aggregate functions */ | -
1384 | - | agg_winobj->markpos = -1; | -
1385 | - | agg_winobj->seekpos = -1; | -
1386 | - |  | -
1387 | - | /* Also reset the row counters for aggregates */ | -
1388 | - | winstate->aggregatedbase = 0; | -
1389 | - | winstate->aggregatedupto = 0; | -
1390 | - | } | -
1391 | - |  | -
1392 | - | /* reset mark and seek positions for RPR navigation */ | 24cfb8dRow pattern recognition patch (executor and commands).
1393 | 12627 | if (winstate->nav_winobj) | 24cfb8dRow pattern recognition patch (executor and commands).
1394 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
1395 | 10180 | winstate->nav_winobj->markpos = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
1396 | 10180 | winstate->nav_winobj->seekpos = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
1397 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
1398 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1399 | - | /* reset mark and seek positions for each real window function */ | -
1400 | - | for (int i = 0; i < numfuncs; i++) | -
1401 | - | { | -
1402 | - | WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]); | -
1403 | - |  | -
1404 | - | if (!perfuncstate->plain_agg) | -
1405 | - | { | -
1406 | - | WindowObject winobj = perfuncstate->winobj; | -
1407 | - |  | -
1408 | - | winobj->markpos = -1; | -
1409 | - | winobj->seekpos = -1; | -
1410 | - |  | -
1411 | - | /* reset null map */ | -
1412 | - | if (winobj->ignore_nulls == IGNORE_NULLS || | -
1413 | - | winobj->ignore_nulls == PARSER_IGNORE_NULLS) | -
1414 | - | { | -
1415 | - | int numargs = perfuncstate->numArguments; | -
1416 | - |  | -
1417 | - | for (int j = 0; j < numargs; j++) | -
1418 | - | { | -
1419 | - | int n = winobj->num_notnull_info[j]; | -
1420 | - |  | -
1421 | - | if (n > 0) | -
1422 | - | memset(winobj->notnull_info[j], 0, | -
1423 | - | NN_POS_TO_BYTES(n)); | -
1424 | - | } | -
1425 | - | } | -
1426 | - | } | -
1427 | - | } | -
1428 | - |  | -
1429 | - | /* | -
1430 | - | * Store the first tuple into the tuplestore (it's always available now; | -
1431 | - | * we either read it above, or saved it at the end of previous partition) | -
1432 | - | */ | -
1433 | - | tuplestore_puttupleslot(winstate->buffer, winstate->first_part_slot); | -
1434 | - | winstate->spooled_rows++; | -
1435 | - | } | -

release_partition() lines 1536-1582
Modified Lines Coverage: 9/9 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
1536 | - | release_partition(WindowAggState *winstate) | -
1537 | - | { | -
1538 | - | int i; | -
1539 | - |  | -
1540 | - | for (i = 0; i < winstate->numfuncs; i++) | -
1541 | - | { | -
1542 | - | WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]); | -
1543 | - |  | -
1544 | - | /* Release any partition-local state of this window function */ | -
1545 | - | if (perfuncstate->winobj) | -
1546 | - | perfuncstate->winobj->localmem = NULL; | -
1547 | - | } | -
1548 | - |  | -
1549 | - | /* | -
1550 | - | * Release all partition-local memory (in particular, any partition-local | -
1551 | - | * state that we might have trashed our pointers to in the above loop, and | -
1552 | - | * any aggregate temp data). We don't rely on retail pfree because some | -
1553 | - | * aggregates might have allocated data we don't have direct pointers to. | -
1554 | - | */ | -
1555 | - | MemoryContextReset(winstate->partcontext); | -
1556 | - | MemoryContextReset(winstate->aggcontext); | -
1557 | - | for (i = 0; i < winstate->numaggs; i++) | -
1558 | - | { | -
1559 | - | if (winstate->peragg[i].aggcontext != winstate->aggcontext) | -
1560 | - | MemoryContextReset(winstate->peragg[i].aggcontext); | -
1561 | - | } | -
1562 | - |  | -
1563 | - | if (winstate->buffer) | -
1564 | - | tuplestore_clear(winstate->buffer); | -
1565 | - | winstate->partition_spooled = false; | -
1566 | - | winstate->next_partition = true; | -
1567 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1568 | - | /* Reset RPR match results */ | 24cfb8dRow pattern recognition patch (executor and commands).
1569 | 17249 | clear_reduced_frame(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
1570 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1571 | - | /* Reset NFA state for new partition */ | 24cfb8dRow pattern recognition patch (executor and commands).
1572 | 17249 | winstate->nfaContext = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
1573 | 17249 | winstate->nfaContextTail = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
1574 | 17249 | winstate->nfaContextFree = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
1575 | 17249 | winstate->nfaStateFree = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
1576 | 17249 | winstate->nfaLastProcessedRow = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
1577 | 17249 | winstate->nfaStatesActive = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
1578 | 17249 | winstate->nfaContextsActive = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
1579 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
1580 | - | /* Invalidate the nav slot position cache for the new partition. */ | 24cfb8dRow pattern recognition patch (executor and commands).
1581 | 17249 | winstate->nav_slot_pos = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
1582 | - | } | -

calculate_frame_offsets() lines 2311-2390
Modified Lines Coverage: 2/2 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
2311 | - | calculate_frame_offsets(PlanState *pstate) | -
2312 | - | { | -
2313 | - | WindowAggState *winstate = castNode(WindowAggState, pstate); | -
2314 | - | ExprContext *econtext; | -
2315 | - | int frameOptions = winstate->frameOptions; | -
2316 | - | Datum value; | -
2317 | - | bool isnull; | -
2318 | - | int16 len; | -
2319 | - | bool byval; | -
2320 | - |  | -
2321 | - | /* Ensure we've not been called before for this scan */ | -
2322 | - | Assert(winstate->all_first); | -
2323 | - |  | -
2324 | - | econtext = winstate->ss.ps.ps_ExprContext; | -
2325 | - |  | -
2326 | - | if (frameOptions & FRAMEOPTION_START_OFFSET) | -
2327 | - | { | -
2328 | - | Assert(winstate->startOffset != NULL); | -
2329 | - | value = ExecEvalExprSwitchContext(winstate->startOffset, | -
2330 | - | econtext, | -
2331 | - | &isnull); | -
2332 | - | if (isnull) | -
2333 | - | ereport(ERROR, | -
2334 | - | (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), | -
2335 | - | errmsg("frame starting offset must not be null"))); | -
2336 | - | /* copy value into query-lifespan context */ | -
2337 | - | get_typlenbyval(exprType((Node *) winstate->startOffset->expr), | -
2338 | - | &len, | -
2339 | - | &byval); | -
2340 | - | winstate->startOffsetValue = datumCopy(value, byval, len); | -
2341 | - | if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS)) | -
2342 | - | { | -
2343 | - | /* value is known to be int8 */ | -
2344 | - | int64 offset = DatumGetInt64(value); | -
2345 | - |  | -
2346 | - | if (offset < 0) | -
2347 | - | ereport(ERROR, | -
2348 | - | (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), | -
2349 | - | errmsg("frame starting offset must not be negative"))); | -
2350 | - | } | -
2351 | - | } | -
2352 | - |  | -
2353 | - | if (frameOptions & FRAMEOPTION_END_OFFSET) | -
2354 | - | { | -
2355 | - | Assert(winstate->endOffset != NULL); | -
2356 | - | value = ExecEvalExprSwitchContext(winstate->endOffset, | -
2357 | - | econtext, | -
2358 | - | &isnull); | -
2359 | - | if (isnull) | -
2360 | - | ereport(ERROR, | -
2361 | - | (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), | -
2362 | - | errmsg("frame ending offset must not be null"))); | -
2363 | - | /* copy value into query-lifespan context */ | -
2364 | - | get_typlenbyval(exprType((Node *) winstate->endOffset->expr), | -
2365 | - | &len, | -
2366 | - | &byval); | -
2367 | - | winstate->endOffsetValue = datumCopy(value, byval, len); | -
2368 | - | if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS)) | -
2369 | - | { | -
2370 | - | /* value is known to be int8 */ | -
2371 | - | int64 offset = DatumGetInt64(value); | -
2372 | - |  | -
2373 | - | if (offset < 0) | -
2374 | - | ereport(ERROR, | -
2375 | - | (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), | -
2376 | - | errmsg("frame ending offset must not be negative"))); | -
2377 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2378 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
2379 | - | * Row pattern recognition forbids a zero-length frame end; | 24cfb8dRow pattern recognition patch (executor and commands).
2380 | - | * checked here so a non-constant offset (e.g. a bind parameter) | 24cfb8dRow pattern recognition patch (executor and commands).
2381 | - | * is caught, not just a literal 0. | 24cfb8dRow pattern recognition patch (executor and commands).
2382 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
2383 | 348 | if (winstate->rpPattern != NULL && offset == 0) | 24cfb8dRow pattern recognition patch (executor and commands).
2384 | 8 | ereport(ERROR, | 24cfb8dRow pattern recognition patch (executor and commands).
2385 | - | errcode(ERRCODE_WINDOWING_ERROR), | 24cfb8dRow pattern recognition patch (executor and commands).
2386 | - | errmsg("frame ending offset must be positive with row pattern recognition")); | 24cfb8dRow pattern recognition patch (executor and commands).
2387 | - | } | -
2388 | - | } | -
2389 | - | winstate->all_first = false; | -
2390 | - | } | -

ExecWindowAgg() lines 2402-2680
Modified Lines Coverage: 5/5 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
2402 | - | ExecWindowAgg(PlanState *pstate) | -
2403 | - | { | -
2404 | - | WindowAggState *winstate = castNode(WindowAggState, pstate); | -
2405 | - | TupleTableSlot *slot; | -
2406 | - | ExprContext *econtext; | -
2407 | - | int i; | -
2408 | - | int numfuncs; | -
2409 | - |  | -
2410 | - | CHECK_FOR_INTERRUPTS(); | -
2411 | - |  | -
2412 | - | if (winstate->status == WINDOWAGG_DONE) | -
2413 | - | return NULL; | -
2414 | - |  | -
2415 | - | /* | -
2416 | - | * Compute frame offset values, if any, during first call (or after a | -
2417 | - | * rescan). These are assumed to hold constant throughout the scan; if | -
2418 | - | * user gives us a volatile expression, we'll only use its initial value. | -
2419 | - | */ | -
2420 | - | if (unlikely(winstate->all_first)) | -
2421 | - | calculate_frame_offsets(pstate); | -
2422 | - |  | -
2423 | - | /* We need to loop as the runCondition or qual may filter out tuples */ | -
2424 | - | for (;;) | -
2425 | - | { | -
2426 | - | if (winstate->next_partition) | -
2427 | - | { | -
2428 | - | /* Initialize for first partition and set current row = 0 */ | -
2429 | - | begin_partition(winstate); | -
2430 | - | /* If there are no input rows, we'll detect that and exit below */ | -
2431 | - | } | -
2432 | - | else | -
2433 | - | { | -
2434 | - | /* Advance current row within partition */ | -
2435 | - | winstate->currentpos++; | -
2436 | - | /* This might mean that the frame moves, too */ | -
2437 | - | winstate->framehead_valid = false; | -
2438 | - | winstate->frametail_valid = false; | -
2439 | - | /* we don't need to invalidate grouptail here; see below */ | -
2440 | - | } | -
2441 | - |  | -
2442 | - | /* | -
2443 | - | * Spool all tuples up to and including the current row, if we haven't | -
2444 | - | * already | -
2445 | - | */ | -
2446 | - | spool_tuples(winstate, winstate->currentpos); | -
2447 | - |  | -
2448 | - | /* Move to the next partition if we reached the end of this partition */ | -
2449 | - | if (winstate->partition_spooled && | -
2450 | - | winstate->currentpos >= winstate->spooled_rows) | -
2451 | - | { | -
2452 | - | release_partition(winstate); | -
2453 | - |  | -
2454 | - | if (winstate->more_partitions) | -
2455 | - | { | -
2456 | - | begin_partition(winstate); | -
2457 | - | Assert(winstate->spooled_rows > 0); | -
2458 | - |  | -
2459 | - | /* Come out of pass-through mode when changing partition */ | -
2460 | - | winstate->status = WINDOWAGG_RUN; | -
2461 | - | } | -
2462 | - | else | -
2463 | - | { | -
2464 | - | /* No further partitions? We're done */ | -
2465 | - | winstate->status = WINDOWAGG_DONE; | -
2466 | - | return NULL; | -
2467 | - | } | -
2468 | - | } | -
2469 | - |  | -
2470 | - | /* final output execution is in ps_ExprContext */ | -
2471 | - | econtext = winstate->ss.ps.ps_ExprContext; | -
2472 | - |  | -
2473 | - | /* Clear the per-output-tuple context for current row */ | -
2474 | - | ResetExprContext(econtext); | -
2475 | - |  | -
2476 | - | /* | -
2477 | - | * Read the current row from the tuplestore, and save in | -
2478 | - | * ScanTupleSlot. (We can't rely on the outerplan's output slot | -
2479 | - | * because we may have to read beyond the current row. Also, we have | -
2480 | - | * to actually copy the row out of the tuplestore, since window | -
2481 | - | * function evaluation might cause the tuplestore to dump its state to | -
2482 | - | * disk.) | -
2483 | - | * | -
2484 | - | * In GROUPS mode, or when tracking a group-oriented exclusion clause, | -
2485 | - | * we must also detect entering a new peer group and update associated | -
2486 | - | * state when that happens. We use temp_slot_2 to temporarily hold | -
2487 | - | * the previous row for this purpose. | -
2488 | - | * | -
2489 | - | * Current row must be in the tuplestore, since we spooled it above. | -
2490 | - | */ | -
2491 | - | tuplestore_select_read_pointer(winstate->buffer, winstate->current_ptr); | -
2492 | - | if ((winstate->frameOptions & (FRAMEOPTION_GROUPS | | -
2493 | - | FRAMEOPTION_EXCLUDE_GROUP | | -
2494 | - | FRAMEOPTION_EXCLUDE_TIES)) && | -
2495 | - | winstate->currentpos > 0) | -
2496 | - | { | -
2497 | - | ExecCopySlot(winstate->temp_slot_2, winstate->ss.ss_ScanTupleSlot); | -
2498 | - | if (!tuplestore_gettupleslot(winstate->buffer, true, true, | -
2499 | - | winstate->ss.ss_ScanTupleSlot)) | -
2500 | - | elog(ERROR, "unexpected end of tuplestore"); | -
2501 | - | if (!are_peers(winstate, winstate->temp_slot_2, | -
2502 | - | winstate->ss.ss_ScanTupleSlot)) | -
2503 | - | { | -
2504 | - | winstate->currentgroup++; | -
2505 | - | winstate->groupheadpos = winstate->currentpos; | -
2506 | - | winstate->grouptail_valid = false; | -
2507 | - | } | -
2508 | - | ExecClearTuple(winstate->temp_slot_2); | -
2509 | - | } | -
2510 | - | else | -
2511 | - | { | -
2512 | - | if (!tuplestore_gettupleslot(winstate->buffer, true, true, | -
2513 | - | winstate->ss.ss_ScanTupleSlot)) | -
2514 | - | elog(ERROR, "unexpected end of tuplestore"); | -
2515 | - | } | -
2516 | - |  | -
2517 | - | /* don't evaluate the window functions when we're in pass-through mode */ | -
2518 | - | if (winstate->status == WINDOWAGG_RUN) | -
2519 | - | { | -
2520 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
2521 | - | * If RPR is defined and skip mode is next row, clear the current | 24cfb8dRow pattern recognition patch (executor and commands).
2522 | - | * match so the next row triggers re-evaluation. | 24cfb8dRow pattern recognition patch (executor and commands).
2523 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
2524 | 1592544 | if (rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
2525 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
2526 | 988684 | if (winstate->rpSkipTo == ST_NEXT_ROW) | 24cfb8dRow pattern recognition patch (executor and commands).
2527 | 7536 | clear_reduced_frame(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
2528 | - |  | 0ed285dDrive RPR row pattern matching once per row
2529 | - | /* | 0ed285dDrive RPR row pattern matching once per row
2530 | - | * Drive the row pattern match every row, so it tracks the row | 0ed285dDrive RPR row pattern matching once per row
2531 | - | * scan rather than frame access: a window function that skips | 0ed285dDrive RPR row pattern matching once per row
2532 | - | * the frame (e.g. nth_value() with a NULL offset) must not | 0ed285dDrive RPR row pattern matching once per row
2533 | - | * leave the match state behind currentpos. | 0ed285dDrive RPR row pattern matching once per row
2534 | - | */ | 0ed285dDrive RPR row pattern matching once per row
2535 | 988684 | Assert(winstate->nav_winobj != NULL); | 0ed285dDrive RPR row pattern matching once per row
2536 | 988684 | (void) row_is_in_reduced_frame(winstate->nav_winobj, | 0ed285dDrive RPR row pattern matching once per row
2537 | - | winstate->currentpos); | 0ed285dDrive RPR row pattern matching once per row
2538 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
2539 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2540 | - | /* | -
2541 | - | * Evaluate true window functions | -
2542 | - | */ | -
2543 | - | numfuncs = winstate->numfuncs; | -
2544 | - | for (i = 0; i < numfuncs; i++) | -
2545 | - | { | -
2546 | - | WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]); | -
2547 | - |  | -
2548 | - | if (perfuncstate->plain_agg) | -
2549 | - | continue; | -
2550 | - | eval_windowfunction(winstate, perfuncstate, | -
2551 | - | &(econtext->ecxt_aggvalues[perfuncstate->wfuncstate->wfuncno]), | -
2552 | - | &(econtext->ecxt_aggnulls[perfuncstate->wfuncstate->wfuncno])); | -
2553 | - | } | -
2554 | - |  | -
2555 | - | /* | -
2556 | - | * Evaluate aggregates | -
2557 | - | */ | -
2558 | - | if (winstate->numaggs > 0) | -
2559 | - | eval_windowaggregates(winstate); | -
2560 | - | } | -
2561 | - |  | -
2562 | - | /* | -
2563 | - | * If we have created auxiliary read pointers for the frame or group | -
2564 | - | * boundaries, force them to be kept up-to-date, because we don't know | -
2565 | - | * whether the window function(s) will do anything that requires that. | -
2566 | - | * Failing to advance the pointers would result in being unable to | -
2567 | - | * trim data from the tuplestore, which is bad. (If we could know in | -
2568 | - | * advance whether the window functions will use frame boundary info, | -
2569 | - | * we could skip creating these pointers in the first place ... but | -
2570 | - | * unfortunately the window function API doesn't require that.) | -
2571 | - | */ | -
2572 | - | if (winstate->framehead_ptr >= 0) | -
2573 | - | update_frameheadpos(winstate); | -
2574 | - | if (winstate->frametail_ptr >= 0) | -
2575 | - | update_frametailpos(winstate); | -
2576 | - | if (winstate->grouptail_ptr >= 0) | -
2577 | - | update_grouptailpos(winstate); | -
2578 | - |  | -
2579 | - | /* | -
2580 | - | * Truncate any no-longer-needed rows from the tuplestore. | -
2581 | - | */ | -
2582 | - | tuplestore_trim(winstate->buffer); | -
2583 | - |  | -
2584 | - | /* | -
2585 | - | * Form and return a projection tuple using the windowfunc results and | -
2586 | - | * the current row. Setting ecxt_outertuple arranges that any Vars | -
2587 | - | * will be evaluated with respect to that row. | -
2588 | - | */ | -
2589 | - | econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot; | -
2590 | - |  | -
2591 | - | slot = ExecProject(winstate->ss.ps.ps_ProjInfo); | -
2592 | - |  | -
2593 | - | if (winstate->status == WINDOWAGG_RUN) | -
2594 | - | { | -
2595 | - | econtext->ecxt_scantuple = slot; | -
2596 | - |  | -
2597 | - | /* | -
2598 | - | * Now evaluate the run condition to see if we need to go into | -
2599 | - | * pass-through mode, or maybe stop completely. | -
2600 | - | */ | -
2601 | - | if (!ExecQual(winstate->runcondition, econtext)) | -
2602 | - | { | -
2603 | - | /* | -
2604 | - | * Determine which mode to move into. If there is no | -
2605 | - | * PARTITION BY clause and we're the top-level WindowAgg then | -
2606 | - | * we're done. This tuple and any future tuples cannot | -
2607 | - | * possibly match the runcondition. However, when there is a | -
2608 | - | * PARTITION BY clause or we're not the top-level window we | -
2609 | - | * can't just stop as we need to either process other | -
2610 | - | * partitions or ensure WindowAgg nodes above us receive all | -
2611 | - | * of the tuples they need to process their WindowFuncs. | -
2612 | - | */ | -
2613 | - | if (winstate->use_pass_through) | -
2614 | - | { | -
2615 | - | /* | -
2616 | - | * When switching into a pass-through mode, we'd better | -
2617 | - | * NULLify the aggregate results as these are no longer | -
2618 | - | * updated and NULLifying them avoids the old stale | -
2619 | - | * results lingering. Some of these might be byref types | -
2620 | - | * so we can't have them pointing to free'd memory. The | -
2621 | - | * planner insisted that quals used in the runcondition | -
2622 | - | * are strict, so the top-level WindowAgg will always | -
2623 | - | * filter these NULLs out in the filter clause. | -
2624 | - | */ | -
2625 | - | numfuncs = winstate->numfuncs; | -
2626 | - | for (i = 0; i < numfuncs; i++) | -
2627 | - | { | -
2628 | - | econtext->ecxt_aggvalues[i] = (Datum) 0; | -
2629 | - | econtext->ecxt_aggnulls[i] = true; | -
2630 | - | } | -
2631 | - |  | -
2632 | - | /* | -
2633 | - | * STRICT pass-through mode is required for the top window | -
2634 | - | * when there is a PARTITION BY clause. Otherwise we must | -
2635 | - | * ensure we store tuples that don't match the | -
2636 | - | * runcondition so they're available to WindowAggs above. | -
2637 | - | */ | -
2638 | - | if (winstate->top_window) | -
2639 | - | { | -
2640 | - | winstate->status = WINDOWAGG_PASSTHROUGH_STRICT; | -
2641 | - | continue; | -
2642 | - | } | -
2643 | - | else | -
2644 | - | { | -
2645 | - | winstate->status = WINDOWAGG_PASSTHROUGH; | -
2646 | - | } | -
2647 | - | } | -
2648 | - | else | -
2649 | - | { | -
2650 | - | /* | -
2651 | - | * Pass-through not required. We can just return NULL. | -
2652 | - | * Nothing else will match the runcondition. | -
2653 | - | */ | -
2654 | - | winstate->status = WINDOWAGG_DONE; | -
2655 | - | return NULL; | -
2656 | - | } | -
2657 | - | } | -
2658 | - |  | -
2659 | - | /* | -
2660 | - | * Filter out any tuples we don't need in the top-level WindowAgg. | -
2661 | - | */ | -
2662 | - | if (!ExecQual(winstate->ss.ps.qual, econtext)) | -
2663 | - | { | -
2664 | - | InstrCountFiltered1(winstate, 1); | -
2665 | - | continue; | -
2666 | - | } | -
2667 | - |  | -
2668 | - | break; | -
2669 | - | } | -
2670 | - |  | -
2671 | - | /* | -
2672 | - | * When not in WINDOWAGG_RUN mode, we must still return this tuple if | -
2673 | - | * we're anything apart from the top window. | -
2674 | - | */ | -
2675 | - | else if (!winstate->top_window) | -
2676 | - | break; | -
2677 | - | } | -
2678 | - |  | -
2679 | - | return slot; | -
2680 | - | } | -

ExecInitWindowAgg() lines 2690-3117
Modified Lines Coverage: 58/58 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
2690 | - | ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) | -
2691 | - | { | -
2692 | - | WindowAggState *winstate; | -
2693 | - | Plan *outerPlan; | -
2694 | - | ExprContext *econtext; | -
2695 | - | ExprContext *tmpcontext; | -
2696 | - | WindowStatePerFunc perfunc; | -
2697 | - | WindowStatePerAgg peragg; | -
2698 | - | int frameOptions = node->frameOptions; | -
2699 | - | int numfuncs, | -
2700 | - | wfuncno, | -
2701 | - | numaggs, | -
2702 | - | aggno; | -
2703 | - | TupleDesc scanDesc; | -
2704 | - | ListCell *l; | -
2705 | - |  | -
2706 | - | /* check for unsupported flags */ | -
2707 | - | Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); | -
2708 | - |  | -
2709 | - | /* | -
2710 | - | * create state structure | -
2711 | - | */ | -
2712 | - | winstate = makeNode(WindowAggState); | -
2713 | - | winstate->ss.ps.plan = (Plan *) node; | -
2714 | - | winstate->ss.ps.state = estate; | -
2715 | - | winstate->ss.ps.ExecProcNode = ExecWindowAgg; | -
2716 | - |  | -
2717 | - | /* copy frame options to state node for easy access */ | -
2718 | - | winstate->frameOptions = frameOptions; | -
2719 | - |  | -
2720 | - | /* | -
2721 | - | * Create expression contexts. We need two, one for per-input-tuple | -
2722 | - | * processing and one for per-output-tuple processing, plus an optional | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2723 | - | * third for row pattern recognition DEFINE evaluation (built just below | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2724 | - | * when a DEFINE clause is present). We cheat a little by using | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2725 | - | * ExecAssignExprContext() to build them all. Each call overwrites | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2726 | - | * ps_ExprContext, so the last call must establish the output context. | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2727 | - | */ | -
2728 | - | ExecAssignExprContext(estate, &winstate->ss.ps); | -
2729 | - | tmpcontext = winstate->ss.ps.ps_ExprContext; | -
2730 | - | winstate->tmpcontext = tmpcontext; | -
2731 | - |  | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2732 | - | /* | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2733 | - | * Row pattern recognition evaluates DEFINE clauses in a third context, | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2734 | - | * reset before each DEFINE evaluation pass. It must be distinct from | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2735 | - | * tmpcontext and ps_ExprContext so its reset frees neither input nor | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2736 | - | * output tuple memory. | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2737 | - | */ | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2738 | 4974 | if (node->defineClause != NIL) | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2739 | - | { | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2740 | 2996 | ExecAssignExprContext(estate, &winstate->ss.ps); | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2741 | 2996 | winstate->rprContext = winstate->ss.ps.ps_ExprContext; | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2742 | - | } | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2743 | - |  | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
2744 | - | ExecAssignExprContext(estate, &winstate->ss.ps); | -
2745 | - |  | -
2746 | - | /* Create long-lived context for storage of partition-local memory etc */ | -
2747 | - | winstate->partcontext = | -
2748 | - | AllocSetContextCreate(CurrentMemoryContext, | -
2749 | - | "WindowAgg Partition", | -
2750 | - | ALLOCSET_DEFAULT_SIZES); | -
2751 | - |  | -
2752 | - | /* | -
2753 | - | * Create mid-lived context for aggregate trans values etc. | -
2754 | - | * | -
2755 | - | * Note that moving aggregates each use their own private context, not | -
2756 | - | * this one. | -
2757 | - | */ | -
2758 | - | winstate->aggcontext = | -
2759 | - | AllocSetContextCreate(CurrentMemoryContext, | -
2760 | - | "WindowAgg Aggregates", | -
2761 | - | ALLOCSET_DEFAULT_SIZES); | -
2762 | - |  | -
2763 | - | /* Only the top-level WindowAgg may have a qual */ | -
2764 | - | Assert(node->plan.qual == NIL || node->topWindow); | -
2765 | - |  | -
2766 | - | /* Initialize the qual */ | -
2767 | - | winstate->ss.ps.qual = ExecInitQual(node->plan.qual, | -
2768 | - | (PlanState *) winstate); | -
2769 | - |  | -
2770 | - | /* | -
2771 | - | * Setup the run condition, if we received one from the query planner. | -
2772 | - | * When set, this may allow us to move into pass-through mode so that we | -
2773 | - | * don't have to perform any further evaluation of WindowFuncs in the | -
2774 | - | * current partition or possibly stop returning tuples altogether when all | -
2775 | - | * tuples are in the same partition. | -
2776 | - | */ | -
2777 | - | winstate->runcondition = ExecInitQual(node->runCondition, | -
2778 | - | (PlanState *) winstate); | -
2779 | - |  | -
2780 | - | /* | -
2781 | - | * When we're not the top-level WindowAgg node or we are but have a | -
2782 | - | * PARTITION BY clause we must move into one of the WINDOWAGG_PASSTHROUGH* | -
2783 | - | * modes when the runCondition becomes false. | -
2784 | - | */ | -
2785 | - | winstate->use_pass_through = !node->topWindow || node->partNumCols > 0; | -
2786 | - |  | -
2787 | - | /* remember if we're the top-window or we are below the top-window */ | -
2788 | - | winstate->top_window = node->topWindow; | -
2789 | - |  | -
2790 | - | /* | -
2791 | - | * initialize child nodes | -
2792 | - | */ | -
2793 | - | outerPlan = outerPlan(node); | -
2794 | - | outerPlanState(winstate) = ExecInitNode(outerPlan, estate, eflags); | -
2795 | - |  | -
2796 | - | /* | -
2797 | - | * initialize source tuple type (which is also the tuple type that we'll | -
2798 | - | * store in the tuplestore and use in all our working slots). | -
2799 | - | */ | -
2800 | - | ExecCreateScanSlotFromOuterPlan(estate, &winstate->ss, &TTSOpsMinimalTuple); | -
2801 | - | scanDesc = winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor; | -
2802 | - |  | -
2803 | - | /* the outer tuple isn't the child's tuple, but always a minimal tuple */ | -
2804 | - | winstate->ss.ps.outeropsset = true; | -
2805 | - | winstate->ss.ps.outerops = &TTSOpsMinimalTuple; | -
2806 | - | winstate->ss.ps.outeropsfixed = true; | -
2807 | - |  | -
2808 | - | /* | -
2809 | - | * tuple table initialization | -
2810 | - | */ | -
2811 | - | winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc, | -
2812 | - | &TTSOpsMinimalTuple); | -
2813 | - | winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc, | -
2814 | - | &TTSOpsMinimalTuple); | -
2815 | - | winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc, | -
2816 | - | &TTSOpsMinimalTuple); | -
2817 | - | winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc, | -
2818 | - | &TTSOpsMinimalTuple); | -
2819 | - |  | -
2820 | 4974 | if (node->rpPattern != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
2821 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
2822 | 2996 | winstate->nav_slot = ExecInitExtraTupleSlot(estate, scanDesc, | 24cfb8dRow pattern recognition patch (executor and commands).
2823 | - | &TTSOpsMinimalTuple); | 24cfb8dRow pattern recognition patch (executor and commands).
2824 | 2996 | winstate->nav_slot_pos = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
2825 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2826 | 2996 | winstate->nav_null_slot = ExecInitExtraTupleSlot(estate, scanDesc, | 24cfb8dRow pattern recognition patch (executor and commands).
2827 | - | &TTSOpsMinimalTuple); | 24cfb8dRow pattern recognition patch (executor and commands).
2828 | 2996 | winstate->nav_null_slot = ExecStoreAllNullTuple(winstate->nav_null_slot); | 24cfb8dRow pattern recognition patch (executor and commands).
2829 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2830 | 2996 | winstate->nav_saved_outertuple = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
2831 | 2996 | winstate->nav_match_start = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
2832 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
2833 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2834 | - | /* | -
2835 | - | * create frame head and tail slots only if needed (must create slots in | -
2836 | - | * exactly the same cases that update_frameheadpos and update_frametailpos | -
2837 | - | * need them) | -
2838 | - | */ | -
2839 | - | winstate->framehead_slot = winstate->frametail_slot = NULL; | -
2840 | - |  | -
2841 | - | if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS)) | -
2842 | - | { | -
2843 | - | if (((frameOptions & FRAMEOPTION_START_CURRENT_ROW) && | -
2844 | - | node->ordNumCols != 0) || | -
2845 | - | (frameOptions & FRAMEOPTION_START_OFFSET)) | -
2846 | - | winstate->framehead_slot = ExecInitExtraTupleSlot(estate, scanDesc, | -
2847 | - | &TTSOpsMinimalTuple); | -
2848 | - | if (((frameOptions & FRAMEOPTION_END_CURRENT_ROW) && | -
2849 | - | node->ordNumCols != 0) || | -
2850 | - | (frameOptions & FRAMEOPTION_END_OFFSET)) | -
2851 | - | winstate->frametail_slot = ExecInitExtraTupleSlot(estate, scanDesc, | -
2852 | - | &TTSOpsMinimalTuple); | -
2853 | - | } | -
2854 | - |  | -
2855 | - | /* | -
2856 | - | * Initialize result slot, type and projection. | -
2857 | - | */ | -
2858 | - | ExecInitResultTupleSlotTL(&winstate->ss.ps, &TTSOpsVirtual); | -
2859 | - | ExecAssignProjectionInfo(&winstate->ss.ps, NULL); | -
2860 | - |  | -
2861 | - | /* Set up data for comparing tuples */ | -
2862 | - | if (node->partNumCols > 0) | -
2863 | - | winstate->partEqfunction = | -
2864 | - | execTuplesMatchPrepare(scanDesc, | -
2865 | - | node->partNumCols, | -
2866 | - | node->partColIdx, | -
2867 | - | node->partOperators, | -
2868 | - | node->partCollations, | -
2869 | - | &winstate->ss.ps); | -
2870 | - |  | -
2871 | - | if (node->ordNumCols > 0) | -
2872 | - | winstate->ordEqfunction = | -
2873 | - | execTuplesMatchPrepare(scanDesc, | -
2874 | - | node->ordNumCols, | -
2875 | - | node->ordColIdx, | -
2876 | - | node->ordOperators, | -
2877 | - | node->ordCollations, | -
2878 | - | &winstate->ss.ps); | -
2879 | - |  | -
2880 | - | /* | -
2881 | - | * WindowAgg nodes use aggvalues and aggnulls as well as Agg nodes. | -
2882 | - | */ | -
2883 | - | numfuncs = winstate->numfuncs; | -
2884 | - | numaggs = winstate->numaggs; | -
2885 | - | econtext = winstate->ss.ps.ps_ExprContext; | -
2886 | - | econtext->ecxt_aggvalues = palloc0_array(Datum, numfuncs); | -
2887 | - | econtext->ecxt_aggnulls = palloc0_array(bool, numfuncs); | -
2888 | - |  | -
2889 | - | /* | -
2890 | - | * allocate per-wfunc/per-agg state information. | -
2891 | - | */ | -
2892 | - | perfunc = palloc0_array(WindowStatePerFuncData, numfuncs); | -
2893 | - | peragg = palloc0_array(WindowStatePerAggData, numaggs); | -
2894 | - | winstate->perfunc = perfunc; | -
2895 | - | winstate->peragg = peragg; | -
2896 | - |  | -
2897 | - | wfuncno = -1; | -
2898 | - | aggno = -1; | -
2899 | - | foreach(l, winstate->funcs) | -
2900 | - | { | -
2901 | - | WindowFuncExprState *wfuncstate = (WindowFuncExprState *) lfirst(l); | -
2902 | - | WindowFunc *wfunc = wfuncstate->wfunc; | -
2903 | - | WindowStatePerFunc perfuncstate; | -
2904 | - | AclResult aclresult; | -
2905 | - | int i; | -
2906 | - |  | -
2907 | - | if (wfunc->winref != node->winref) /* planner screwed up? */ | -
2908 | - | elog(ERROR, "WindowFunc with winref %u assigned to WindowAgg with winref %u", | -
2909 | - | wfunc->winref, node->winref); | -
2910 | - |  | -
2911 | - | /* | -
2912 | - | * Look for a previous duplicate window function, which needs the same | -
2913 | - | * ignore_nulls value | -
2914 | - | */ | -
2915 | - | for (i = 0; i <= wfuncno; i++) | -
2916 | - | { | -
2917 | - | if (equal(wfunc, perfunc[i].wfunc) && | -
2918 | - | !contain_volatile_functions((Node *) wfunc)) | -
2919 | - | break; | -
2920 | - | } | -
2921 | - | if (i <= wfuncno && wfunc->ignore_nulls == perfunc[i].ignore_nulls) | -
2922 | - | { | -
2923 | - | /* Found a match to an existing entry, so just mark it */ | -
2924 | - | wfuncstate->wfuncno = i; | -
2925 | - | continue; | -
2926 | - | } | -
2927 | - |  | -
2928 | - | /* Nope, so assign a new PerAgg record */ | -
2929 | - | perfuncstate = &perfunc[++wfuncno]; | -
2930 | - |  | -
2931 | - | /* Mark WindowFunc state node with assigned index in the result array */ | -
2932 | - | wfuncstate->wfuncno = wfuncno; | -
2933 | - |  | -
2934 | - | /* Check permission to call window function */ | -
2935 | - | aclresult = object_aclcheck(ProcedureRelationId, wfunc->winfnoid, GetUserId(), | -
2936 | - | ACL_EXECUTE); | -
2937 | - | if (aclresult != ACLCHECK_OK) | -
2938 | - | aclcheck_error(aclresult, OBJECT_FUNCTION, | -
2939 | - | get_func_name(wfunc->winfnoid)); | -
2940 | - | InvokeFunctionExecuteHook(wfunc->winfnoid); | -
2941 | - |  | -
2942 | - | /* Fill in the perfuncstate data */ | -
2943 | - | perfuncstate->wfuncstate = wfuncstate; | -
2944 | - | perfuncstate->wfunc = wfunc; | -
2945 | - | perfuncstate->numArguments = list_length(wfuncstate->args); | -
2946 | - | perfuncstate->winCollation = wfunc->inputcollid; | -
2947 | - |  | -
2948 | - | get_typlenbyval(wfunc->wintype, | -
2949 | - | &perfuncstate->resulttypeLen, | -
2950 | - | &perfuncstate->resulttypeByVal); | -
2951 | - |  | -
2952 | - | /* | -
2953 | - | * If it's really just a plain aggregate function, we'll emulate the | -
2954 | - | * Agg environment for it. | -
2955 | - | */ | -
2956 | - | perfuncstate->plain_agg = wfunc->winagg; | -
2957 | - | if (wfunc->winagg) | -
2958 | - | { | -
2959 | - | WindowStatePerAgg peraggstate; | -
2960 | - |  | -
2961 | - | perfuncstate->aggno = ++aggno; | -
2962 | - | peraggstate = &winstate->peragg[aggno]; | -
2963 | - | initialize_peragg(winstate, wfunc, peraggstate); | -
2964 | - | peraggstate->wfuncno = wfuncno; | -
2965 | - | } | -
2966 | - | else | -
2967 | - | { | -
2968 | - | WindowObject winobj = makeNode(WindowObjectData); | -
2969 | - |  | -
2970 | - | winobj->winstate = winstate; | -
2971 | - | winobj->argstates = wfuncstate->args; | -
2972 | - | winobj->localmem = NULL; | -
2973 | - | perfuncstate->winobj = winobj; | -
2974 | - | winobj->ignore_nulls = wfunc->ignore_nulls; | -
2975 | - | init_notnull_info(winobj, perfuncstate); | -
2976 | - |  | -
2977 | - | /* It's a real window function, so set up to call it. */ | -
2978 | - | fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo, | -
2979 | - | econtext->ecxt_per_query_memory); | -
2980 | - | fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo); | -
2981 | - | } | -
2982 | - | } | -
2983 | - |  | -
2984 | - | /* Update numfuncs, numaggs to match number of unique functions found */ | -
2985 | - | winstate->numfuncs = wfuncno + 1; | -
2986 | - | winstate->numaggs = aggno + 1; | -
2987 | - |  | -
2988 | - | /* Set up WindowObject for aggregates, if needed */ | -
2989 | - | if (winstate->numaggs > 0) | -
2990 | - | { | -
2991 | - | WindowObject agg_winobj = makeNode(WindowObjectData); | -
2992 | - |  | -
2993 | - | agg_winobj->winstate = winstate; | -
2994 | - | agg_winobj->argstates = NIL; | -
2995 | - | agg_winobj->localmem = NULL; | -
2996 | - | /* make sure markptr = -1 to invalidate. It may not get used */ | -
2997 | - | agg_winobj->markptr = -1; | -
2998 | - | agg_winobj->readptr = -1; | -
2999 | - | winstate->agg_winobj = agg_winobj; | -
3000 | - | } | -
3001 | - |  | -
3002 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3003 | - | * Set up WindowObject for RPR navigation opcodes. This is separate from | 24cfb8dRow pattern recognition patch (executor and commands).
3004 | - | * agg_winobj because it needs its own read pointer to avoid interfering | 24cfb8dRow pattern recognition patch (executor and commands).
3005 | - | * with aggregate processing. | 24cfb8dRow pattern recognition patch (executor and commands).
3006 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3007 | 4974 | if (node->rpPattern != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
3008 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3009 | 2996 | WindowObject nav_winobj = makeNode(WindowObjectData); | 24cfb8dRow pattern recognition patch (executor and commands).
3010 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3011 | 2996 | nav_winobj->winstate = winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
3012 | 2996 | nav_winobj->argstates = NIL; | 24cfb8dRow pattern recognition patch (executor and commands).
3013 | 2996 | nav_winobj->localmem = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
3014 | 2996 | nav_winobj->markptr = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
3015 | 2996 | nav_winobj->readptr = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
3016 | 2996 | winstate->nav_winobj = nav_winobj; | 24cfb8dRow pattern recognition patch (executor and commands).
3017 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3018 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3019 | - | /* Set the status to running */ | -
3020 | - | winstate->status = WINDOWAGG_RUN; | -
3021 | - |  | -
3022 | - | /* initialize frame bound offset expressions */ | -
3023 | - | winstate->startOffset = ExecInitExpr((Expr *) node->startOffset, | -
3024 | - | (PlanState *) winstate); | -
3025 | - | winstate->endOffset = ExecInitExpr((Expr *) node->endOffset, | -
3026 | - | (PlanState *) winstate); | -
3027 | - |  | -
3028 | - | /* Lookup in_range support functions if needed */ | -
3029 | - | if (OidIsValid(node->startInRangeFunc)) | -
3030 | - | fmgr_info(node->startInRangeFunc, &winstate->startInRangeFunc); | -
3031 | - | if (OidIsValid(node->endInRangeFunc)) | -
3032 | - | fmgr_info(node->endInRangeFunc, &winstate->endInRangeFunc); | -
3033 | - | winstate->inRangeColl = node->inRangeColl; | -
3034 | - | winstate->inRangeAsc = node->inRangeAsc; | -
3035 | - | winstate->inRangeNullsFirst = node->inRangeNullsFirst; | -
3036 | - |  | -
3037 | - | /* Set up SKIP TO type */ | 24cfb8dRow pattern recognition patch (executor and commands).
3038 | 4974 | winstate->rpSkipTo = node->rpSkipTo; | 24cfb8dRow pattern recognition patch (executor and commands).
3039 | - | /* Set up row pattern recognition PATTERN clause (compiled NFA) */ | 24cfb8dRow pattern recognition patch (executor and commands).
3040 | 4974 | winstate->rpPattern = node->rpPattern; | 24cfb8dRow pattern recognition patch (executor and commands).
3041 | - | /* Set up nav offsets for tuplestore trim; resolve any NEEDS_EVAL kinds */ | 24cfb8dRow pattern recognition patch (executor and commands).
3042 | 4974 | winstate->navMaxOffsetKind = node->navMaxOffsetKind; | 24cfb8dRow pattern recognition patch (executor and commands).
3043 | 4974 | winstate->navMaxOffset = node->navMaxOffset; | 24cfb8dRow pattern recognition patch (executor and commands).
3044 | 4974 | winstate->hasFirstNav = node->hasFirstNav; | 24cfb8dRow pattern recognition patch (executor and commands).
3045 | 4974 | winstate->navFirstOffsetKind = node->navFirstOffsetKind; | 24cfb8dRow pattern recognition patch (executor and commands).
3046 | 4974 | winstate->navFirstOffset = node->navFirstOffset; | 24cfb8dRow pattern recognition patch (executor and commands).
3047 | 4974 | eval_define_offsets(winstate, node->defineClause); | 24cfb8dRow pattern recognition patch (executor and commands).
3048 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3049 | - | /* Copy match_start dependency bitmapset for per-context evaluation */ | 24cfb8dRow pattern recognition patch (executor and commands).
3050 | 4974 | winstate->defineMatchStartDependent = bms_copy(node->defineMatchStartDependent); | 24cfb8dRow pattern recognition patch (executor and commands).
3051 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3052 | - | /* Calculate NFA state size and allocate cycle detection bitmap */ | 24cfb8dRow pattern recognition patch (executor and commands).
3053 | 4974 | if (node->rpPattern != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
3054 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3055 | 2996 | int nfaVisitedNWords; | 24cfb8dRow pattern recognition patch (executor and commands).
3056 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3057 | 2996 | winstate->nfaStateSize = offsetof(RPRNFAState, counts) + | 24cfb8dRow pattern recognition patch (executor and commands).
3058 | 2996 | sizeof(int32) * node->rpPattern->maxDepth; | 24cfb8dRow pattern recognition patch (executor and commands).
3059 | 2996 | nfaVisitedNWords = | 24cfb8dRow pattern recognition patch (executor and commands).
3060 | 2996 | (node->rpPattern->numElements - 1) / BITS_PER_BITMAPWORD + 1; | 24cfb8dRow pattern recognition patch (executor and commands).
3061 | 2996 | winstate->nfaVisitedElems = palloc0(sizeof(bitmapword) * | 24cfb8dRow pattern recognition patch (executor and commands).
3062 | - | nfaVisitedNWords); | 24cfb8dRow pattern recognition patch (executor and commands).
3063 | - | /* High-water mark sentinels: no bits set yet. */ | 24cfb8dRow pattern recognition patch (executor and commands).
3064 | 2996 | winstate->nfaVisitedMinWord = PG_INT16_MAX; | 24cfb8dRow pattern recognition patch (executor and commands).
3065 | 2996 | winstate->nfaVisitedMaxWord = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
3066 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3067 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3068 | - | /* Set up row pattern recognition DEFINE clause */ | 24cfb8dRow pattern recognition patch (executor and commands).
3069 | 4974 | winstate->defineVariableList = NIL; | 24cfb8dRow pattern recognition patch (executor and commands).
3070 | 4974 | winstate->defineClauseExprs = NIL; | b848408Tidy up row pattern recognition plumbing
3071 | - |  | b848408Tidy up row pattern recognition plumbing
3072 | - | /* | b848408Tidy up row pattern recognition plumbing
3073 | - | * Compile DEFINE clause expressions. PREV/NEXT navigation is handled by | b848408Tidy up row pattern recognition plumbing
3074 | - | * EEOP_RPR_NAV_SET/RESTORE opcodes emitted during ExecInitExpr, so no | b848408Tidy up row pattern recognition plumbing
3075 | - | * varno rewriting is needed here. | b848408Tidy up row pattern recognition plumbing
3076 | - | */ | b848408Tidy up row pattern recognition plumbing
3077 | 11922 | foreach_node(TargetEntry, te, node->defineClause) | b848408Tidy up row pattern recognition plumbing
3078 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3079 | 6948 | char *name = te->resname; | b848408Tidy up row pattern recognition plumbing
3080 | 6948 | ExprState *exprstate; | b848408Tidy up row pattern recognition plumbing
3081 | - |  | b848408Tidy up row pattern recognition plumbing
3082 | 13896 | winstate->defineVariableList = | b848408Tidy up row pattern recognition plumbing
3083 | 6948 | lappend(winstate->defineVariableList, | b848408Tidy up row pattern recognition plumbing
3084 | 6948 | makeString(pstrdup(name))); | b848408Tidy up row pattern recognition plumbing
3085 | - |  | b848408Tidy up row pattern recognition plumbing
3086 | 6948 | exprstate = ExecInitExpr(te->expr, (PlanState *) winstate); | b848408Tidy up row pattern recognition plumbing
3087 | - |  | b848408Tidy up row pattern recognition plumbing
3088 | 6948 | winstate->defineClauseExprs = | b848408Tidy up row pattern recognition plumbing
3089 | 6948 | lappend(winstate->defineClauseExprs, exprstate); | b848408Tidy up row pattern recognition plumbing
3090 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3091 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3092 | - | /* Initialize NFA free lists for row pattern matching */ | 24cfb8dRow pattern recognition patch (executor and commands).
3093 | 4974 | winstate->nfaContext = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
3094 | 4974 | winstate->nfaContextTail = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
3095 | 4974 | winstate->nfaContextFree = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
3096 | 4974 | winstate->nfaStateFree = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
3097 | 4974 | winstate->nfaLastProcessedRow = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
3098 | 4974 | winstate->nfaStatesActive = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
3099 | 4974 | winstate->nfaContextsActive = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
3100 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3101 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3102 | - | * Allocate varMatched array for NFA evaluation. With the new varNames | 24cfb8dRow pattern recognition patch (executor and commands).
3103 | - | * ordering (DEFINE order first), varId == defineIdx for all defined | 24cfb8dRow pattern recognition patch (executor and commands).
3104 | - | * variables, so no mapping is needed. | 24cfb8dRow pattern recognition patch (executor and commands).
3105 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3106 | 4974 | if (winstate->defineVariableList != NIL) | 4cf9108Further tidy up row pattern recognition plumbing
3107 | 2996 | winstate->nfaVarMatched = palloc0(sizeof(bool) * | 24cfb8dRow pattern recognition patch (executor and commands).
3108 | 2996 | list_length(winstate->defineVariableList)); | 24cfb8dRow pattern recognition patch (executor and commands).
3109 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3110 | 1978 | winstate->nfaVarMatched = NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
3111 | - | winstate->all_first = true; | -
3112 | - | winstate->partition_spooled = false; | -
3113 | - | winstate->more_partitions = false; | -
3114 | - | winstate->next_partition = true; | -
3115 | - |  | -
3116 | - | return winstate; | -
3117 | - | } | -

ExecRPRNavGetSlot() lines 3126-3152
Modified Lines Coverage: 11/11 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3126 | 983092 | ExecRPRNavGetSlot(WindowAggState *winstate, int64 pos) | 24cfb8dRow pattern recognition patch (executor and commands).
3127 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3128 | 983092 | WindowObject winobj = winstate->nav_winobj; | 24cfb8dRow pattern recognition patch (executor and commands).
3129 | 983092 | TupleTableSlot *slot = winstate->nav_slot; | 24cfb8dRow pattern recognition patch (executor and commands).
3130 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3131 | 983092 | if (pos < 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3132 | 22556 | return winstate->nav_null_slot; | 24cfb8dRow pattern recognition patch (executor and commands).
3133 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3134 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3135 | - | * If nav_slot already holds this position, return it without re-fetching. | 24cfb8dRow pattern recognition patch (executor and commands).
3136 | - | * This is critical when multiple PREV/NEXT calls in the same expression | 24cfb8dRow pattern recognition patch (executor and commands).
3137 | - | * navigate to the same row, because re-fetching would free the slot's | 24cfb8dRow pattern recognition patch (executor and commands).
3138 | - | * tuple memory and invalidate any pass-by-ref Datum pointers from earlier | 24cfb8dRow pattern recognition patch (executor and commands).
3139 | - | * navigation results. | 24cfb8dRow pattern recognition patch (executor and commands).
3140 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3141 | 960536 | if (winstate->nav_slot_pos == pos) | 24cfb8dRow pattern recognition patch (executor and commands).
3142 | - | return slot; | 24cfb8dRow pattern recognition patch (executor and commands).
3143 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3144 | 484480 | if (!window_gettupleslot(winobj, pos, slot)) | 24cfb8dRow pattern recognition patch (executor and commands).
3145 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3146 | 152 | winstate->nav_slot_pos = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
3147 | 152 | return winstate->nav_null_slot; | 24cfb8dRow pattern recognition patch (executor and commands).
3148 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3149 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3150 | 484328 | winstate->nav_slot_pos = pos; | 24cfb8dRow pattern recognition patch (executor and commands).
3151 | 484328 | return slot; | 24cfb8dRow pattern recognition patch (executor and commands).
3152 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

ExecReScanWindowAgg() lines 3195-3229
Modified Lines Coverage: 2/2 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3195 | - | ExecReScanWindowAgg(WindowAggState *node) | -
3196 | - | { | -
3197 | - | PlanState *outerPlan = outerPlanState(node); | -
3198 | - | ExprContext *econtext = node->ss.ps.ps_ExprContext; | -
3199 | - |  | -
3200 | - | node->status = WINDOWAGG_RUN; | -
3201 | - | node->all_first = true; | -
3202 | - |  | -
3203 | - | /* release tuplestore et al */ | -
3204 | - | release_partition(node); | -
3205 | - |  | -
3206 | - | /* release all temp tuples, but especially first_part_slot */ | -
3207 | - | ExecClearTuple(node->ss.ss_ScanTupleSlot); | -
3208 | - | ExecClearTuple(node->first_part_slot); | -
3209 | - | ExecClearTuple(node->agg_row_slot); | -
3210 | - | ExecClearTuple(node->temp_slot_1); | -
3211 | - | ExecClearTuple(node->temp_slot_2); | -
3212 | 108 | if (node->nav_slot) | 24cfb8dRow pattern recognition patch (executor and commands).
3213 | 56 | ExecClearTuple(node->nav_slot); | 24cfb8dRow pattern recognition patch (executor and commands).
3214 | - | if (node->framehead_slot) | -
3215 | - | ExecClearTuple(node->framehead_slot); | -
3216 | - | if (node->frametail_slot) | -
3217 | - | ExecClearTuple(node->frametail_slot); | -
3218 | - |  | -
3219 | - | /* Forget current wfunc values */ | -
3220 | - | MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numfuncs); | -
3221 | - | MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numfuncs); | -
3222 | - |  | -
3223 | - | /* | -
3224 | - | * if chgParam of subnode is not null then plan will be re-scanned by | -
3225 | - | * first ExecProcNode. | -
3226 | - | */ | -
3227 | - | if (outerPlan->chgParam == NULL) | -
3228 | - | ExecReScan(outerPlan); | -
3229 | - | } | -

window_gettupleslot() lines 3555-3639
Modified Lines Coverage: 0/1 lines (0.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3555 | - | window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot) | -
3556 | - | { | -
3557 | - | WindowAggState *winstate = winobj->winstate; | -
3558 | - | MemoryContext oldcontext; | -
3559 | - |  | -
3560 | - | /* often called repeatedly in a row */ | -
3561 | - | CHECK_FOR_INTERRUPTS(); | -
3562 | - |  | -
3563 | - | /* Don't allow passing -1 to spool_tuples here */ | -
3564 | - | if (pos < 0) | -
3565 | - | return false; | -
3566 | - |  | -
3567 | - | /* If necessary, fetch the tuple into the spool */ | -
3568 | - | spool_tuples(winstate, pos); | -
3569 | - |  | -
3570 | - | if (pos >= winstate->spooled_rows) | -
3571 | - | return false; | -
3572 | - |  | -
3573 | - | if (pos < winobj->markpos) | -
3574 | 0 | elog(ERROR, "cannot fetch row: " INT64_FORMAT " before WindowObject's mark position: " INT64_FORMAT, | 24cfb8dRow pattern recognition patch (executor and commands).
3575 | - | pos, winobj->markpos); | 24cfb8dRow pattern recognition patch (executor and commands).
3576 | - |  | -
3577 | - | oldcontext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_query_memory); | -
3578 | - |  | -
3579 | - | tuplestore_select_read_pointer(winstate->buffer, winobj->readptr); | -
3580 | - |  | -
3581 | - | /* | -
3582 | - | * Advance or rewind until we are within one tuple of the one we want. | -
3583 | - | */ | -
3584 | - | if (winobj->seekpos < pos - 1) | -
3585 | - | { | -
3586 | - | if (!tuplestore_skiptuples(winstate->buffer, | -
3587 | - | pos - 1 - winobj->seekpos, | -
3588 | - | true)) | -
3589 | - | elog(ERROR, "unexpected end of tuplestore"); | -
3590 | - | winobj->seekpos = pos - 1; | -
3591 | - | } | -
3592 | - | else if (winobj->seekpos > pos + 1) | -
3593 | - | { | -
3594 | - | if (!tuplestore_skiptuples(winstate->buffer, | -
3595 | - | winobj->seekpos - (pos + 1), | -
3596 | - | false)) | -
3597 | - | elog(ERROR, "unexpected end of tuplestore"); | -
3598 | - | winobj->seekpos = pos + 1; | -
3599 | - | } | -
3600 | - | else if (winobj->seekpos == pos) | -
3601 | - | { | -
3602 | - | /* | -
3603 | - | * There's no API to refetch the tuple at the current position. We | -
3604 | - | * have to move one tuple forward, and then one backward. (We don't | -
3605 | - | * do it the other way because we might try to fetch the row before | -
3606 | - | * our mark, which isn't allowed.) XXX this case could stand to be | -
3607 | - | * optimized. | -
3608 | - | */ | -
3609 | - | tuplestore_advance(winstate->buffer, true); | -
3610 | - | winobj->seekpos++; | -
3611 | - | } | -
3612 | - |  | -
3613 | - | /* | -
3614 | - | * Now we should be on the tuple immediately before or after the one we | -
3615 | - | * want, so just fetch forwards or backwards as appropriate. | -
3616 | - | * | -
3617 | - | * Notice that we tell tuplestore_gettupleslot to make a physical copy of | -
3618 | - | * the fetched tuple. This ensures that the slot's contents remain valid | -
3619 | - | * through manipulations of the tuplestore, which some callers depend on. | -
3620 | - | */ | -
3621 | - | if (winobj->seekpos > pos) | -
3622 | - | { | -
3623 | - | if (!tuplestore_gettupleslot(winstate->buffer, false, true, slot)) | -
3624 | - | elog(ERROR, "unexpected end of tuplestore"); | -
3625 | - | winobj->seekpos--; | -
3626 | - | } | -
3627 | - | else | -
3628 | - | { | -
3629 | - | if (!tuplestore_gettupleslot(winstate->buffer, true, true, slot)) | -
3630 | - | elog(ERROR, "unexpected end of tuplestore"); | -
3631 | - | winobj->seekpos++; | -
3632 | - | } | -
3633 | - |  | -
3634 | - | Assert(winobj->seekpos == pos); | -
3635 | - |  | -
3636 | - | MemoryContextSwitchTo(oldcontext); | -
3637 | - |  | -
3638 | - | return true; | -
3639 | - | } | -

ignorenulls_getfuncarginframe() lines 3680-3856
Modified Lines Coverage: 15/16 lines (93.8%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3680 | - | ignorenulls_getfuncarginframe(WindowObject winobj, int argno, | -
3681 | - | int relpos, int seektype, bool set_mark, | -
3682 | - | bool *isnull, bool *isout) | -
3683 | - | { | -
3684 | - | WindowAggState *winstate; | -
3685 | - | ExprContext *econtext; | -
3686 | - | TupleTableSlot *slot; | -
3687 | - | Datum datum; | -
3688 | - | int64 abs_pos; | -
3689 | - | int64 mark_pos; | -
3690 | - | int notnull_offset; | -
3691 | - | int notnull_relpos; | -
3692 | - | int forward; | -
3693 | 1088 | int64 num_reduced_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
3694 | - |  | -
3695 | - | Assert(WindowObjectIsValid(winobj)); | -
3696 | - | winstate = winobj->winstate; | -
3697 | - | econtext = winstate->ss.ps.ps_ExprContext; | -
3698 | - | slot = winstate->temp_slot_1; | -
3699 | - | datum = (Datum) 0; | -
3700 | - | notnull_offset = 0; | -
3701 | - | notnull_relpos = abs(relpos); | -
3702 | - |  | -
3703 | - | switch (seektype) | -
3704 | - | { | -
3705 | - | case WINDOW_SEEK_CURRENT: | -
3706 | - | elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame"); | -
3707 | - | abs_pos = mark_pos = 0; /* keep compiler quiet */ | -
3708 | - | break; | -
3709 | - | case WINDOW_SEEK_HEAD: | -
3710 | - | /* rejecting relpos < 0 is easy and simplifies code below */ | -
3711 | - | if (relpos < 0) | -
3712 | - | goto out_of_frame; | -
3713 | - | update_frameheadpos(winstate); | -
3714 | - | abs_pos = winstate->frameheadpos; | -
3715 | - | mark_pos = winstate->frameheadpos; | -
3716 | - | forward = 1; | -
3717 | - | break; | -
3718 | - | case WINDOW_SEEK_TAIL: | -
3719 | - | /* rejecting relpos > 0 is easy and simplifies code below */ | -
3720 | - | if (relpos > 0) | -
3721 | - | goto out_of_frame; | -
3722 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3723 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3724 | - | * RPR cares about frame head pos. Need to call | 24cfb8dRow pattern recognition patch (executor and commands).
3725 | - | * update_frameheadpos | 24cfb8dRow pattern recognition patch (executor and commands).
3726 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3727 | 308 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
3728 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3729 | - | update_frametailpos(winstate); | -
3730 | - | abs_pos = winstate->frametailpos - 1; | -
3731 | - | mark_pos = 0; /* keep compiler quiet */ | -
3732 | - | forward = -1; | -
3733 | - | break; | -
3734 | - | default: | -
3735 | - | elog(ERROR, "unrecognized window seek type: %d", seektype); | -
3736 | - | abs_pos = mark_pos = 0; /* keep compiler quiet */ | -
3737 | - | break; | -
3738 | - | } | -
3739 | - |  | -
3740 | - | /* | -
3741 | - | * Get the next nonnull value in the frame, moving forward or backward | -
3742 | - | * until we find a value or reach the frame's end. | -
3743 | - | */ | -
3744 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3745 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3746 | - | * Check whether current row is in reduced frame. | 24cfb8dRow pattern recognition patch (executor and commands).
3747 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3748 | 1088 | num_reduced_frame = row_is_in_reduced_frame(winobj, winstate->frameheadpos); | 24cfb8dRow pattern recognition patch (executor and commands).
3749 | 1088 | if (num_reduced_frame < 0) /* unmatched or skipped row */ | 24cfb8dRow pattern recognition patch (executor and commands).
3750 | 320 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
3751 | 768 | else if (num_reduced_frame > 0) /* the first row of the reduced frame */ | 24cfb8dRow pattern recognition patch (executor and commands).
3752 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3753 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3754 | - | * Early check if row could be out of reduced frame. When RPR is | 24cfb8dRow pattern recognition patch (executor and commands).
3755 | - | * enabled, EXCLUDE clause cannot be specified and the frame is always | 24cfb8dRow pattern recognition patch (executor and commands).
3756 | - | * contiguous. So we can safely perform the following checks. Note, | 24cfb8dRow pattern recognition patch (executor and commands).
3757 | - | * however, it is possible that a row is out of reduced frame if | 24cfb8dRow pattern recognition patch (executor and commands).
3758 | - | * there's a NULL in the middle. So we need to check it in the | 24cfb8dRow pattern recognition patch (executor and commands).
3759 | - | * following do loop. | 24cfb8dRow pattern recognition patch (executor and commands).
3760 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3761 | 88 | if (seektype == WINDOW_SEEK_HEAD && relpos >= num_reduced_frame) | 24cfb8dRow pattern recognition patch (executor and commands).
3762 | 16 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
3763 | 72 | if (seektype == WINDOW_SEEK_TAIL) | 24cfb8dRow pattern recognition patch (executor and commands).
3764 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3765 | 24 | if (notnull_relpos >= num_reduced_frame) | 24cfb8dRow pattern recognition patch (executor and commands).
3766 | 0 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
3767 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3768 | - | /* not out of reduced frame. Set abspos as a starting point */ | 24cfb8dRow pattern recognition patch (executor and commands).
3769 | 24 | abs_pos = winstate->frameheadpos + num_reduced_frame - 1; | 24cfb8dRow pattern recognition patch (executor and commands).
3770 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3771 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3772 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3773 | - | do | -
3774 | - | { | -
3775 | - | int inframe; | -
3776 | - | int v; | -
3777 | - |  | -
3778 | - | /* | -
3779 | - | * Check apparent out of frame case. We need to do this because we | -
3780 | - | * may not call window_gettupleslot before row_is_in_frame, which | -
3781 | - | * supposes abs_pos is never negative. | -
3782 | - | */ | -
3783 | - | if (abs_pos < 0) | -
3784 | - | goto out_of_frame; | -
3785 | - |  | -
3786 | - | /* check whether row is in frame */ | -
3787 | - | inframe = row_is_in_frame(winobj, abs_pos, slot, true); | -
3788 | - | if (inframe == -1) | -
3789 | - | goto out_of_frame; | -
3790 | - | else if (inframe == 0) | -
3791 | - | goto advance; | -
3792 | - |  | -
3793 | - | if (isout) | -
3794 | - | *isout = false; | -
3795 | - |  | -
3796 | - | v = get_notnull_info(winobj, abs_pos, argno); | -
3797 | - | if (v == NN_NULL) /* this row is known to be NULL */ | -
3798 | - | goto advance; | -
3799 | - |  | -
3800 | - | else if (v == NN_UNKNOWN) /* need to check NULL or not */ | -
3801 | - | { | -
3802 | - | if (!window_gettupleslot(winobj, abs_pos, slot)) | -
3803 | - | goto out_of_frame; | -
3804 | - |  | -
3805 | - | econtext->ecxt_outertuple = slot; | -
3806 | - | datum = ExecEvalExpr( | -
3807 | - | (ExprState *) list_nth(winobj->argstates, | -
3808 | - | argno), econtext, | -
3809 | - | isnull); | -
3810 | - | if (!*isnull) | -
3811 | - | notnull_offset++; | -
3812 | - |  | -
3813 | - | /* record the row status */ | -
3814 | - | put_notnull_info(winobj, abs_pos, argno, *isnull); | -
3815 | - | } | -
3816 | - | else /* this row is known to be NOT NULL */ | -
3817 | - | { | -
3818 | - | notnull_offset++; | -
3819 | - | if (notnull_offset > notnull_relpos) | -
3820 | - | { | -
3821 | - | /* to prepare exiting this loop, datum needs to be set */ | -
3822 | - | if (!window_gettupleslot(winobj, abs_pos, slot)) | -
3823 | - | goto out_of_frame; | -
3824 | - |  | -
3825 | - | econtext->ecxt_outertuple = slot; | -
3826 | - | datum = ExecEvalExpr( | -
3827 | - | (ExprState *) list_nth | -
3828 | - | (winobj->argstates, argno), | -
3829 | - | econtext, isnull); | -
3830 | - | } | -
3831 | - | } | -
3832 | - | advance: | -
3833 | - | abs_pos += forward; | -
3834 | 1664 | if (rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
3835 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3836 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3837 | - | * Check whether we are still in the reduced frame. (also check | 24cfb8dRow pattern recognition patch (executor and commands).
3838 | - | * if we succeeded in getting the target row). | 24cfb8dRow pattern recognition patch (executor and commands).
3839 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3840 | 136 | num_reduced_frame--; | 24cfb8dRow pattern recognition patch (executor and commands).
3841 | 136 | if (num_reduced_frame <= 0 && notnull_offset <= notnull_relpos) | 24cfb8dRow pattern recognition patch (executor and commands).
3842 | 12 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
3843 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3844 | - | } while (notnull_offset <= notnull_relpos); | -
3845 | - |  | -
3846 | - | if (set_mark) | -
3847 | - | WinSetMarkPosition(winobj, mark_pos); | -
3848 | - |  | -
3849 | - | return datum; | -
3850 | - |  | -
3851 | - | out_of_frame: | -
3852 | - | if (isout) | -
3853 | - | *isout = true; | -
3854 | - | *isnull = true; | -
3855 | - | return (Datum) 0; | -
3856 | - | } | -

eval_nav_offset_helper() lines 3999-4022
Modified Lines Coverage: 13/14 lines (92.9%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3999 | 36 | eval_nav_offset_helper(WindowAggState *winstate, Expr *offset_expr, | 24cfb8dRow pattern recognition patch (executor and commands).
4000 | - | int64 defaultOffset) | 24cfb8dRow pattern recognition patch (executor and commands).
4001 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4002 | 36 | ExprContext *econtext = winstate->ss.ps.ps_ExprContext; | 24cfb8dRow pattern recognition patch (executor and commands).
4003 | 36 | ExprState *estate; | 24cfb8dRow pattern recognition patch (executor and commands).
4004 | 36 | Datum val; | 24cfb8dRow pattern recognition patch (executor and commands).
4005 | 36 | bool isnull; | 24cfb8dRow pattern recognition patch (executor and commands).
4006 | 36 | int64 offset; | 24cfb8dRow pattern recognition patch (executor and commands).
4007 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4008 | 36 | if (offset_expr == NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
4009 | 36 | return defaultOffset; | 24cfb8dRow pattern recognition patch (executor and commands).
4010 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4011 | 36 | estate = ExecInitExpr(offset_expr, (PlanState *) winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4012 | 36 | val = ExecEvalExprSwitchContext(estate, econtext, &isnull); | 24cfb8dRow pattern recognition patch (executor and commands).
4013 | - |  | 95b07bcSupport window functions a la SQL:2008.
4014 | 36 | if (isnull) | 24cfb8dRow pattern recognition patch (executor and commands).
4015 | - | return 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4016 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4017 | 36 | offset = DatumGetInt64(val); | 24cfb8dRow pattern recognition patch (executor and commands).
4018 | 36 | if (offset < 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4019 | 0 | return 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4020 | - |  | -
4021 | - | return offset; | 24cfb8dRow pattern recognition patch (executor and commands).
4022 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

DatumGetInt64() lines 4017-4032
Modified Lines Coverage: 2/3 lines (66.7%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4017 | 36 | offset = DatumGetInt64(val); | 24cfb8dRow pattern recognition patch (executor and commands).
4018 | 36 | if (offset < 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4019 | 0 | return 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4020 | - |  | -
4021 | - | return offset; | 24cfb8dRow pattern recognition patch (executor and commands).
4022 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4023 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4024 | - | typedef struct | 24cfb8dRow pattern recognition patch (executor and commands).
4025 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4026 | - | WindowAggState *winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4027 | - | int64 maxOffset; /* max backward-reach offset across all nav | 24cfb8dRow pattern recognition patch (executor and commands).
4028 | - | * exprs */ | 24cfb8dRow pattern recognition patch (executor and commands).
4029 | - | bool maxOverflow; /* true if backward-reach overflow detected */ | 24cfb8dRow pattern recognition patch (executor and commands).
4030 | - | int64 minFirstOffset; /* min forward-from-match_start offset; may be | 24cfb8dRow pattern recognition patch (executor and commands).
4031 | - | * negative (PREV_FIRST: inner - outer < 0) */ | 24cfb8dRow pattern recognition patch (executor and commands).
4032 | - | } EvalDefineOffsetsContext; | 24cfb8dRow pattern recognition patch (executor and commands).

visit_nav_exec() lines 4054-4150
Modified Lines Coverage: 28/35 lines (80.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4054 | 24 | visit_nav_exec(NavTraversal *t, RPRNavExpr *nav) | 24cfb8dRow pattern recognition patch (executor and commands).
4055 | - | { | -
4056 | 24 | EvalDefineOffsetsContext *context = (EvalDefineOffsetsContext *) t->data; | 24cfb8dRow pattern recognition patch (executor and commands).
4057 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4058 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4059 | - | * Parser guarantee (mirrors visit_nav_plan): nav's direct children are | 24cfb8dRow pattern recognition patch (executor and commands).
4060 | - | * never RPRNavExpr -- compound nesting is flattened in place and any | 24cfb8dRow pattern recognition patch (executor and commands).
4061 | - | * other nesting is rejected. Outer-kind dispatch is sufficient. | 24cfb8dRow pattern recognition patch (executor and commands).
4062 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4063 | 24 | Assert(nav->arg == NULL || !IsA(nav->arg, RPRNavExpr)); | 24cfb8dRow pattern recognition patch (executor and commands).
4064 | 24 | Assert(nav->offset_arg == NULL || !IsA(nav->offset_arg, RPRNavExpr)); | 24cfb8dRow pattern recognition patch (executor and commands).
4065 | 24 | Assert(nav->compound_offset_arg == NULL || | 24cfb8dRow pattern recognition patch (executor and commands).
4066 | - | !IsA(nav->compound_offset_arg, RPRNavExpr)); | 24cfb8dRow pattern recognition patch (executor and commands).
4067 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4068 | - | /* Backward reach: PREV, LAST-with-offset */ | 24cfb8dRow pattern recognition patch (executor and commands).
4069 | 24 | if (!context->maxOverflow) | 24cfb8dRow pattern recognition patch (executor and commands).
4070 | - | { | -
4071 | 24 | int64 reach = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4072 | 24 | bool gotReach = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4073 | - |  | -
4074 | 24 | if (nav->kind == RPR_NAV_PREV) | 24cfb8dRow pattern recognition patch (executor and commands).
4075 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4076 | 12 | reach = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4077 | - | nav->offset_arg, 1); | 24cfb8dRow pattern recognition patch (executor and commands).
4078 | - | gotReach = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4079 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4080 | 12 | else if (nav->kind == RPR_NAV_LAST && nav->offset_arg != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
4081 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4082 | 0 | reach = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4083 | - | nav->offset_arg, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
4084 | - | gotReach = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4085 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4086 | 12 | else if (nav->kind == RPR_NAV_PREV_LAST || | 24cfb8dRow pattern recognition patch (executor and commands).
4087 | - | nav->kind == RPR_NAV_NEXT_LAST) | 24cfb8dRow pattern recognition patch (executor and commands).
4088 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4089 | 8 | int64 inner = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4090 | - | nav->offset_arg, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
4091 | 8 | int64 outer = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4092 | - | nav->compound_offset_arg, 1); | 24cfb8dRow pattern recognition patch (executor and commands).
4093 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4094 | 8 | if (nav->kind == RPR_NAV_PREV_LAST) | 24cfb8dRow pattern recognition patch (executor and commands).
4095 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4096 | 8 | if (pg_add_s64_overflow(inner, outer, &reach)) | 24cfb8dRow pattern recognition patch (executor and commands).
4097 | 8 | context->maxOverflow = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4098 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4099 | - | gotReach = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4100 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4101 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4102 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4103 | 0 | reach = Max(inner - outer, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
4104 | 0 | gotReach = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4105 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4106 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4107 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4108 | 8 | if (gotReach) | 24cfb8dRow pattern recognition patch (executor and commands).
4109 | 12 | context->maxOffset = Max(context->maxOffset, reach); | 24cfb8dRow pattern recognition patch (executor and commands).
4110 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4111 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4112 | - | /* Forward reach from match_start: FIRST, compound PREV_FIRST/NEXT_FIRST */ | 24cfb8dRow pattern recognition patch (executor and commands).
4113 | 24 | if (nav->kind == RPR_NAV_FIRST) | 24cfb8dRow pattern recognition patch (executor and commands).
4114 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4115 | 0 | int64 reach; | 24cfb8dRow pattern recognition patch (executor and commands).
4116 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4117 | 0 | reach = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4118 | - | nav->offset_arg, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
4119 | 0 | context->minFirstOffset = Min(context->minFirstOffset, reach); | 24cfb8dRow pattern recognition patch (executor and commands).
4120 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4121 | 24 | else if (nav->kind == RPR_NAV_PREV_FIRST || | 24cfb8dRow pattern recognition patch (executor and commands).
4122 | - | nav->kind == RPR_NAV_NEXT_FIRST) | 24cfb8dRow pattern recognition patch (executor and commands).
4123 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4124 | 4 | int64 inner = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4125 | - | nav->offset_arg, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
4126 | 4 | int64 outer = eval_nav_offset_helper(context->winstate, | 24cfb8dRow pattern recognition patch (executor and commands).
4127 | - | nav->compound_offset_arg, 1); | 24cfb8dRow pattern recognition patch (executor and commands).
4128 | 4 | int64 reach; | 24cfb8dRow pattern recognition patch (executor and commands).
4129 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4130 | 4 | if (nav->kind == RPR_NAV_PREV_FIRST) | 24cfb8dRow pattern recognition patch (executor and commands).
4131 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4132 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4133 | - | * reach = inner - outer. Both are non-negative, so the result >= | 24cfb8dRow pattern recognition patch (executor and commands).
4134 | - | * -PG_INT64_MAX, which cannot underflow int64. | 24cfb8dRow pattern recognition patch (executor and commands).
4135 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4136 | 0 | reach = inner - outer; | 24cfb8dRow pattern recognition patch (executor and commands).
4137 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4138 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4139 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4140 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4141 | - | * NEXT_FIRST: reach = inner + outer. This can overflow, but the | 24cfb8dRow pattern recognition patch (executor and commands).
4142 | - | * result is always >= 0, so it never updates minFirstOffset | 24cfb8dRow pattern recognition patch (executor and commands).
4143 | - | * (which tracks the minimum). Clamp to PG_INT64_MAX on overflow. | 24cfb8dRow pattern recognition patch (executor and commands).
4144 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4145 | 4 | if (pg_add_s64_overflow(inner, outer, &reach)) | 24cfb8dRow pattern recognition patch (executor and commands).
4146 | 4 | reach = PG_INT64_MAX; | 24cfb8dRow pattern recognition patch (executor and commands).
4147 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4148 | 4 | context->minFirstOffset = Min(context->minFirstOffset, reach); | 24cfb8dRow pattern recognition patch (executor and commands).
4149 | - | } | -
4150 | - | } | -

eval_define_offsets() lines 4166-4212
Modified Lines Coverage: 26/27 lines (96.3%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4166 | 4974 | eval_define_offsets(WindowAggState *winstate, List *defineClause) | 24cfb8dRow pattern recognition patch (executor and commands).
4167 | - | { | -
4168 | 4974 | EvalDefineOffsetsContext ctx; | 24cfb8dRow pattern recognition patch (executor and commands).
4169 | 4974 | NavTraversal trav; | 24cfb8dRow pattern recognition patch (executor and commands).
4170 | 4974 | bool needsMax = (winstate->navMaxOffsetKind == RPR_NAV_OFFSET_NEEDS_EVAL); | 24cfb8dRow pattern recognition patch (executor and commands).
4171 | 4974 | bool needsFirst = (winstate->hasFirstNav && | 24cfb8dRow pattern recognition patch (executor and commands).
4172 | 136 | winstate->navFirstOffsetKind == RPR_NAV_OFFSET_NEEDS_EVAL); | 24cfb8dRow pattern recognition patch (executor and commands).
4173 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4174 | 4974 | if (!needsMax && !needsFirst) | 24cfb8dRow pattern recognition patch (executor and commands).
4175 | 4950 | return; | 24cfb8dRow pattern recognition patch (executor and commands).
4176 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4177 | 24 | ctx.winstate = winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4178 | 24 | ctx.maxOffset = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4179 | 24 | ctx.maxOverflow = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4180 | 24 | ctx.minFirstOffset = PG_INT64_MAX; | 24cfb8dRow pattern recognition patch (executor and commands).
4181 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4182 | 24 | trav.visit = visit_nav_exec; | 24cfb8dRow pattern recognition patch (executor and commands).
4183 | 24 | trav.data = &ctx; | 24cfb8dRow pattern recognition patch (executor and commands).
4184 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4185 | 48 | foreach_node(TargetEntry, te, defineClause) | 24cfb8dRow pattern recognition patch (executor and commands).
4186 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4187 | 24 | nav_traversal_walker((Node *) te->expr, &trav); | 24cfb8dRow pattern recognition patch (executor and commands).
4188 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4189 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4190 | 24 | if (needsMax) | 24cfb8dRow pattern recognition patch (executor and commands).
4191 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4192 | 20 | if (ctx.maxOverflow) | 24cfb8dRow pattern recognition patch (executor and commands).
4193 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4194 | 8 | winstate->navMaxOffsetKind = RPR_NAV_OFFSET_RETAIN_ALL; | 24cfb8dRow pattern recognition patch (executor and commands).
4195 | 8 | winstate->navMaxOffset = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4196 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4197 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4198 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4199 | 12 | winstate->navMaxOffsetKind = RPR_NAV_OFFSET_FIXED; | 24cfb8dRow pattern recognition patch (executor and commands).
4200 | 12 | winstate->navMaxOffset = ctx.maxOffset; | 24cfb8dRow pattern recognition patch (executor and commands).
4201 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4202 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4203 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4204 | 24 | if (needsFirst) | 24cfb8dRow pattern recognition patch (executor and commands).
4205 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4206 | 4 | winstate->navFirstOffsetKind = RPR_NAV_OFFSET_FIXED; | 24cfb8dRow pattern recognition patch (executor and commands).
4207 | 4 | if (ctx.minFirstOffset < PG_INT64_MAX) | 24cfb8dRow pattern recognition patch (executor and commands).
4208 | 0 | winstate->navFirstOffset = ctx.minFirstOffset; | 24cfb8dRow pattern recognition patch (executor and commands).
4209 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4210 | 4 | winstate->navFirstOffset = PG_INT64_MAX; | 24cfb8dRow pattern recognition patch (executor and commands).
4211 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4212 | - | } | -

rpr_is_defined() lines 4219-4222
Modified Lines Coverage: 2/2 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4219 | 8909011 | rpr_is_defined(WindowAggState *winstate) | 24cfb8dRow pattern recognition patch (executor and commands).
4220 | - | { | -
4221 | 8909011 | return winstate->rpPattern != NULL; | 24cfb8dRow pattern recognition patch (executor and commands).
4222 | - | } | -

row_is_in_reduced_frame() lines 4243-4291
Modified Lines Coverage: 18/20 lines (90.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4243 | 4355848 | row_is_in_reduced_frame(WindowObject winobj, int64 pos) | 24cfb8dRow pattern recognition patch (executor and commands).
4244 | - | { | -
4245 | 4355848 | WindowAggState *winstate = winobj->winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4246 | 4355848 | int state; | 24cfb8dRow pattern recognition patch (executor and commands).
4247 | 4355848 | int64 rtn; | 24cfb8dRow pattern recognition patch (executor and commands).
4248 | - |  | -
4249 | 4355848 | if (!rpr_is_defined(winstate)) | 24cfb8dRow pattern recognition patch (executor and commands).
4250 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4251 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4252 | - | * RPR is not defined. Assume that we are always in the reduced window | 24cfb8dRow pattern recognition patch (executor and commands).
4253 | - | * frame. | 24cfb8dRow pattern recognition patch (executor and commands).
4254 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4255 | 4355788 | rtn = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4256 | - | return rtn; | 24cfb8dRow pattern recognition patch (executor and commands).
4257 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4258 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4259 | 4349196 | state = get_reduced_frame_status(winstate, pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4260 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4261 | 4349196 | if (state == RF_NOT_DETERMINED) | 24cfb8dRow pattern recognition patch (executor and commands).
4262 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4263 | 129804 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4264 | 129804 | update_reduced_frame(winobj, pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4265 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4266 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4267 | 4349136 | state = get_reduced_frame_status(winstate, pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4268 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4269 | 4349136 | switch (state) | 24cfb8dRow pattern recognition patch (executor and commands).
4270 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4271 | 81396 | case RF_FRAME_HEAD: | 24cfb8dRow pattern recognition patch (executor and commands).
4272 | 81396 | rtn = winstate->rpr_match_length; | 24cfb8dRow pattern recognition patch (executor and commands).
4273 | 81396 | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4274 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4275 | - | case RF_SKIPPED: | 24cfb8dRow pattern recognition patch (executor and commands).
4276 | - | rtn = -2; | 24cfb8dRow pattern recognition patch (executor and commands).
4277 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4278 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4279 | 469588 | case RF_UNMATCHED: | 24cfb8dRow pattern recognition patch (executor and commands).
4280 | - | case RF_EMPTY_MATCH: | 24cfb8dRow pattern recognition patch (executor and commands).
4281 | 469588 | rtn = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
4282 | 469588 | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4283 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4284 | 0 | default: | 24cfb8dRow pattern recognition patch (executor and commands).
4285 | 0 | elog(ERROR, "unrecognized state: %d at: " INT64_FORMAT, | 24cfb8dRow pattern recognition patch (executor and commands).
4286 | - | state, pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4287 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4288 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4289 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4290 | - | return rtn; | 24cfb8dRow pattern recognition patch (executor and commands).
4291 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

clear_reduced_frame() lines 4298-4304
Modified Lines Coverage: 6/6 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4298 | 34977 | clear_reduced_frame(WindowAggState *winstate) | 24cfb8dRow pattern recognition patch (executor and commands).
4299 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4300 | 34977 | winstate->rpr_match_valid = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4301 | 34977 | winstate->rpr_match_matched = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4302 | 34977 | winstate->rpr_match_start = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
4303 | 34977 | winstate->rpr_match_length = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4304 | 34977 | } | 24cfb8dRow pattern recognition patch (executor and commands).

get_reduced_frame_status() lines 4327-4364
Modified Lines Coverage: 9/9 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4327 | 14177520 | get_reduced_frame_status(WindowAggState *winstate, int64 pos) | 24cfb8dRow pattern recognition patch (executor and commands).
4328 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4329 | 14177520 | int64 start = winstate->rpr_match_start; | 24cfb8dRow pattern recognition patch (executor and commands).
4330 | 14177520 | int64 length = winstate->rpr_match_length; | 24cfb8dRow pattern recognition patch (executor and commands).
4331 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4332 | 14177520 | if (!winstate->rpr_match_valid) | 24cfb8dRow pattern recognition patch (executor and commands).
4333 | - | return RF_NOT_DETERMINED; | 24cfb8dRow pattern recognition patch (executor and commands).
4334 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4335 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4336 | - | * By here the record is valid and holds one of the three shapes above. | 24cfb8dRow pattern recognition patch (executor and commands).
4337 | - | * | 24cfb8dRow pattern recognition patch (executor and commands).
4338 | - | * The empty match (true, 0) must be classified first: it has length 0, so | 24cfb8dRow pattern recognition patch (executor and commands).
4339 | - | * the range test below would compute start + length == start and reject | 24cfb8dRow pattern recognition patch (executor and commands).
4340 | - | * its own start position as out of range. | 24cfb8dRow pattern recognition patch (executor and commands).
4341 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4342 | 14160300 | if (pos == start && winstate->rpr_match_matched && length == 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4343 | - | return RF_EMPTY_MATCH; | 24cfb8dRow pattern recognition patch (executor and commands).
4344 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4345 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4346 | - | * By here length >= 1 -- the only zero-length record, the empty match, | 24cfb8dRow pattern recognition patch (executor and commands).
4347 | - | * has been handled -- so [start, start + length) is a well-formed range. | 24cfb8dRow pattern recognition patch (executor and commands).
4348 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4349 | 14158148 | if (pos < start || pos >= start + length) | 24cfb8dRow pattern recognition patch (executor and commands).
4350 | - | return RF_NOT_DETERMINED; | 24cfb8dRow pattern recognition patch (executor and commands).
4351 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4352 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4353 | - | * By here pos lies within [start, start + length). An unmatched record | 24cfb8dRow pattern recognition patch (executor and commands).
4354 | - | * is (false, 1), so this returns for its single in-range position. | 24cfb8dRow pattern recognition patch (executor and commands).
4355 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4356 | 14013972 | if (!winstate->rpr_match_matched) | 24cfb8dRow pattern recognition patch (executor and commands).
4357 | - | return RF_UNMATCHED; | 24cfb8dRow pattern recognition patch (executor and commands).
4358 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4359 | - | /* By here the match is real (true, >= 1) and pos is one of its rows. */ | 24cfb8dRow pattern recognition patch (executor and commands).
4360 | 12993484 | if (pos == start) | 24cfb8dRow pattern recognition patch (executor and commands).
4361 | 1113204 | return RF_FRAME_HEAD; | 24cfb8dRow pattern recognition patch (executor and commands).
4362 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4363 | - | return RF_SKIPPED; | 24cfb8dRow pattern recognition patch (executor and commands).
4364 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

advance_nav_mark() lines 4380-4419
Modified Lines Coverage: 14/14 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4380 | 988588 | advance_nav_mark(WindowAggState *winstate, int64 currentPos) | 0ed285dDrive RPR row pattern matching once per row
4381 | - | { | 0ed285dDrive RPR row pattern matching once per row
4382 | 988588 | int64 navmarkpos; | 0ed285dDrive RPR row pattern matching once per row
4383 | - |  | 0ed285dDrive RPR row pattern matching once per row
4384 | - | /* No RPR navigation read pointer: nothing to advance */ | 0ed285dDrive RPR row pattern matching once per row
4385 | 988588 | if (winstate->nav_winobj == NULL) | 0ed285dDrive RPR row pattern matching once per row
4386 | - | return; | 0ed285dDrive RPR row pattern matching once per row
4387 | - |  | 0ed285dDrive RPR row pattern matching once per row
4388 | - | /* RETAIN_ALL disables trim for the backward (PREV/LAST) dimension */ | 0ed285dDrive RPR row pattern matching once per row
4389 | 988588 | if (winstate->navMaxOffsetKind == RPR_NAV_OFFSET_RETAIN_ALL) | 0ed285dDrive RPR row pattern matching once per row
4390 | - | return; | 0ed285dDrive RPR row pattern matching once per row
4391 | - |  | 0ed285dDrive RPR row pattern matching once per row
4392 | - | /* navMax is FIXED here: NEEDS_EVAL resolved, RETAIN_ALL returned */ | 0ed285dDrive RPR row pattern matching once per row
4393 | 988548 | Assert(winstate->navMaxOffsetKind == RPR_NAV_OFFSET_FIXED); | 0ed285dDrive RPR row pattern matching once per row
4394 | - |  | 0ed285dDrive RPR row pattern matching once per row
4395 | 988548 | if (currentPos > winstate->navMaxOffset) | 0ed285dDrive RPR row pattern matching once per row
4396 | 966164 | navmarkpos = currentPos - winstate->navMaxOffset; | 0ed285dDrive RPR row pattern matching once per row
4397 | - | else | 0ed285dDrive RPR row pattern matching once per row
4398 | - | navmarkpos = 0; | 0ed285dDrive RPR row pattern matching once per row
4399 | - |  | 0ed285dDrive RPR row pattern matching once per row
4400 | 988548 | if (winstate->hasFirstNav && winstate->nfaContext != NULL) | 0ed285dDrive RPR row pattern matching once per row
4401 | - | { | 0ed285dDrive RPR row pattern matching once per row
4402 | 5848 | int64 firstreach; | 0ed285dDrive RPR row pattern matching once per row
4403 | - |  | 0ed285dDrive RPR row pattern matching once per row
4404 | - | /* navFirst is always FIXED; it never takes RETAIN_ALL */ | 0ed285dDrive RPR row pattern matching once per row
4405 | 5848 | Assert(winstate->navFirstOffsetKind == RPR_NAV_OFFSET_FIXED); | 0ed285dDrive RPR row pattern matching once per row
4406 | - |  | 0ed285dDrive RPR row pattern matching once per row
4407 | - | /* | 0ed285dDrive RPR row pattern matching once per row
4408 | - | * Head context has the smallest matchStartRow (contexts appended in | 0ed285dDrive RPR row pattern matching once per row
4409 | - | * nondecreasing order), so bounding by it covers every FIRST reach. | 0ed285dDrive RPR row pattern matching once per row
4410 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4411 | 5848 | if (!pg_add_s64_overflow(winstate->nfaContext->matchStartRow, | 0ed285dDrive RPR row pattern matching once per row
4412 | - | winstate->navFirstOffset, | 0ed285dDrive RPR row pattern matching once per row
4413 | - | &firstreach)) | 0ed285dDrive RPR row pattern matching once per row
4414 | 5812 | navmarkpos = Min(navmarkpos, Max(firstreach, 0)); | 0ed285dDrive RPR row pattern matching once per row
4415 | - | } | 0ed285dDrive RPR row pattern matching once per row
4416 | - |  | 0ed285dDrive RPR row pattern matching once per row
4417 | 988548 | if (navmarkpos > winstate->nav_winobj->markpos) | 0ed285dDrive RPR row pattern matching once per row
4418 | 970732 | WinSetMarkPosition(winstate->nav_winobj, navmarkpos); | 0ed285dDrive RPR row pattern matching once per row
4419 | - | } | 0ed285dDrive RPR row pattern matching once per row

advance_reduced_frame_nfa() lines 4430-4501
Modified Lines Coverage: 19/19 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4430 | 99156 | advance_reduced_frame_nfa(WindowObject winobj, RPRNFAContext *targetCtx, | 0ed285dDrive RPR row pattern matching once per row
4431 | - | int64 pos, bool hasLimitedFrame, int64 frameOffset) | 0ed285dDrive RPR row pattern matching once per row
4432 | - | { | 0ed285dDrive RPR row pattern matching once per row
4433 | 99156 | WindowAggState *winstate = winobj->winstate; | 0ed285dDrive RPR row pattern matching once per row
4434 | 99156 | int64 currentPos; | 0ed285dDrive RPR row pattern matching once per row
4435 | 99156 | int64 startPos; | 0ed285dDrive RPR row pattern matching once per row
4436 | - |  | 0ed285dDrive RPR row pattern matching once per row
4437 | - | /* | 0ed285dDrive RPR row pattern matching once per row
4438 | - | * Determine where to start processing. Usually nfaLastProcessedRow+1 >= | 0ed285dDrive RPR row pattern matching once per row
4439 | - | * pos since contexts are created at currentPos+1 during processing. | 0ed285dDrive RPR row pattern matching once per row
4440 | - | * However, pos can exceed this when rows are skipped (e.g., unmatched | 0ed285dDrive RPR row pattern matching once per row
4441 | - | * rows don't update nfaLastProcessedRow). | 0ed285dDrive RPR row pattern matching once per row
4442 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4443 | 99156 | startPos = Max(pos, winstate->nfaLastProcessedRow + 1); | 0ed285dDrive RPR row pattern matching once per row
4444 | - |  | 0ed285dDrive RPR row pattern matching once per row
4445 | - | /* | 0ed285dDrive RPR row pattern matching once per row
4446 | - | * Process rows until target context completes or we hit boundaries. Each | 0ed285dDrive RPR row pattern matching once per row
4447 | - | * row evaluation is shared across all active contexts. | 0ed285dDrive RPR row pattern matching once per row
4448 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4449 | 1087744 | for (currentPos = startPos; targetCtx->states != NULL; currentPos++) | 0ed285dDrive RPR row pattern matching once per row
4450 | - | { | 0ed285dDrive RPR row pattern matching once per row
4451 | 994976 | bool rowExists; | 0ed285dDrive RPR row pattern matching once per row
4452 | - |  | 0ed285dDrive RPR row pattern matching once per row
4453 | - | /* | 0ed285dDrive RPR row pattern matching once per row
4454 | - | * Evaluate variables for this row - done only once, shared by all | 0ed285dDrive RPR row pattern matching once per row
4455 | - | * contexts. | 0ed285dDrive RPR row pattern matching once per row
4456 | - | * | 0ed285dDrive RPR row pattern matching once per row
4457 | - | * Set nav_match_start to the head context's matchStartRow for | 0ed285dDrive RPR row pattern matching once per row
4458 | - | * FIRST/LAST navigation. Match_start-dependent variables (FIRST, | 0ed285dDrive RPR row pattern matching once per row
4459 | - | * LAST-with-offset) are re-evaluated per-context in ExecRPRProcessRow | 0ed285dDrive RPR row pattern matching once per row
4460 | - | * when matchStartRow differs. | 0ed285dDrive RPR row pattern matching once per row
4461 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4462 | 994976 | winstate->nav_match_start = targetCtx->matchStartRow; | 0ed285dDrive RPR row pattern matching once per row
4463 | 994976 | rowExists = nfa_evaluate_row(winobj, currentPos, winstate->nfaVarMatched); | 0ed285dDrive RPR row pattern matching once per row
4464 | - |  | 0ed285dDrive RPR row pattern matching once per row
4465 | - | /* No more rows in partition? Finalize all contexts */ | 0ed285dDrive RPR row pattern matching once per row
4466 | 994916 | if (!rowExists) | 0ed285dDrive RPR row pattern matching once per row
4467 | - | { | 0ed285dDrive RPR row pattern matching once per row
4468 | 6328 | ExecRPRFinalizeAllContexts(winstate, currentPos - 1); | 0ed285dDrive RPR row pattern matching once per row
4469 | - | /* Clean up dead contexts from finalization */ | 0ed285dDrive RPR row pattern matching once per row
4470 | 6328 | ExecRPRCleanupDeadContexts(winstate, targetCtx); | 0ed285dDrive RPR row pattern matching once per row
4471 | 6328 | break; | 0ed285dDrive RPR row pattern matching once per row
4472 | - | } | 0ed285dDrive RPR row pattern matching once per row
4473 | - |  | 0ed285dDrive RPR row pattern matching once per row
4474 | - | /* Update last processed row */ | 0ed285dDrive RPR row pattern matching once per row
4475 | 988588 | winstate->nfaLastProcessedRow = currentPos; | 0ed285dDrive RPR row pattern matching once per row
4476 | - |  | 0ed285dDrive RPR row pattern matching once per row
4477 | - | /*-------------------------- | 0ed285dDrive RPR row pattern matching once per row
4478 | - | * Process all contexts for this row: | 0ed285dDrive RPR row pattern matching once per row
4479 | - | * 1. Match all (convergence) | 0ed285dDrive RPR row pattern matching once per row
4480 | - | * 2. Absorb redundant | 0ed285dDrive RPR row pattern matching once per row
4481 | - | * 3. Advance all (divergence) | 0ed285dDrive RPR row pattern matching once per row
4482 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4483 | 988588 | ExecRPRProcessRow(winstate, currentPos, hasLimitedFrame, frameOffset); | 0ed285dDrive RPR row pattern matching once per row
4484 | - |  | 0ed285dDrive RPR row pattern matching once per row
4485 | - | /* | 0ed285dDrive RPR row pattern matching once per row
4486 | - | * Create a new context for the next potential start position. This | 0ed285dDrive RPR row pattern matching once per row
4487 | - | * enables overlapping match detection for SKIP TO NEXT ROW. | 0ed285dDrive RPR row pattern matching once per row
4488 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4489 | 988588 | ExecRPRStartContext(winstate, currentPos + 1); | 0ed285dDrive RPR row pattern matching once per row
4490 | - |  | 0ed285dDrive RPR row pattern matching once per row
4491 | - | /* | 0ed285dDrive RPR row pattern matching once per row
4492 | - | * Clean up dead contexts (failed with no active states and no match). | 0ed285dDrive RPR row pattern matching once per row
4493 | - | * This removes contexts that failed during processing and counts them | 0ed285dDrive RPR row pattern matching once per row
4494 | - | * appropriately as pruned or mismatched. | 0ed285dDrive RPR row pattern matching once per row
4495 | - | */ | 0ed285dDrive RPR row pattern matching once per row
4496 | 988588 | ExecRPRCleanupDeadContexts(winstate, targetCtx); | 0ed285dDrive RPR row pattern matching once per row
4497 | - |  | 0ed285dDrive RPR row pattern matching once per row
4498 | - | /* Advance the nav mark to the frontier so trim can free old rows. */ | 0ed285dDrive RPR row pattern matching once per row
4499 | 988588 | advance_nav_mark(winstate, currentPos); | 0ed285dDrive RPR row pattern matching once per row
4500 | - | } | 0ed285dDrive RPR row pattern matching once per row
4501 | 99096 | } | 0ed285dDrive RPR row pattern matching once per row

update_reduced_frame() lines 4518-4631
Modified Lines Coverage: 49/49 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4518 | 129804 | update_reduced_frame(WindowObject winobj, int64 pos) | 24cfb8dRow pattern recognition patch (executor and commands).
4519 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4520 | 129804 | WindowAggState *winstate = winobj->winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4521 | 129804 | RPRNFAContext *targetCtx; | 24cfb8dRow pattern recognition patch (executor and commands).
4522 | 129804 | int frameOptions = winstate->frameOptions; | 24cfb8dRow pattern recognition patch (executor and commands).
4523 | 129804 | bool hasLimitedFrame; | 24cfb8dRow pattern recognition patch (executor and commands).
4524 | 129804 | int64 frameOffset = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4525 | 129804 | int64 matchLen; | 24cfb8dRow pattern recognition patch (executor and commands).
4526 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4527 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4528 | - | * Check if we have a limited frame (ROWS ... N FOLLOWING). Each context | 24cfb8dRow pattern recognition patch (executor and commands).
4529 | - | * needs its own frame end based on matchStartRow + offset. | 24cfb8dRow pattern recognition patch (executor and commands).
4530 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4531 | 129804 | hasLimitedFrame = (frameOptions & FRAMEOPTION_ROWS) && | 24cfb8dRow pattern recognition patch (executor and commands).
4532 | - | !(frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING); | 24cfb8dRow pattern recognition patch (executor and commands).
4533 | 129804 | if (hasLimitedFrame) | 24cfb8dRow pattern recognition patch (executor and commands).
4534 | 408 | frameOffset = DatumGetInt64(winstate->endOffsetValue); | 24cfb8dRow pattern recognition patch (executor and commands).
4535 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4536 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4537 | - | * Case 1: pos is before any existing context's start position. This means | 24cfb8dRow pattern recognition patch (executor and commands).
4538 | - | * the position was already processed and determined unmatched. Head is | 24cfb8dRow pattern recognition patch (executor and commands).
4539 | - | * the oldest context (lowest matchStartRow) since contexts are added at | 24cfb8dRow pattern recognition patch (executor and commands).
4540 | - | * tail with increasing positions. | 24cfb8dRow pattern recognition patch (executor and commands).
4541 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4542 | 129804 | if (winstate->nfaContext != NULL && | 24cfb8dRow pattern recognition patch (executor and commands).
4543 | 113492 | pos < winstate->nfaContext->matchStartRow) | 24cfb8dRow pattern recognition patch (executor and commands).
4544 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4545 | - | /* already processed, unmatched */ | 24cfb8dRow pattern recognition patch (executor and commands).
4546 | 23816 | winstate->rpr_match_valid = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4547 | 23816 | winstate->rpr_match_matched = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4548 | 23816 | winstate->rpr_match_start = pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4549 | 23816 | winstate->rpr_match_length = 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4550 | 23816 | return; | 24cfb8dRow pattern recognition patch (executor and commands).
4551 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4552 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4553 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4554 | - | * Case 2: Find existing context for this pos, or create new one. | 24cfb8dRow pattern recognition patch (executor and commands).
4555 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4556 | 105988 | targetCtx = ExecRPRGetHeadContext(winstate, pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4557 | 105988 | if (targetCtx == NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
4558 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4559 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4560 | - | * No context exists. If pos is already processed, it means this row | 24cfb8dRow pattern recognition patch (executor and commands).
4561 | - | * was already determined to be unmatched or skipped - no need to | 24cfb8dRow pattern recognition patch (executor and commands).
4562 | - | * reprocess. | 24cfb8dRow pattern recognition patch (executor and commands).
4563 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4564 | 16312 | if (pos <= winstate->nfaLastProcessedRow) | 24cfb8dRow pattern recognition patch (executor and commands).
4565 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4566 | - | /* already processed, unmatched */ | 24cfb8dRow pattern recognition patch (executor and commands).
4567 | 6044 | winstate->rpr_match_valid = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4568 | 6044 | winstate->rpr_match_matched = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4569 | 6044 | winstate->rpr_match_start = pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4570 | 6044 | winstate->rpr_match_length = 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4571 | 6044 | return; | 24cfb8dRow pattern recognition patch (executor and commands).
4572 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4573 | - | /* Not yet processed - create new context and start fresh */ | 24cfb8dRow pattern recognition patch (executor and commands).
4574 | 10268 | targetCtx = ExecRPRStartContext(winstate, pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4575 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4576 | 89676 | else if (targetCtx->states == NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
4577 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4578 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4579 | - | * The head context already completed in an earlier call. Reachable | 24cfb8dRow pattern recognition patch (executor and commands).
4580 | - | * under SKIP TO NEXT ROW, where overlapping contexts let one reach | 24cfb8dRow pattern recognition patch (executor and commands).
4581 | - | * FIN -- recording its result -- before the call for its own start | 24cfb8dRow pattern recognition patch (executor and commands).
4582 | - | * row arrives. Register that result. | 24cfb8dRow pattern recognition patch (executor and commands).
4583 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4584 | 788 | goto register_result; | 24cfb8dRow pattern recognition patch (executor and commands).
4585 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4586 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4587 | - | /* Drive the NFA forward until pos's match is resolved. */ | 0ed285dDrive RPR row pattern matching once per row
4588 | 99156 | advance_reduced_frame_nfa(winobj, targetCtx, pos, hasLimitedFrame, | 0ed285dDrive RPR row pattern matching once per row
4589 | - | frameOffset); | 0ed285dDrive RPR row pattern matching once per row
4590 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4591 | 99884 | register_result: | 24cfb8dRow pattern recognition patch (executor and commands).
4592 | 99884 | Assert(pos == targetCtx->matchStartRow); | 24cfb8dRow pattern recognition patch (executor and commands).
4593 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4594 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4595 | - | * Record match result. | 24cfb8dRow pattern recognition patch (executor and commands).
4596 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4597 | 99884 | winstate->rpr_match_valid = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4598 | 99884 | winstate->rpr_match_start = targetCtx->matchStartRow; | 24cfb8dRow pattern recognition patch (executor and commands).
4599 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4600 | 99884 | if (targetCtx->matchEndRow < targetCtx->matchStartRow) | 24cfb8dRow pattern recognition patch (executor and commands).
4601 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4602 | 63180 | matchLen = targetCtx->lastProcessedRow - targetCtx->matchStartRow + 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4603 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4604 | 63180 | if (targetCtx->matchedState != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
4605 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4606 | - | /* Empty match: FIN reached but 0 rows consumed */ | 24cfb8dRow pattern recognition patch (executor and commands).
4607 | 424 | winstate->rpr_match_matched = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4608 | 424 | winstate->rpr_match_length = 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4609 | 424 | ExecRPRRecordContextSuccess(winstate, 0); | 24cfb8dRow pattern recognition patch (executor and commands).
4610 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4611 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4612 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4613 | - | /* No match */ | 24cfb8dRow pattern recognition patch (executor and commands).
4614 | 62756 | winstate->rpr_match_matched = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4615 | 62756 | winstate->rpr_match_length = 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4616 | 62756 | ExecRPRRecordContextFailure(winstate, matchLen); | 24cfb8dRow pattern recognition patch (executor and commands).
4617 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4618 | 63180 | ExecRPRFreeContext(winstate, targetCtx); | 24cfb8dRow pattern recognition patch (executor and commands).
4619 | 63180 | return; | 24cfb8dRow pattern recognition patch (executor and commands).
4620 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4621 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4622 | - | /* Match succeeded */ | 24cfb8dRow pattern recognition patch (executor and commands).
4623 | 36704 | matchLen = targetCtx->matchEndRow - targetCtx->matchStartRow + 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4624 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4625 | 36704 | winstate->rpr_match_matched = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4626 | 36704 | winstate->rpr_match_length = matchLen; | 24cfb8dRow pattern recognition patch (executor and commands).
4627 | 36704 | ExecRPRRecordContextSuccess(winstate, matchLen); | 24cfb8dRow pattern recognition patch (executor and commands).
4628 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4629 | - | /* Remove the matched context */ | 24cfb8dRow pattern recognition patch (executor and commands).
4630 | 36704 | ExecRPRFreeContext(winstate, targetCtx); | 24cfb8dRow pattern recognition patch (executor and commands).
4631 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

nfa_evaluate_row() lines 4646-4689
Modified Lines Coverage: 20/20 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4646 | 994976 | nfa_evaluate_row(WindowObject winobj, int64 pos, bool *varMatched) | 24cfb8dRow pattern recognition patch (executor and commands).
4647 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4648 | 994976 | WindowAggState *winstate = winobj->winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4649 | 994976 | ExprContext *econtext = winstate->rprContext; | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
4650 | 994976 | TupleTableSlot *slot; | 24cfb8dRow pattern recognition patch (executor and commands).
4651 | 994976 | int64 saved_pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4652 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4653 | - | /* Release the previous row's DEFINE evaluation memory */ | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
4654 | 994976 | ResetExprContext(econtext); | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
4655 | - |  | a70f1c1Use a dedicated ExprContext for RPR DEFINE clause evaluation
4656 | - | /* Fetch current row into temp_slot_1 */ | 24cfb8dRow pattern recognition patch (executor and commands).
4657 | 994976 | slot = winstate->temp_slot_1; | 24cfb8dRow pattern recognition patch (executor and commands).
4658 | 994976 | if (!window_gettupleslot(winobj, pos, slot)) | 24cfb8dRow pattern recognition patch (executor and commands).
4659 | - | return false; /* No row exists */ | 24cfb8dRow pattern recognition patch (executor and commands).
4660 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4661 | - | /* Set up 1-slot context: only ecxt_outertuple */ | 24cfb8dRow pattern recognition patch (executor and commands).
4662 | 988648 | econtext->ecxt_outertuple = slot; | 24cfb8dRow pattern recognition patch (executor and commands).
4663 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4664 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4665 | - | * Save and set currentpos so that EEOP_RPR_NAV_SET opcodes can calculate | 24cfb8dRow pattern recognition patch (executor and commands).
4666 | - | * target positions (currentpos +/- offset). | 24cfb8dRow pattern recognition patch (executor and commands).
4667 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4668 | 988648 | saved_pos = winstate->currentpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4669 | 988648 | winstate->currentpos = pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4670 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4671 | - | /* Invalidate nav_slot cache so PREV/NEXT re-fetch for new row */ | 24cfb8dRow pattern recognition patch (executor and commands).
4672 | 988648 | winstate->nav_slot_pos = -1; | 24cfb8dRow pattern recognition patch (executor and commands).
4673 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4674 | 3336192 | foreach_ptr(ExprState, exprState, winstate->defineClauseExprs) | b848408Tidy up row pattern recognition plumbing
4675 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4676 | 2347604 | int varIdx = foreach_current_index(exprState); | 4cf9108Further tidy up row pattern recognition plumbing
4677 | 2347604 | Datum result; | 24cfb8dRow pattern recognition patch (executor and commands).
4678 | 2347604 | bool isnull; | 24cfb8dRow pattern recognition patch (executor and commands).
4679 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4680 | - | /* Evaluate DEFINE expression */ | 24cfb8dRow pattern recognition patch (executor and commands).
4681 | 2347604 | result = ExecEvalExpr(exprState, econtext, &isnull); | 24cfb8dRow pattern recognition patch (executor and commands).
4682 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4683 | 3721520 | varMatched[varIdx] = (!isnull && DatumGetBool(result)); | 24cfb8dRow pattern recognition patch (executor and commands).
4684 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4685 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4686 | 988588 | winstate->currentpos = saved_pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4687 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4688 | 988588 | return true; /* Row exists */ | 24cfb8dRow pattern recognition patch (executor and commands).
4689 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

WinGetSlotInFrame() lines 4706-4916
Modified Lines Coverage: 85/101 lines (84.2%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4706 | 1531400 | WinGetSlotInFrame(WindowObject winobj, TupleTableSlot *slot, | 24cfb8dRow pattern recognition patch (executor and commands).
4707 | - | int relpos, int seektype, bool set_mark, | 24cfb8dRow pattern recognition patch (executor and commands).
4708 | - | bool *isnull, bool *isout) | 24cfb8dRow pattern recognition patch (executor and commands).
4709 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4710 | 1531400 | WindowAggState *winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4711 | 1531400 | int64 abs_pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4712 | 1531400 | int64 mark_pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4713 | 1531400 | int64 num_reduced_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4714 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4715 | 1531400 | Assert(WindowObjectIsValid(winobj)); | 24cfb8dRow pattern recognition patch (executor and commands).
4716 | 1531400 | winstate = winobj->winstate; | 24cfb8dRow pattern recognition patch (executor and commands).
4717 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4718 | 1531400 | switch (seektype) | 24cfb8dRow pattern recognition patch (executor and commands).
4719 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4720 | 0 | case WINDOW_SEEK_CURRENT: | 24cfb8dRow pattern recognition patch (executor and commands).
4721 | 0 | elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame"); | 24cfb8dRow pattern recognition patch (executor and commands).
4722 | - | abs_pos = mark_pos = 0; /* keep compiler quiet */ | 24cfb8dRow pattern recognition patch (executor and commands).
4723 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4724 | 969760 | case WINDOW_SEEK_HEAD: | 24cfb8dRow pattern recognition patch (executor and commands).
4725 | - | /* rejecting relpos < 0 is easy and simplifies code below */ | 24cfb8dRow pattern recognition patch (executor and commands).
4726 | 969760 | if (relpos < 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4727 | 0 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4728 | 969760 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4729 | 969732 | abs_pos = winstate->frameheadpos + relpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4730 | 969732 | mark_pos = abs_pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4731 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4732 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4733 | - | * Account for exclusion option if one is active, but advance only | 24cfb8dRow pattern recognition patch (executor and commands).
4734 | - | * abs_pos not mark_pos. This prevents changes of the current | 24cfb8dRow pattern recognition patch (executor and commands).
4735 | - | * row's peer group from resulting in trying to fetch a row before | 24cfb8dRow pattern recognition patch (executor and commands).
4736 | - | * some previous mark position. | 24cfb8dRow pattern recognition patch (executor and commands).
4737 | - | * | 24cfb8dRow pattern recognition patch (executor and commands).
4738 | - | * Note that in some corner cases such as current row being | 24cfb8dRow pattern recognition patch (executor and commands).
4739 | - | * outside frame, these calculations are theoretically too simple, | 24cfb8dRow pattern recognition patch (executor and commands).
4740 | - | * but it doesn't matter because we'll end up deciding the row is | 24cfb8dRow pattern recognition patch (executor and commands).
4741 | - | * out of frame. We do not attempt to avoid fetching rows past | 24cfb8dRow pattern recognition patch (executor and commands).
4742 | - | * end of frame; that would happen in some cases anyway. | 24cfb8dRow pattern recognition patch (executor and commands).
4743 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4744 | 969732 | switch (winstate->frameOptions & FRAMEOPTION_EXCLUSION) | 24cfb8dRow pattern recognition patch (executor and commands).
4745 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4746 | - | case 0: | 24cfb8dRow pattern recognition patch (executor and commands).
4747 | - | /* no adjustment needed */ | 24cfb8dRow pattern recognition patch (executor and commands).
4748 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4749 | 160 | case FRAMEOPTION_EXCLUDE_CURRENT_ROW: | 24cfb8dRow pattern recognition patch (executor and commands).
4750 | 160 | if (abs_pos >= winstate->currentpos && | 24cfb8dRow pattern recognition patch (executor and commands).
4751 | - | winstate->currentpos >= winstate->frameheadpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4752 | 44 | abs_pos++; | 24cfb8dRow pattern recognition patch (executor and commands).
4753 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4754 | 80 | case FRAMEOPTION_EXCLUDE_GROUP: | 24cfb8dRow pattern recognition patch (executor and commands).
4755 | 80 | update_grouptailpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4756 | 80 | if (abs_pos >= winstate->groupheadpos && | 24cfb8dRow pattern recognition patch (executor and commands).
4757 | 48 | winstate->grouptailpos > winstate->frameheadpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4758 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4759 | 48 | int64 overlapstart = Max(winstate->groupheadpos, | 24cfb8dRow pattern recognition patch (executor and commands).
4760 | - | winstate->frameheadpos); | 24cfb8dRow pattern recognition patch (executor and commands).
4761 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4762 | 48 | abs_pos += winstate->grouptailpos - overlapstart; | 24cfb8dRow pattern recognition patch (executor and commands).
4763 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4764 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4765 | 200 | case FRAMEOPTION_EXCLUDE_TIES: | 24cfb8dRow pattern recognition patch (executor and commands).
4766 | 200 | update_grouptailpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4767 | 200 | if (abs_pos >= winstate->groupheadpos && | 24cfb8dRow pattern recognition patch (executor and commands).
4768 | 136 | winstate->grouptailpos > winstate->frameheadpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4769 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4770 | 56 | int64 overlapstart = Max(winstate->groupheadpos, | 24cfb8dRow pattern recognition patch (executor and commands).
4771 | - | winstate->frameheadpos); | 24cfb8dRow pattern recognition patch (executor and commands).
4772 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4773 | 56 | if (abs_pos == overlapstart) | 24cfb8dRow pattern recognition patch (executor and commands).
4774 | 56 | abs_pos = winstate->currentpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4775 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4776 | 0 | abs_pos += winstate->grouptailpos - overlapstart - 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4777 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4778 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4779 | 0 | default: | 24cfb8dRow pattern recognition patch (executor and commands).
4780 | 0 | elog(ERROR, "unrecognized frame option state: 0x%x", | 24cfb8dRow pattern recognition patch (executor and commands).
4781 | - | winstate->frameOptions); | 24cfb8dRow pattern recognition patch (executor and commands).
4782 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4783 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4784 | 969732 | num_reduced_frame = row_is_in_reduced_frame(winobj, | 24cfb8dRow pattern recognition patch (executor and commands).
4785 | - | winstate->frameheadpos); | 24cfb8dRow pattern recognition patch (executor and commands).
4786 | 969732 | if (num_reduced_frame < 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4787 | 960720 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4788 | 9012 | else if (num_reduced_frame > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4789 | 6060 | if (relpos >= num_reduced_frame) | 24cfb8dRow pattern recognition patch (executor and commands).
4790 | 16 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4791 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4792 | 561640 | case WINDOW_SEEK_TAIL: | 24cfb8dRow pattern recognition patch (executor and commands).
4793 | - | /* rejecting relpos > 0 is easy and simplifies code below */ | 24cfb8dRow pattern recognition patch (executor and commands).
4794 | 561640 | if (relpos > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4795 | 0 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4796 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4797 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4798 | - | * RPR cares about frame head pos. Need to call | 24cfb8dRow pattern recognition patch (executor and commands).
4799 | - | * update_frameheadpos | 24cfb8dRow pattern recognition patch (executor and commands).
4800 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4801 | 561640 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4802 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4803 | 561640 | update_frametailpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4804 | 561636 | abs_pos = winstate->frametailpos - 1 + relpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4805 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4806 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4807 | - | * Account for exclusion option if one is active. If there is no | 24cfb8dRow pattern recognition patch (executor and commands).
4808 | - | * exclusion, we can safely set the mark at the accessed row. But | 24cfb8dRow pattern recognition patch (executor and commands).
4809 | - | * if there is, we can only mark the frame start, because we can't | 24cfb8dRow pattern recognition patch (executor and commands).
4810 | - | * be sure how far back in the frame the exclusion might cause us | 24cfb8dRow pattern recognition patch (executor and commands).
4811 | - | * to fetch in future. Furthermore, we have to actually check | 24cfb8dRow pattern recognition patch (executor and commands).
4812 | - | * against frameheadpos here, since it's unsafe to try to fetch a | 24cfb8dRow pattern recognition patch (executor and commands).
4813 | - | * row before frame start if the mark might be there already. | 24cfb8dRow pattern recognition patch (executor and commands).
4814 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4815 | 561636 | switch (winstate->frameOptions & FRAMEOPTION_EXCLUSION) | 24cfb8dRow pattern recognition patch (executor and commands).
4816 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4817 | - | case 0: | 24cfb8dRow pattern recognition patch (executor and commands).
4818 | - | /* no adjustment needed */ | 24cfb8dRow pattern recognition patch (executor and commands).
4819 | - | mark_pos = abs_pos; | 24cfb8dRow pattern recognition patch (executor and commands).
4820 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4821 | 120 | case FRAMEOPTION_EXCLUDE_CURRENT_ROW: | 24cfb8dRow pattern recognition patch (executor and commands).
4822 | 120 | if (abs_pos <= winstate->currentpos && | 24cfb8dRow pattern recognition patch (executor and commands).
4823 | - | winstate->currentpos < winstate->frametailpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4824 | 12 | abs_pos--; | 24cfb8dRow pattern recognition patch (executor and commands).
4825 | 120 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4826 | 120 | if (abs_pos < winstate->frameheadpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4827 | 8 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4828 | - | mark_pos = winstate->frameheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4829 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4830 | 160 | case FRAMEOPTION_EXCLUDE_GROUP: | 24cfb8dRow pattern recognition patch (executor and commands).
4831 | 160 | update_grouptailpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4832 | 160 | if (abs_pos < winstate->grouptailpos && | 24cfb8dRow pattern recognition patch (executor and commands).
4833 | 36 | winstate->groupheadpos < winstate->frametailpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4834 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4835 | 36 | int64 overlapend = Min(winstate->grouptailpos, | 24cfb8dRow pattern recognition patch (executor and commands).
4836 | - | winstate->frametailpos); | 24cfb8dRow pattern recognition patch (executor and commands).
4837 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4838 | 36 | abs_pos -= overlapend - winstate->groupheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4839 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4840 | 160 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4841 | 160 | if (abs_pos < winstate->frameheadpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4842 | 36 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4843 | - | mark_pos = winstate->frameheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4844 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4845 | 80 | case FRAMEOPTION_EXCLUDE_TIES: | 24cfb8dRow pattern recognition patch (executor and commands).
4846 | 80 | update_grouptailpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4847 | 80 | if (abs_pos < winstate->grouptailpos && | 24cfb8dRow pattern recognition patch (executor and commands).
4848 | 24 | winstate->groupheadpos < winstate->frametailpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4849 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4850 | 24 | int64 overlapend = Min(winstate->grouptailpos, | 24cfb8dRow pattern recognition patch (executor and commands).
4851 | - | winstate->frametailpos); | 24cfb8dRow pattern recognition patch (executor and commands).
4852 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4853 | 24 | if (abs_pos == overlapend - 1) | 24cfb8dRow pattern recognition patch (executor and commands).
4854 | 24 | abs_pos = winstate->currentpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4855 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
4856 | 0 | abs_pos -= overlapend - 1 - winstate->groupheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4857 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4858 | 80 | update_frameheadpos(winstate); | 24cfb8dRow pattern recognition patch (executor and commands).
4859 | 80 | if (abs_pos < winstate->frameheadpos) | 24cfb8dRow pattern recognition patch (executor and commands).
4860 | 0 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4861 | - | mark_pos = winstate->frameheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4862 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4863 | 0 | default: | 24cfb8dRow pattern recognition patch (executor and commands).
4864 | 0 | elog(ERROR, "unrecognized frame option state: 0x%x", | 24cfb8dRow pattern recognition patch (executor and commands).
4865 | - | winstate->frameOptions); | 24cfb8dRow pattern recognition patch (executor and commands).
4866 | - | mark_pos = 0; /* keep compiler quiet */ | 24cfb8dRow pattern recognition patch (executor and commands).
4867 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4868 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4869 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4870 | 561592 | num_reduced_frame = row_is_in_reduced_frame(winobj, | 24cfb8dRow pattern recognition patch (executor and commands).
4871 | - | winstate->frameheadpos); | 24cfb8dRow pattern recognition patch (executor and commands).
4872 | 561592 | if (num_reduced_frame < 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4873 | 552812 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4874 | 8780 | else if (num_reduced_frame > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4875 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4876 | 5760 | if (-relpos >= num_reduced_frame) | 24cfb8dRow pattern recognition patch (executor and commands).
4877 | 0 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4878 | 5760 | abs_pos = winstate->frameheadpos + relpos + | 24cfb8dRow pattern recognition patch (executor and commands).
4879 | - | num_reduced_frame - 1; | 24cfb8dRow pattern recognition patch (executor and commands).
4880 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4881 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4882 | 0 | default: | 24cfb8dRow pattern recognition patch (executor and commands).
4883 | 0 | elog(ERROR, "unrecognized window seek type: %d", seektype); | 24cfb8dRow pattern recognition patch (executor and commands).
4884 | - | abs_pos = mark_pos = 0; /* keep compiler quiet */ | 24cfb8dRow pattern recognition patch (executor and commands).
4885 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
4886 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4887 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4888 | 17776 | if (!window_gettupleslot(winobj, abs_pos, slot)) | 24cfb8dRow pattern recognition patch (executor and commands).
4889 | 264 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4890 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4891 | - | /* The code above does not detect all out-of-frame cases, so check */ | 24cfb8dRow pattern recognition patch (executor and commands).
4892 | 17512 | if (row_is_in_frame(winobj, abs_pos, slot, false) <= 0) | 24cfb8dRow pattern recognition patch (executor and commands).
4893 | 200 | goto out_of_frame; | 24cfb8dRow pattern recognition patch (executor and commands).
4894 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4895 | 17292 | if (isout) | 24cfb8dRow pattern recognition patch (executor and commands).
4896 | 0 | *isout = false; | 24cfb8dRow pattern recognition patch (executor and commands).
4897 | 17292 | if (set_mark) | 24cfb8dRow pattern recognition patch (executor and commands).
4898 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4899 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
4900 | - | * If RPR is enabled and seek type is WINDOW_SEEK_TAIL, we set the | 24cfb8dRow pattern recognition patch (executor and commands).
4901 | - | * mark position unconditionally to frameheadpos. In this case the | 24cfb8dRow pattern recognition patch (executor and commands).
4902 | - | * frame always starts at CURRENT_ROW and never goes back, thus | 24cfb8dRow pattern recognition patch (executor and commands).
4903 | - | * setting the mark at the position is safe. | 24cfb8dRow pattern recognition patch (executor and commands).
4904 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
4905 | 17248 | if (winstate->rpPattern != NULL && seektype == WINDOW_SEEK_TAIL) | 24cfb8dRow pattern recognition patch (executor and commands).
4906 | 5760 | mark_pos = winstate->frameheadpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4907 | 17248 | WinSetMarkPosition(winobj, mark_pos); | 24cfb8dRow pattern recognition patch (executor and commands).
4908 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4909 | - | return 0; | 24cfb8dRow pattern recognition patch (executor and commands).
4910 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4911 | 1514056 | out_of_frame: | 24cfb8dRow pattern recognition patch (executor and commands).
4912 | 1514056 | if (isout) | 24cfb8dRow pattern recognition patch (executor and commands).
4913 | 0 | *isout = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4914 | 1514056 | *isnull = true; | 24cfb8dRow pattern recognition patch (executor and commands).
4915 | 1514056 | return -1; | 24cfb8dRow pattern recognition patch (executor and commands).
4916 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

WinCheckAndInitializeNullTreatment() lines 4932-4950
Modified Lines Coverage: 9/10 lines (90.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4932 | 2107439 | WinCheckAndInitializeNullTreatment(WindowObject winobj, | 24cfb8dRow pattern recognition patch (executor and commands).
4933 | - | bool allowNullTreatment, | 24cfb8dRow pattern recognition patch (executor and commands).
4934 | - | FunctionCallInfo fcinfo) | 24cfb8dRow pattern recognition patch (executor and commands).
4935 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4936 | 2107439 | Assert(WindowObjectIsValid(winobj)); | 24cfb8dRow pattern recognition patch (executor and commands).
4937 | 2107439 | if (winobj->ignore_nulls != NO_NULLTREATMENT && !allowNullTreatment) | 24cfb8dRow pattern recognition patch (executor and commands).
4938 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4939 | 48 | const char *funcname = get_func_name(fcinfo->flinfo->fn_oid); | 24cfb8dRow pattern recognition patch (executor and commands).
4940 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4941 | 48 | if (!funcname) | 24cfb8dRow pattern recognition patch (executor and commands).
4942 | 0 | elog(ERROR, "could not get function name"); | 24cfb8dRow pattern recognition patch (executor and commands).
4943 | 48 | ereport(ERROR, | 24cfb8dRow pattern recognition patch (executor and commands).
4944 | - | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | 24cfb8dRow pattern recognition patch (executor and commands).
4945 | - | errmsg("function %s does not allow RESPECT/IGNORE NULLS", | 24cfb8dRow pattern recognition patch (executor and commands).
4946 | - | funcname))); | 24cfb8dRow pattern recognition patch (executor and commands).
4947 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4948 | 2107391 | else if (winobj->ignore_nulls == PARSER_IGNORE_NULLS) | 24cfb8dRow pattern recognition patch (executor and commands).
4949 | 152 | winobj->ignore_nulls = IGNORE_NULLS; | 24cfb8dRow pattern recognition patch (executor and commands).
4950 | 2107391 | } | 24cfb8dRow pattern recognition patch (executor and commands).

WinGetPartitionLocalMemory() lines 4965-4972
Modified Lines Coverage: 6/6 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4965 | 221280 | WinGetPartitionLocalMemory(WindowObject winobj, Size sz) | 24cfb8dRow pattern recognition patch (executor and commands).
4966 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4967 | 221280 | Assert(WindowObjectIsValid(winobj)); | 24cfb8dRow pattern recognition patch (executor and commands).
4968 | 221280 | if (winobj->localmem == NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
4969 | 295 | winobj->localmem = | 24cfb8dRow pattern recognition patch (executor and commands).
4970 | 295 | MemoryContextAllocZero(winobj->winstate->partcontext, sz); | 24cfb8dRow pattern recognition patch (executor and commands).
4971 | 221280 | return winobj->localmem; | 24cfb8dRow pattern recognition patch (executor and commands).
4972 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

WinGetCurrentPosition() lines 4980-4984
Modified Lines Coverage: 3/3 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4980 | 501586 | WinGetCurrentPosition(WindowObject winobj) | 24cfb8dRow pattern recognition patch (executor and commands).
4981 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4982 | 501586 | Assert(WindowObjectIsValid(winobj)); | 24cfb8dRow pattern recognition patch (executor and commands).
4983 | 501586 | return winobj->winstate->currentpos; | 24cfb8dRow pattern recognition patch (executor and commands).
4984 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

WinGetPartitionRowCount() lines 4995-5000
Modified Lines Coverage: 4/4 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
4995 | 208 | WinGetPartitionRowCount(WindowObject winobj) | 24cfb8dRow pattern recognition patch (executor and commands).
4996 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
4997 | 208 | Assert(WindowObjectIsValid(winobj)); | 24cfb8dRow pattern recognition patch (executor and commands).
4998 | 208 | spool_tuples(winobj->winstate, -1); | 24cfb8dRow pattern recognition patch (executor and commands).
4999 | 208 | return winobj->winstate->spooled_rows; | 24cfb8dRow pattern recognition patch (executor and commands).
5000 | - | } | 95b07bcSupport window functions a la SQL:2008.

WinGetFuncArgInFrame() lines 5278-5308
Modified Lines Coverage: 3/3 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
5278 | - | WinGetFuncArgInFrame(WindowObject winobj, int argno, | -
5279 | - | int relpos, int seektype, bool set_mark, | -
5280 | - | bool *isnull, bool *isout) | -
5281 | - | { | -
5282 | - | WindowAggState *winstate; | -
5283 | - | ExprContext *econtext; | -
5284 | - | TupleTableSlot *slot; | -
5285 | - |  | -
5286 | - | Assert(WindowObjectIsValid(winobj)); | -
5287 | - | winstate = winobj->winstate; | -
5288 | - | econtext = winstate->ss.ps.ps_ExprContext; | -
5289 | - | slot = winstate->temp_slot_1; | -
5290 | - |  | -
5291 | - | if (winobj->ignore_nulls == IGNORE_NULLS) | -
5292 | - | return ignorenulls_getfuncarginframe(winobj, argno, relpos, seektype, | -
5293 | - | set_mark, isnull, isout); | -
5294 | - |  | -
5295 | 1531400 | if (WinGetSlotInFrame(winobj, slot, | 24cfb8dRow pattern recognition patch (executor and commands).
5296 | - | relpos, seektype, set_mark, | 24cfb8dRow pattern recognition patch (executor and commands).
5297 | - | isnull, isout) == 0) | 24cfb8dRow pattern recognition patch (executor and commands).
5298 | - | { | -
5299 | 17292 | econtext->ecxt_outertuple = slot; | 24cfb8dRow pattern recognition patch (executor and commands).
5300 | 17292 | return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno), | 24cfb8dRow pattern recognition patch (executor and commands).
5301 | - | econtext, isnull); | 24cfb8dRow pattern recognition patch (executor and commands).
5302 | - | } | -
5303 | - |  | -
5304 | - | if (isout) | -
5305 | - | *isout = true; | -
5306 | - | *isnull = true; | -
5307 | - | return (Datum) 0; | -
5308 | - | } | -