src/backend/commands/explain.c - Coverage Report

← Back to Overview

# src/backend/commands/explain.c

Coverage: 180/190 lines (94.7%)
Total Lines
190
modified
Covered
180
94.7%
Uncovered
10
5.3%
Keyboard navigation
append_rpr_quantifier() lines 2916-2948
Modified Lines Coverage: 23/23 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
2916 | 3024 | append_rpr_quantifier(StringInfo buf, RPRPatternElement *elem) | 24cfb8dRow pattern recognition patch (executor and commands).
2917 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
2918 | - | /* Append quantifier if not {1,1} */ | 24cfb8dRow pattern recognition patch (executor and commands).
2919 | 3024 | if (elem->min == 0 && elem->max == RPR_QUANTITY_INF) | 24cfb8dRow pattern recognition patch (executor and commands).
2920 | 56 | appendStringInfoChar(buf, '*'); | 24cfb8dRow pattern recognition patch (executor and commands).
2921 | 2968 | else if (elem->min == 1 && elem->max == RPR_QUANTITY_INF) | 24cfb8dRow pattern recognition patch (executor and commands).
2922 | 648 | appendStringInfoChar(buf, '+'); | 24cfb8dRow pattern recognition patch (executor and commands).
2923 | 2320 | else if (elem->min == 0 && elem->max == 1) | 24cfb8dRow pattern recognition patch (executor and commands).
2924 | 36 | appendStringInfoChar(buf, '?'); | 24cfb8dRow pattern recognition patch (executor and commands).
2925 | 2284 | else if (elem->max == RPR_QUANTITY_INF) | 24cfb8dRow pattern recognition patch (executor and commands).
2926 | 140 | appendStringInfo(buf, "{%d,}", elem->min); | 24cfb8dRow pattern recognition patch (executor and commands).
2927 | 2144 | else if (elem->min == elem->max && elem->min != 1) | 24cfb8dRow pattern recognition patch (executor and commands).
2928 | 176 | appendStringInfo(buf, "{%d}", elem->min); | 24cfb8dRow pattern recognition patch (executor and commands).
2929 | 1968 | else if (elem->min != 1 || elem->max != 1) | 24cfb8dRow pattern recognition patch (executor and commands).
2930 | 88 | appendStringInfo(buf, "{%d,%d}", elem->min, elem->max); | 24cfb8dRow pattern recognition patch (executor and commands).
2931 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2932 | 3024 | if (RPRElemIsReluctant(elem)) | 24cfb8dRow pattern recognition patch (executor and commands).
2933 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
2934 | 44 | if (elem->min == 1 && elem->max == 1) | 24cfb8dRow pattern recognition patch (executor and commands).
2935 | 4 | appendStringInfoString(buf, "{1}"); /* make reluctant ? | 24cfb8dRow pattern recognition patch (executor and commands).
2936 | - | * unambiguous */ | 24cfb8dRow pattern recognition patch (executor and commands).
2937 | 44 | appendStringInfoChar(buf, '?'); | 24cfb8dRow pattern recognition patch (executor and commands).
2938 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
2939 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2940 | - | /* Append absorption markers: " for comparison point, ' for branch only */ | 0bc60efRename absorption "judgment point" to "comparison point" in comments
2941 | 3024 | if (RPRElemIsAbsorbable(elem)) | 24cfb8dRow pattern recognition patch (executor and commands).
2942 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
2943 | 452 | Assert(elem->max == RPR_QUANTITY_INF); | 24cfb8dRow pattern recognition patch (executor and commands).
2944 | 452 | appendStringInfoChar(buf, '"'); | 24cfb8dRow pattern recognition patch (executor and commands).
2945 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
2946 | 2572 | else if (RPRElemIsAbsorbableBranch(elem)) | 24cfb8dRow pattern recognition patch (executor and commands).
2947 | 352 | appendStringInfoChar(buf, '\''); | 24cfb8dRow pattern recognition patch (executor and commands).
2948 | 3024 | } | 24cfb8dRow pattern recognition patch (executor and commands).

deparse_rpr_pattern() lines 2983-2992
Modified Lines Coverage: 6/6 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
2983 | 1060 | deparse_rpr_pattern(RPRPattern *pattern) | 24cfb8dRow pattern recognition patch (executor and commands).
2984 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
2985 | 1060 | StringInfoData buf; | 24cfb8dRow pattern recognition patch (executor and commands).
2986 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2987 | 1060 | Assert(pattern != NULL && pattern->numElements >= 2); | 24cfb8dRow pattern recognition patch (executor and commands).
2988 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
2989 | 1060 | initStringInfo(&buf); | 24cfb8dRow pattern recognition patch (executor and commands).
2990 | 1060 | deparse_rpr_seq(pattern, 0, pattern->numElements, &buf); | 24cfb8dRow pattern recognition patch (executor and commands).
2991 | 1060 | return buf.data; | 24cfb8dRow pattern recognition patch (executor and commands).
2992 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

deparse_rpr_seq() lines 3001-3014
Modified Lines Coverage: 9/9 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3001 | 2188 | deparse_rpr_seq(RPRPattern *pattern, int start, int limit, StringInfo buf) | 24cfb8dRow pattern recognition patch (executor and commands).
3002 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3003 | 2188 | int i = start; | 24cfb8dRow pattern recognition patch (executor and commands).
3004 | 2188 | bool first = true; | 24cfb8dRow pattern recognition patch (executor and commands).
3005 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3006 | 5488 | while (i < limit && !RPRElemIsFin(&pattern->elements[i])) | 24cfb8dRow pattern recognition patch (executor and commands).
3007 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3008 | 3300 | if (!first) | 24cfb8dRow pattern recognition patch (executor and commands).
3009 | 1112 | appendStringInfoChar(buf, ' '); | 24cfb8dRow pattern recognition patch (executor and commands).
3010 | 3300 | first = false; | 24cfb8dRow pattern recognition patch (executor and commands).
3011 | 3300 | i = deparse_rpr_node(pattern, i, limit, buf); | 24cfb8dRow pattern recognition patch (executor and commands).
3012 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3013 | 2188 | return i; | 24cfb8dRow pattern recognition patch (executor and commands).
3014 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

deparse_rpr_node() lines 3029-3090
Modified Lines Coverage: 37/38 lines (97.4%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3029 | 3388 | deparse_rpr_node(RPRPattern *pattern, int idx, int limit, StringInfo buf) | 0e23c67Rename loop index variables in row pattern deparse helpers
3030 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3031 | 3388 | RPRPatternElement *elem = &pattern->elements[idx]; | 0e23c67Rename loop index variables in row pattern deparse helpers
3032 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3033 | 3388 | if (RPRElemIsVar(elem)) | 24cfb8dRow pattern recognition patch (executor and commands).
3034 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3035 | 2592 | Assert(elem->varId < pattern->numVars); | 24cfb8dRow pattern recognition patch (executor and commands).
3036 | 2592 | appendStringInfoString(buf, | 24cfb8dRow pattern recognition patch (executor and commands).
3037 | 2592 | quote_identifier(pattern->varNames[elem->varId])); | 24cfb8dRow pattern recognition patch (executor and commands).
3038 | 2592 | append_rpr_quantifier(buf, elem); | 24cfb8dRow pattern recognition patch (executor and commands).
3039 | 2592 | return idx + 1; | 0e23c67Rename loop index variables in row pattern deparse helpers
3040 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3041 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3042 | 796 | if (RPRElemIsBegin(elem)) | 24cfb8dRow pattern recognition patch (executor and commands).
3043 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3044 | 432 | int end = rpr_match_end(pattern, idx); | 0e23c67Rename loop index variables in row pattern deparse helpers
3045 | 432 | bool loneAlt; | 24cfb8dRow pattern recognition patch (executor and commands).
3046 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3047 | 1296 | loneAlt = (idx + 1 < end && | 0e23c67Rename loop index variables in row pattern deparse helpers
3048 | 528 | RPRElemIsAlt(&pattern->elements[idx + 1]) && | 0e23c67Rename loop index variables in row pattern deparse helpers
3049 | 96 | rpr_alt_scope_end(pattern, idx + 1) == end); | 0e23c67Rename loop index variables in row pattern deparse helpers
3050 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3051 | 432 | if (loneAlt) | 24cfb8dRow pattern recognition patch (executor and commands).
3052 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3053 | - | /* The ALT child already parenthesizes the whole group body. */ | 24cfb8dRow pattern recognition patch (executor and commands).
3054 | 88 | (void) deparse_rpr_node(pattern, idx + 1, end, buf); | 0e23c67Rename loop index variables in row pattern deparse helpers
3055 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3056 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3057 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3058 | 344 | appendStringInfoChar(buf, '('); | 24cfb8dRow pattern recognition patch (executor and commands).
3059 | 344 | (void) deparse_rpr_seq(pattern, idx + 1, end, buf); | 0e23c67Rename loop index variables in row pattern deparse helpers
3060 | 344 | appendStringInfoChar(buf, ')'); | 24cfb8dRow pattern recognition patch (executor and commands).
3061 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3062 | 432 | append_rpr_quantifier(buf, &pattern->elements[end]); | 24cfb8dRow pattern recognition patch (executor and commands).
3063 | 432 | return end + 1; | 24cfb8dRow pattern recognition patch (executor and commands).
3064 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3065 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3066 | 364 | Assert(RPRElemIsAlt(elem)); | 24cfb8dRow pattern recognition patch (executor and commands).
3067 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3068 | 364 | int altEnd = rpr_alt_scope_end(pattern, idx); | 0e23c67Rename loop index variables in row pattern deparse helpers
3069 | 364 | int b; | 24cfb8dRow pattern recognition patch (executor and commands).
3070 | 364 | bool first = true; | 24cfb8dRow pattern recognition patch (executor and commands).
3071 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3072 | 364 | if (altEnd > limit) | 24cfb8dRow pattern recognition patch (executor and commands).
3073 | 0 | altEnd = limit; | 24cfb8dRow pattern recognition patch (executor and commands).
| UnreachableDefensive (unreachable) · confidence high · `deparse_rpr_node @3073` Reason
    CONFIRMED unreachable.
    Line 3073 (`altEnd = limit;
    `) only fires when `altEnd > limit`, i.e. when rpr_alt_scope_end(idx) overshoots the inherited limit.
    I traced every call site of deparse_rpr_node's ALT branch and the depth invariants from rpr.c (fillRPRPatternAlt sets ALT marker at depth d, branches at d+1;
    finalizeRPRPattern puts FIN at depth 0;
    rpr_alt_scope_end uses `depth <= d`, so it stops AT the first element whose depth is <= the ALT's depth and never skips a same-or-lower-depth boundary).
    The three possible limits all bound the ALT's scope:
    (1) top-level seq passes limit=numElements;
    an ALT here is at depth 0 and its scope_end stops at FIN (depth 0) or a depth-0 sibling, index <= numElements-1 < limit.
    (2) loneAlt path (line 3054) passes limit=end with the explicit guard rpr_alt_scope_end(idx+1)==end, so altEnd==limit exactly, not >.
    (3) seq inside a non-loneAlt group passes limit=group END index;
    the END sits at depth d_group = d_alt-1 < d_alt, so scope_end stops at or before it, altEnd <= limit.
    Nested ALTs are flattened by flattenAltChildren/optimizeAltPattern and {1,1} groups are unwrapped, so no two ALTs ever share a depth boundary that could push scope past the limit.
    In all cases altEnd <= limit, so `altEnd > limit` is never true.
    The root-cause analysis in the finding is accurate.
Recommended fix
    Replace the silent clamp with an assertion documenting the invariant.
    Change lines 3072-3073 from `if (altEnd > limit) altEnd = limit;
    ` to `Assert(altEnd <= limit);
    `.
    This removes the uncoverable assignment, documents that an ALT's depth-derived scope end never exceeds the inherited limit (guaranteed by the depth invariants in optimizer/plan/rpr.c:
    ALT branches at depth d+1, FIN/END boundaries at depth <= d, and ALT flattening preventing shared boundaries), and still catches any future invariant break in assert-enabled builds.
    The `limit` parameter is otherwise unused after this in the ALT branch, but it is still used by the VAR/BEGIN paths and by the Assert, so keep the parameter.
    Optionally add a one-line comment:
    `/* an ALT's scope end never exceeds the limit handed down (see rpr.c depth invariants) */`.
3074 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3075 | 364 | appendStringInfoChar(buf, '('); | 24cfb8dRow pattern recognition patch (executor and commands).
3076 | 364 | b = idx + 1; | 0e23c67Rename loop index variables in row pattern deparse helpers
3077 | 1148 | while (b < altEnd) | 24cfb8dRow pattern recognition patch (executor and commands).
3078 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3079 | 784 | int nb = rpr_next_branch(pattern, b, altEnd); | 24cfb8dRow pattern recognition patch (executor and commands).
3080 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3081 | 784 | if (!first) | 24cfb8dRow pattern recognition patch (executor and commands).
3082 | 420 | appendStringInfoString(buf, " | "); | 24cfb8dRow pattern recognition patch (executor and commands).
3083 | 784 | first = false; | 24cfb8dRow pattern recognition patch (executor and commands).
3084 | 784 | (void) deparse_rpr_seq(pattern, b, nb, buf); | 24cfb8dRow pattern recognition patch (executor and commands).
3085 | 784 | b = nb; | 24cfb8dRow pattern recognition patch (executor and commands).
3086 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3087 | 364 | appendStringInfoChar(buf, ')'); | 24cfb8dRow pattern recognition patch (executor and commands).
3088 | 364 | return altEnd; | 24cfb8dRow pattern recognition patch (executor and commands).
3089 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3090 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

rpr_match_end() lines 3097-3110
Modified Lines Coverage: 7/8 lines (87.5%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3097 | 432 | rpr_match_end(RPRPattern *pattern, int beginIdx) | 24cfb8dRow pattern recognition patch (executor and commands).
3098 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3099 | 432 | RPRDepth d = pattern->elements[beginIdx].depth; | 24cfb8dRow pattern recognition patch (executor and commands).
3100 | 432 | int i; | 0e23c67Rename loop index variables in row pattern deparse helpers
3101 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3102 | 1564 | for (i = beginIdx + 1; i < pattern->numElements; i++) | 0e23c67Rename loop index variables in row pattern deparse helpers
3103 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3104 | 1564 | RPRPatternElement *e = &pattern->elements[i]; | 0e23c67Rename loop index variables in row pattern deparse helpers
3105 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3106 | 1564 | if (RPRElemIsEnd(e) && e->depth == d) | 24cfb8dRow pattern recognition patch (executor and commands).
3107 | 432 | return i; | 0e23c67Rename loop index variables in row pattern deparse helpers
3108 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3109 | 0 | pg_unreachable(); /* a BEGIN always has a matching END */ | 24cfb8dRow pattern recognition patch (executor and commands).
| UnreachableDefensive (unreachable) · confidence high · `rpr_match_end @3109` Reason
    CONFIRMED defensive-unreachable.
    Line 3109 is `pg_unreachable()` placed after a for-loop that always returns. rpr_match_end (explain.c:3096-3110) is called only from the RPRElemIsBegin branch (explain.c:3044).
    In fillRPRPatternGroup (rpr.c:1226-1294) the BEGIN marker (lines 1233-1252) and the matching END marker (lines 1261-1291) are emitted under the IDENTICAL guard `node->min != 1 || node->max != 1` and share the same `depth` parameter.
    Children recurse at depth+1, so their END markers (deeper depth) are skipped by the `e->depth == d` test, and the first same-depth END (the real partner) is always present after beginIdx.
    Thus the loop (3102-3108) always returns before falling through.
    Round-trip serialization (-DWRITE_READ_PARSE_PLAN_TREES) copies the elements array verbatim preserving varId/depth, so it cannot introduce an unpaired BEGIN.
    No SQL/regression input or node rewrite can reach line 3109. Tried to refute via nested groups, ALT children (which emit no BEGIN/END VARID markers), and the copy/out/read round-trip;
    none break the pairing invariant. pg_unreachable() is the correct idiom and is intentionally excluded from meaningful coverage.
Recommended fix
    No change needed.
    The line is `pg_unreachable()`, the correct defensive idiom for a code path guaranteed unreachable by the BEGIN/END pairing invariant.
    Leave as is;
    it is appropriately excluded from meaningful coverage.
3110 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

rpr_alt_scope_end() lines 3119-3130
Modified Lines Coverage: 5/5 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3119 | 460 | rpr_alt_scope_end(RPRPattern *pattern, int idx) | 0e23c67Rename loop index variables in row pattern deparse helpers
3120 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3121 | 460 | RPRDepth d = pattern->elements[idx].depth; | 0e23c67Rename loop index variables in row pattern deparse helpers
3122 | 460 | int i; | 0e23c67Rename loop index variables in row pattern deparse helpers
3123 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3124 | 2176 | for (i = idx + 1; i < pattern->numElements; i++) | 0e23c67Rename loop index variables in row pattern deparse helpers
3125 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3126 | 2176 | if (pattern->elements[i].depth <= d) | 0e23c67Rename loop index variables in row pattern deparse helpers
3127 | - | return i; | 0e23c67Rename loop index variables in row pattern deparse helpers
3128 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3129 | - | return pattern->numElements; | 24cfb8dRow pattern recognition patch (executor and commands).
3130 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

rpr_next_branch() lines 3143-3151
Modified Lines Coverage: 5/5 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3143 | 784 | rpr_next_branch(RPRPattern *pattern, int bno, int altEnd) | 0e23c67Rename loop index variables in row pattern deparse helpers
3144 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3145 | 784 | int j = pattern->elements[bno].jump; | 0e23c67Rename loop index variables in row pattern deparse helpers
3146 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3147 | 784 | if (j != RPR_ELEMIDX_INVALID && j < altEnd && | 24cfb8dRow pattern recognition patch (executor and commands).
3148 | 424 | pattern->elements[j - 1].next != j) | 24cfb8dRow pattern recognition patch (executor and commands).
3149 | 420 | return j; | 24cfb8dRow pattern recognition patch (executor and commands).
3150 | - | return altEnd; | 24cfb8dRow pattern recognition patch (executor and commands).
3151 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

show_window_def() lines 3157-3284
Modified Lines Coverage: 26/34 lines (76.5%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3157 | - | show_window_def(WindowAggState *planstate, List *ancestors, ExplainState *es) | -
3158 | - | { | -
3159 | - | WindowAgg *wagg = (WindowAgg *) planstate->ss.ps.plan; | -
3160 | - | StringInfoData wbuf; | -
3161 | - | bool needspace = false; | -
3162 | - |  | -
3163 | - | initStringInfo(&wbuf); | -
3164 | - | appendStringInfo(&wbuf, "%s AS (", quote_identifier(wagg->winname)); | -
3165 | - |  | -
3166 | - | /* The key columns refer to the tlist of the child plan */ | -
3167 | - | ancestors = lcons(wagg, ancestors); | -
3168 | - | if (wagg->partNumCols > 0) | -
3169 | - | { | -
3170 | - | appendStringInfoString(&wbuf, "PARTITION BY "); | -
3171 | - | show_window_keys(&wbuf, outerPlanState(planstate), | -
3172 | - | wagg->partNumCols, wagg->partColIdx, | -
3173 | - | ancestors, es); | -
3174 | - | needspace = true; | -
3175 | - | } | -
3176 | - | if (wagg->ordNumCols > 0) | -
3177 | - | { | -
3178 | - | if (needspace) | -
3179 | - | appendStringInfoChar(&wbuf, ' '); | -
3180 | - | appendStringInfoString(&wbuf, "ORDER BY "); | -
3181 | - | show_window_keys(&wbuf, outerPlanState(planstate), | -
3182 | - | wagg->ordNumCols, wagg->ordColIdx, | -
3183 | - | ancestors, es); | -
3184 | - | needspace = true; | -
3185 | - | } | -
3186 | - | ancestors = list_delete_first(ancestors); | -
3187 | - | if (wagg->frameOptions & FRAMEOPTION_NONDEFAULT) | -
3188 | - | { | -
3189 | - | List *context; | -
3190 | - | bool useprefix; | -
3191 | - | char *framestr; | -
3192 | - |  | -
3193 | - | /* Set up deparsing context for possible frame expressions */ | -
3194 | - | context = set_deparse_context_plan(es->deparse_cxt, | -
3195 | - | (Plan *) wagg, | -
3196 | - | ancestors); | -
3197 | - | useprefix = (es->rtable_size > 1 || es->verbose); | -
3198 | - | framestr = get_window_frame_options_for_explain(wagg->frameOptions, | -
3199 | - | wagg->startOffset, | -
3200 | - | wagg->endOffset, | -
3201 | - | context, | -
3202 | - | useprefix); | -
3203 | - | if (needspace) | -
3204 | - | appendStringInfoChar(&wbuf, ' '); | -
3205 | - | appendStringInfoString(&wbuf, framestr); | -
3206 | - | pfree(framestr); | -
3207 | - | } | -
3208 | - | appendStringInfoChar(&wbuf, ')'); | -
3209 | - | ExplainPropertyText("Window", wbuf.data, es); | -
3210 | - | pfree(wbuf.data); | -
3211 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3212 | - | /* Show Row Pattern Recognition pattern if present */ | 24cfb8dRow pattern recognition patch (executor and commands).
3213 | 1412 | if (wagg->rpPattern != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
3214 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3215 | 1060 | RPRNavOffsetKind maxKind = wagg->navMaxOffsetKind; | b848408Tidy up row pattern recognition plumbing
3216 | 1060 | int64 maxOffset = wagg->navMaxOffset; | b848408Tidy up row pattern recognition plumbing
3217 | 1060 | RPRNavOffsetKind firstKind = wagg->navFirstOffsetKind; | b848408Tidy up row pattern recognition plumbing
3218 | 1060 | int64 firstOffset = wagg->navFirstOffset; | b848408Tidy up row pattern recognition plumbing
3219 | - |  | b848408Tidy up row pattern recognition plumbing
3220 | 1060 | char *patternStr = deparse_rpr_pattern(wagg->rpPattern); | 24cfb8dRow pattern recognition patch (executor and commands).
3221 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3222 | 1060 | ExplainPropertyText("Pattern", patternStr, es); | b848408Tidy up row pattern recognition plumbing
3223 | - |  | b848408Tidy up row pattern recognition plumbing
3224 | 1060 | pfree(patternStr); | b848408Tidy up row pattern recognition plumbing
3225 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3226 | - | /* | 24cfb8dRow pattern recognition patch (executor and commands).
3227 | - | * Show navigation offsets for tuplestore trim. For EXPLAIN ANALYZE, | 24cfb8dRow pattern recognition patch (executor and commands).
3228 | - | * use the executor-resolved values (which may differ from the plan | 24cfb8dRow pattern recognition patch (executor and commands).
3229 | - | * when NEEDS_EVAL was resolved to FIXED or RETAIN_ALL at init). | 24cfb8dRow pattern recognition patch (executor and commands).
3230 | - | */ | 24cfb8dRow pattern recognition patch (executor and commands).
3231 | 1060 | if (es->analyze) | b848408Tidy up row pattern recognition plumbing
3232 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3233 | 500 | maxKind = planstate->navMaxOffsetKind; | b848408Tidy up row pattern recognition plumbing
3234 | 500 | maxOffset = planstate->navMaxOffset; | b848408Tidy up row pattern recognition plumbing
3235 | 500 | firstKind = planstate->navFirstOffsetKind; | b848408Tidy up row pattern recognition plumbing
3236 | 500 | firstOffset = planstate->navFirstOffset; | b848408Tidy up row pattern recognition plumbing
3237 | - | } | b848408Tidy up row pattern recognition plumbing
3238 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3239 | 1060 | switch (maxKind) | b848408Tidy up row pattern recognition plumbing
3240 | - | { | b848408Tidy up row pattern recognition plumbing
3241 | 12 | case RPR_NAV_OFFSET_NEEDS_EVAL: | b848408Tidy up row pattern recognition plumbing
3242 | 12 | ExplainPropertyText("Nav Mark Lookback", "runtime", es); | b848408Tidy up row pattern recognition plumbing
3243 | - | break; | b848408Tidy up row pattern recognition plumbing
3244 | 8 | case RPR_NAV_OFFSET_RETAIN_ALL: | b848408Tidy up row pattern recognition plumbing
3245 | 8 | ExplainPropertyText("Nav Mark Lookback", "retain all", es); | b848408Tidy up row pattern recognition plumbing
3246 | - | break; | b848408Tidy up row pattern recognition plumbing
3247 | 1040 | case RPR_NAV_OFFSET_FIXED: | b848408Tidy up row pattern recognition plumbing
3248 | 1040 | ExplainPropertyInteger("Nav Mark Lookback", NULL, | b848408Tidy up row pattern recognition plumbing
3249 | - | maxOffset, es); | b848408Tidy up row pattern recognition plumbing
3250 | - | break; | b848408Tidy up row pattern recognition plumbing
3251 | 0 | default: | b848408Tidy up row pattern recognition plumbing
| UnreachableDefensive (unreachable) · confidence high · `show_window_def @3251-3252` · 2 lines Reason
    Confirmed defensive-unreachable.
    Lines 3251-3253 are the default: arm (elog(ERROR, "unrecognized RPR nav offset kind: %d", maxKind)) of the "Nav Mark Lookback" switch over maxKind, which is of type RPRNavOffsetKind.
    The enum (parsenodes.h:604-610) has exactly three values:
    RPR_NAV_OFFSET_FIXED, RPR_NAV_OFFSET_NEEDS_EVAL, RPR_NAV_OFFSET_RETAIN_ALL, all three handled by the preceding case arms (lines 3241-3249). maxKind is sourced from wagg->navMaxOffsetKind or (under es->analyze) planstate->navMaxOffsetKind.
    Every assignment to these fields in the backend uses one of the three valid enumerators: createplan.c:2826/7046 (FIXED), nodeWindowAgg.c:3042 (copies plan value), nodeWindowAgg.c:4194 (RETAIN_ALL), nodeWindowAgg.c:4199 (FIXED).
    No code path assigns an out-of-range value, so no SQL/regression input can drive execution into the default.
    Reaching it would require memory corruption or addition of a new enumerator without updating the switch.
    This is a standard PostgreSQL can't-happen guard.
    The original finding (no test proposed) is correct.
Recommended fix
    No action required.
    The elog(ERROR) default is the established PostgreSQL convention for enum switch-default guards and should be kept for robustness against future enum additions.
    Optionally it could be reduced to Assert(false) but that would weaken protection in production builds;
    keeping elog(ERROR) is preferable.
    Leave as-is and accept the 2 uncovered lines as defensive code.
3252 | 0 | elog(ERROR, "unrecognized RPR nav offset kind: %d", | b848408Tidy up row pattern recognition plumbing
3253 | - | maxKind); | b848408Tidy up row pattern recognition plumbing
3254 | - | break; | b848408Tidy up row pattern recognition plumbing
3255 | - | } | b848408Tidy up row pattern recognition plumbing
3256 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3257 | 1060 | if (wagg->hasFirstNav) | b848408Tidy up row pattern recognition plumbing
3258 | - | { | b848408Tidy up row pattern recognition plumbing
3259 | 28 | switch (firstKind) | b848408Tidy up row pattern recognition plumbing
3260 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3261 | 0 | case RPR_NAV_OFFSET_NEEDS_EVAL: | 24cfb8dRow pattern recognition patch (executor and commands).
| ReachableTestable · confidence high · `show_window_def @3261-3262` · 2 lines How to test
    Proposed test works as-is and is empirically verified.
    Add to rpr_explain.sql (mirrors the existing test_overflow_lookahead but plain EXPLAIN on the Lookahead dimension):

    PREPARE p_first_runtime(int8, int8) AS
    SELECT count(*) OVER w
    FROM generate_series(1,10) s(v)
    WINDOW w AS (
    ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
    PATTERN (A+)
    DEFINE A AS NEXT(FIRST(v, $1), $2) IS NOT NULL
    );
    SET plan_cache_mode = force_generic_plan;
    EXPLAIN (COSTS OFF)
    EXECUTE p_first_runtime(1, 1);
    RESET plan_cache_mode;
    DEALLOCATE p_first_runtime;

    Expected output (verified live):
     WindowAgg
       Window: w AS (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
       Pattern: a+
       Nav Mark Lookback: 0
       Nav Mark Lookahead: runtime
       ->  Function Scan on generate_series s

    A simpler equivalent that also covers the lines:
    DEFINE A AS FIRST(v, $1) IS NOT NULL (a bare RPR_NAV_FIRST with a Param offset also sets hasFirst + firstNeedsEval).
    The compound NEXT(FIRST(...)) form is fine and matches the existing test family's style.
Verdict
    CONFIRMED testable and the proposed test covers the exact lines.
    Lines 3261-3263 are the RPR_NAV_OFFSET_NEEDS_EVAL arm of the Lookahead switch (gated by wagg->hasFirstNav at explain.c:3257), printing "Nav Mark Lookahead: runtime".
    Root cause is accurate: when !es->analyze, firstKind = wagg->navFirstOffsetKind from the plan (explain.c:3231-3237 only overrides with executor-resolved values for ANALYZE).
    At plan time, a non-Const offset arg makes extract_const_offset return false (createplan.c:2502-2526), setting ctx.firstNeedsEval -> navFirstOffsetKind = NEEDS_EVAL (createplan.c:2780-2784).
    NEXT_FIRST also sets hasFirst=true (createplan.c:2653-2656), so the Lookahead block runs.
    The existing test_overflow_lookahead (rpr_explain.out:5998-6022) uses ONLY EXPLAIN ANALYZE on this dimension, which resolves NEEDS_EVAL to FIXED/infinite at executor init, hitting the FIXED arm (3269-3275).
    The plain-EXPLAIN "runtime" case is only exercised on the LookBACK dimension (test_overflow_lookback line 5971 -> line 3242), never Lookahead. grep confirms NO expected .out file contains "Nav Mark Lookahead: runtime".
    I EMPIRICALLY ran the proposed test against a freshly initdb'd v19 RPR cluster (the installed binary was a control-version ahead of PGDATA, so I built a temp cluster): plain EXPLAIN (COSTS OFF) of the parameterized NEXT(FIRST(v,$1),$2) query under force_generic_plan produced exactly "Nav Mark Lookback: 0" and "Nav Mark Lookahead: runtime", proving execution flows through lines 3261-3263. Note: the orchestrator labeled these as lines 3261-3262, but the ExplainPropertyText call spans 3262-3263;
    the case label is 3261. The 2-line count is fine and the test covers all of them.
3262 | 0 | ExplainPropertyText("Nav Mark Lookahead", "runtime", | b848408Tidy up row pattern recognition plumbing
3263 | - | es); | b848408Tidy up row pattern recognition plumbing
3264 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
3265 | 0 | case RPR_NAV_OFFSET_RETAIN_ALL: | 24cfb8dRow pattern recognition patch (executor and commands).
| UnreachableDefensive (unreachable) · confidence high · `show_window_def @3265-3266` · 2 lines Reason
    CONFIRMED unreachable.
    Lines 3265-3266 are the RPR_NAV_OFFSET_RETAIN_ALL arm of the firstKind (Nav Mark Lookahead) switch.
    I traced every writer of navFirstOffsetKind in the entire tree:
    (1) createplan.c:7049 copies the local value computed by compute_define_metadata, which assigns *firstKind ONLY to NEEDS_EVAL (2782), FIXED (2787), or FIXED (2794) -- never RETAIN_ALL;
    RETAIN_ALL is set ONLY for *maxKind on backward-reach overflow (2762).
    (2) nodeWindowAgg.c:3045 copies the plan value into exec state.
    (3) nodeWindowAgg.c:4206 (eval_define_offsets, the NEEDS_EVAL late-binding path) sets navFirstOffsetKind ONLY to FIXED;
    first-offset overflow is handled by clamping navFirstOffset to PG_INT64_MAX while keeping kind FIXED (4210), which is exactly why the FIXED arm at 3270-3272 prints 'infinite' instead of a RETAIN_ALL path.
    The RPR authors even added Assert(winstate->navFirstOffsetKind == RPR_NAV_OFFSET_FIXED) at nodeWindowAgg.c:4405, self-documenting that the lookahead/first dimension is structurally never RETAIN_ALL.
    I could not construct any SQL input (FIRST/PREV_FIRST/NEXT_FIRST with any quantifier or huge offset) that yields RETAIN_ALL for the first dimension, because overflow on that dimension clamps to FIXED+INT64_MAX rather than RETAIN_ALL.
    The arm exists purely for switch completeness (its sibling default already elog(ERROR)s on unrecognized kinds).
    The root-cause analysis in the finding is accurate.
Recommended fix
    Remove the dead RPR_NAV_OFFSET_RETAIN_ALL arm from the firstKind (Lookahead) switch in show_window_def.
    The default arm already does elog(ERROR, "unrecognized RPR nav offset kind: %d", firstKind), so deleting lines 3265-3268 keeps behavior identical while eliminating the permanently-uncoverable lines and correctly documenting (consistent with the Assert at nodeWindowAgg.c:4405) that the lookahead/first dimension never retains-all.
    If the authors prefer to keep all enum arms explicit for symmetry with the maxKind switch, add a brief comment '/* lookahead dimension never overflows to RETAIN_ALL;
    see eval_define_offsets */' and accept the 2 uncovered lines, or replace the arm body with Assert(false) to make the intent explicit.
    Folding into default is the cleanest.
3266 | 0 | ExplainPropertyText("Nav Mark Lookahead", "retain all", | b848408Tidy up row pattern recognition plumbing
3267 | - | es); | b848408Tidy up row pattern recognition plumbing
3268 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
3269 | 28 | case RPR_NAV_OFFSET_FIXED: | 24cfb8dRow pattern recognition patch (executor and commands).
3270 | 28 | if (firstOffset == PG_INT64_MAX) | b848408Tidy up row pattern recognition plumbing
3271 | 8 | ExplainPropertyText("Nav Mark Lookahead", "infinite", | b848408Tidy up row pattern recognition plumbing
3272 | - | es); | b848408Tidy up row pattern recognition plumbing
3273 | - | else | b848408Tidy up row pattern recognition plumbing
3274 | 20 | ExplainPropertyInteger("Nav Mark Lookahead", NULL, | b848408Tidy up row pattern recognition plumbing
3275 | - | firstOffset, es); | b848408Tidy up row pattern recognition plumbing
3276 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
3277 | 0 | default: | 24cfb8dRow pattern recognition patch (executor and commands).
| UnreachableDefensive (unreachable) · confidence high · `show_window_def @3277-3278` · 2 lines Reason
    Confirmed defensive-unreachable.
    Lines 3277-3278 are the default: arm (elog(ERROR, "unrecognized RPR nav offset kind: %d", firstKind)) of the Lookahead switch over firstKind, a strongly-typed RPRNavOffsetKind.
    The enum (src/include/nodes/parsenodes.h:605-609) has exactly three enumerators:
    RPR_NAV_OFFSET_FIXED, RPR_NAV_OFFSET_NEEDS_EVAL, RPR_NAV_OFFSET_RETAIN_ALL, and the switch (explain.c:3261/3265/3269) explicitly handles all three. firstKind is sourced either from wagg->navFirstOffsetKind (plan node, set by compute_define_metadata in createplan.c, default FIXED) or, under EXPLAIN ANALYZE, from planstate->navFirstOffsetKind (set in nodeWindowAgg.c:3045/4206, only ever FIXED/NEEDS_EVAL/RETAIN_ALL;
    an Assert at 4405 even pins it to FIXED on the eval path).
    No SQL or regression input can assign a 4th value;
    reaching the default would require memory corruption.
    I tried to refute by tracing every producer of the field and found none that can emit an out-of-range value.
    This matches the already-confirmed Lookback default at 3251-3253. Switch is additionally guarded by if (wagg->hasFirstNav) but that does not change reachability of the default within the switch.
Recommended fix
    Acceptable as the standard enum switch-default guard following PostgreSQL convention (mirrors the Lookback default at 3251-3253).
    No action required.
    The existing elog(ERROR, ...) is the idiomatic in-tree form for unrecognized-enum defaults, so keeping it as-is is preferable to switching to Assert(false) for consistency with the sibling switch.
3278 | 0 | elog(ERROR, "unrecognized RPR nav offset kind: %d", | 24cfb8dRow pattern recognition patch (executor and commands).
3279 | - | firstKind); | b848408Tidy up row pattern recognition plumbing
3280 | - | break; | 24cfb8dRow pattern recognition patch (executor and commands).
3281 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3282 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3283 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3284 | - | } | -

show_windowagg_info() lines 3832-3853
Modified Lines Coverage: 3/3 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3832 | - | show_windowagg_info(WindowAggState *winstate, ExplainState *es) | -
3833 | - | { | -
3834 | - | char *maxStorageType; | -
3835 | - | int64 maxSpaceUsed; | -
3836 | 1412 | WindowAgg *wagg = (WindowAgg *) winstate->ss.ps.plan; | 24cfb8dRow pattern recognition patch (executor and commands).
3837 | - |  | -
3838 | - | Tuplestorestate *tupstore = winstate->buffer; | -
3839 | - |  | -
3840 | - | /* | -
3841 | - | * Nothing to show if ANALYZE option wasn't used or if execution didn't | -
3842 | - | * get as far as creating the tuplestore. | -
3843 | - | */ | -
3844 | - | if (!es->analyze || tupstore == NULL) | -
3845 | - | return; | -
3846 | - |  | -
3847 | - | tuplestore_get_stats(tupstore, &maxStorageType, &maxSpaceUsed); | -
3848 | - | show_storage_info(maxStorageType, maxSpaceUsed, es); | -
3849 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3850 | - | /* Show NFA statistics for Row Pattern Recognition */ | 24cfb8dRow pattern recognition patch (executor and commands).
3851 | 508 | if (wagg->rpPattern != NULL) | 24cfb8dRow pattern recognition patch (executor and commands).
3852 | 496 | show_rpr_nfa_stats(winstate, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3853 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).

show_rpr_nfa_stats() lines 3859-4003
Modified Lines Coverage: 59/59 lines (100.0%)

Line | Hits | Source | Commit
--- | --- | --- | ---
3859 | 496 | show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) | 24cfb8dRow pattern recognition patch (executor and commands).
3860 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3861 | 496 | if (es->format != EXPLAIN_FORMAT_TEXT) | 24cfb8dRow pattern recognition patch (executor and commands).
3862 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3863 | - | /* State and context counters */ | 24cfb8dRow pattern recognition patch (executor and commands).
3864 | 20 | ExplainPropertyInteger("NFA States Peak", NULL, winstate->nfaStatesMax, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3865 | 20 | ExplainPropertyInteger("NFA States Total", NULL, winstate->nfaStatesTotalCreated, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3866 | 20 | ExplainPropertyInteger("NFA States Merged", NULL, winstate->nfaStatesMerged, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3867 | 20 | ExplainPropertyInteger("NFA Contexts Peak", NULL, winstate->nfaContextsMax, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3868 | 20 | ExplainPropertyInteger("NFA Contexts Total", NULL, winstate->nfaContextsTotalCreated, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3869 | 20 | ExplainPropertyInteger("NFA Contexts Absorbed", NULL, winstate->nfaContextsAbsorbed, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3870 | 20 | ExplainPropertyInteger("NFA Contexts Skipped", NULL, winstate->nfaContextsSkipped, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3871 | 20 | ExplainPropertyInteger("NFA Contexts Pruned", NULL, winstate->nfaContextsPruned, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3872 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3873 | - | /* Match/mismatch counts and length statistics */ | 24cfb8dRow pattern recognition patch (executor and commands).
3874 | 20 | ExplainPropertyInteger("NFA Matched", NULL, winstate->nfaMatchesSucceeded, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3875 | 20 | ExplainPropertyInteger("NFA Mismatched", NULL, winstate->nfaMatchesFailed, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3876 | 20 | if (winstate->nfaMatchesSucceeded > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3877 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3878 | 20 | ExplainPropertyInteger("NFA Match Length Min", NULL, winstate->nfaMatchLen.min, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3879 | 20 | ExplainPropertyInteger("NFA Match Length Max", NULL, winstate->nfaMatchLen.max, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3880 | 20 | ExplainPropertyFloat("NFA Match Length Avg", NULL, | 24cfb8dRow pattern recognition patch (executor and commands).
3881 | 20 | (double) winstate->nfaMatchLen.total / winstate->nfaMatchesSucceeded, 1, | 24cfb8dRow pattern recognition patch (executor and commands).
3882 | - | es); | 24cfb8dRow pattern recognition patch (executor and commands).
3883 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3884 | 20 | if (winstate->nfaMatchesFailed > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3885 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3886 | 8 | ExplainPropertyInteger("NFA Mismatch Length Min", NULL, winstate->nfaFailLen.min, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3887 | 8 | ExplainPropertyInteger("NFA Mismatch Length Max", NULL, winstate->nfaFailLen.max, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3888 | 8 | ExplainPropertyFloat("NFA Mismatch Length Avg", NULL, | 24cfb8dRow pattern recognition patch (executor and commands).
3889 | 8 | (double) winstate->nfaFailLen.total / winstate->nfaMatchesFailed, 1, | 24cfb8dRow pattern recognition patch (executor and commands).
3890 | - | es); | 24cfb8dRow pattern recognition patch (executor and commands).
3891 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3892 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3893 | - | /* Absorbed/skipped context length statistics */ | 24cfb8dRow pattern recognition patch (executor and commands).
3894 | 20 | if (winstate->nfaContextsAbsorbed > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3895 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3896 | 4 | ExplainPropertyInteger("NFA Absorbed Length Min", NULL, winstate->nfaAbsorbedLen.min, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3897 | 4 | ExplainPropertyInteger("NFA Absorbed Length Max", NULL, winstate->nfaAbsorbedLen.max, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3898 | 4 | ExplainPropertyFloat("NFA Absorbed Length Avg", NULL, | 24cfb8dRow pattern recognition patch (executor and commands).
3899 | 4 | (double) winstate->nfaAbsorbedLen.total / winstate->nfaContextsAbsorbed, 1, | 24cfb8dRow pattern recognition patch (executor and commands).
3900 | - | es); | 24cfb8dRow pattern recognition patch (executor and commands).
3901 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3902 | 20 | if (winstate->nfaContextsSkipped > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3903 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3904 | 20 | ExplainPropertyInteger("NFA Skipped Length Min", NULL, winstate->nfaSkippedLen.min, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3905 | 20 | ExplainPropertyInteger("NFA Skipped Length Max", NULL, winstate->nfaSkippedLen.max, es); | 24cfb8dRow pattern recognition patch (executor and commands).
3906 | 20 | ExplainPropertyFloat("NFA Skipped Length Avg", NULL, | 24cfb8dRow pattern recognition patch (executor and commands).
3907 | 20 | (double) winstate->nfaSkippedLen.total / winstate->nfaContextsSkipped, 1, | 24cfb8dRow pattern recognition patch (executor and commands).
3908 | - | es); | 24cfb8dRow pattern recognition patch (executor and commands).
3909 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3910 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3911 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3912 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3913 | - | /* State and context counters */ | 24cfb8dRow pattern recognition patch (executor and commands).
3914 | 476 | ExplainIndentText(es); | 24cfb8dRow pattern recognition patch (executor and commands).
3915 | 476 | appendStringInfo(es->str, | 24cfb8dRow pattern recognition patch (executor and commands).
3916 | - | "NFA States: " INT64_FORMAT " peak, " INT64_FORMAT " total, " INT64_FORMAT " merged\n", | 24cfb8dRow pattern recognition patch (executor and commands).
3917 | - | winstate->nfaStatesMax, | 24cfb8dRow pattern recognition patch (executor and commands).
3918 | - | winstate->nfaStatesTotalCreated, | 24cfb8dRow pattern recognition patch (executor and commands).
3919 | - | winstate->nfaStatesMerged); | 24cfb8dRow pattern recognition patch (executor and commands).
3920 | 476 | ExplainIndentText(es); | 24cfb8dRow pattern recognition patch (executor and commands).
3921 | 476 | appendStringInfo(es->str, | 24cfb8dRow pattern recognition patch (executor and commands).
3922 | - | "NFA Contexts: " INT64_FORMAT " peak, " INT64_FORMAT " total, " INT64_FORMAT " pruned\n", | 24cfb8dRow pattern recognition patch (executor and commands).
3923 | - | winstate->nfaContextsMax, | 24cfb8dRow pattern recognition patch (executor and commands).
3924 | - | winstate->nfaContextsTotalCreated, | 24cfb8dRow pattern recognition patch (executor and commands).
3925 | - | winstate->nfaContextsPruned); | 24cfb8dRow pattern recognition patch (executor and commands).
3926 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3927 | - | /* Match/mismatch counts with length min/max/avg */ | 24cfb8dRow pattern recognition patch (executor and commands).
3928 | 476 | ExplainIndentText(es); | 24cfb8dRow pattern recognition patch (executor and commands).
3929 | 476 | appendStringInfoString(es->str, "NFA: "); | 24cfb8dRow pattern recognition patch (executor and commands).
3930 | 476 | if (winstate->nfaMatchesSucceeded > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3931 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3932 | 448 | double avgLen = (double) winstate->nfaMatchLen.total / winstate->nfaMatchesSucceeded; | 24cfb8dRow pattern recognition patch (executor and commands).
3933 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3934 | 448 | appendStringInfo(es->str, | 24cfb8dRow pattern recognition patch (executor and commands).
3935 | - | INT64_FORMAT " matched (len " INT64_FORMAT "/" INT64_FORMAT "/%.1f)", | 24cfb8dRow pattern recognition patch (executor and commands).
3936 | - | winstate->nfaMatchesSucceeded, | 24cfb8dRow pattern recognition patch (executor and commands).
3937 | - | winstate->nfaMatchLen.min, | 24cfb8dRow pattern recognition patch (executor and commands).
3938 | - | winstate->nfaMatchLen.max, | 24cfb8dRow pattern recognition patch (executor and commands).
3939 | - | avgLen); | 24cfb8dRow pattern recognition patch (executor and commands).
3940 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3941 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3942 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3943 | 28 | appendStringInfoString(es->str, "0 matched"); | 24cfb8dRow pattern recognition patch (executor and commands).
3944 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3945 | 476 | if (winstate->nfaMatchesFailed > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3946 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3947 | 140 | double avgFail = (double) winstate->nfaFailLen.total / winstate->nfaMatchesFailed; | 24cfb8dRow pattern recognition patch (executor and commands).
3948 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3949 | 140 | appendStringInfo(es->str, | 24cfb8dRow pattern recognition patch (executor and commands).
3950 | - | ", " INT64_FORMAT " mismatched (len " INT64_FORMAT "/" INT64_FORMAT "/%.1f)", | 24cfb8dRow pattern recognition patch (executor and commands).
3951 | - | winstate->nfaMatchesFailed, | 24cfb8dRow pattern recognition patch (executor and commands).
3952 | - | winstate->nfaFailLen.min, | 24cfb8dRow pattern recognition patch (executor and commands).
3953 | - | winstate->nfaFailLen.max, | 24cfb8dRow pattern recognition patch (executor and commands).
3954 | - | avgFail); | 24cfb8dRow pattern recognition patch (executor and commands).
3955 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3956 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3957 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3958 | 336 | appendStringInfoString(es->str, ", 0 mismatched"); | 24cfb8dRow pattern recognition patch (executor and commands).
3959 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3960 | 476 | appendStringInfoChar(es->str, '\n'); | 24cfb8dRow pattern recognition patch (executor and commands).
3961 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3962 | - | /* Absorbed/skipped context length statistics */ | 24cfb8dRow pattern recognition patch (executor and commands).
3963 | 476 | if (winstate->nfaContextsAbsorbed > 0 || winstate->nfaContextsSkipped > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3964 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3965 | 380 | ExplainIndentText(es); | 24cfb8dRow pattern recognition patch (executor and commands).
3966 | 380 | appendStringInfoString(es->str, "NFA: "); | 24cfb8dRow pattern recognition patch (executor and commands).
3967 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3968 | 380 | if (winstate->nfaContextsAbsorbed > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3969 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3970 | 148 | double avgAbsorbed = (double) winstate->nfaAbsorbedLen.total / winstate->nfaContextsAbsorbed; | 24cfb8dRow pattern recognition patch (executor and commands).
3971 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3972 | 148 | appendStringInfo(es->str, | 24cfb8dRow pattern recognition patch (executor and commands).
3973 | - | INT64_FORMAT " absorbed (len " INT64_FORMAT "/" INT64_FORMAT "/%.1f)", | 24cfb8dRow pattern recognition patch (executor and commands).
3974 | - | winstate->nfaContextsAbsorbed, | 24cfb8dRow pattern recognition patch (executor and commands).
3975 | - | winstate->nfaAbsorbedLen.min, | 24cfb8dRow pattern recognition patch (executor and commands).
3976 | - | winstate->nfaAbsorbedLen.max, | 24cfb8dRow pattern recognition patch (executor and commands).
3977 | - | avgAbsorbed); | 24cfb8dRow pattern recognition patch (executor and commands).
3978 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3979 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3980 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3981 | 232 | appendStringInfoString(es->str, "0 absorbed"); | 24cfb8dRow pattern recognition patch (executor and commands).
3982 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3983 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3984 | 380 | if (winstate->nfaContextsSkipped > 0) | 24cfb8dRow pattern recognition patch (executor and commands).
3985 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3986 | 364 | double avgSkipped = (double) winstate->nfaSkippedLen.total / winstate->nfaContextsSkipped; | 24cfb8dRow pattern recognition patch (executor and commands).
3987 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
3988 | 364 | appendStringInfo(es->str, | 24cfb8dRow pattern recognition patch (executor and commands).
3989 | - | ", " INT64_FORMAT " skipped (len " INT64_FORMAT "/" INT64_FORMAT "/%.1f)", | 24cfb8dRow pattern recognition patch (executor and commands).
3990 | - | winstate->nfaContextsSkipped, | 24cfb8dRow pattern recognition patch (executor and commands).
3991 | - | winstate->nfaSkippedLen.min, | 24cfb8dRow pattern recognition patch (executor and commands).
3992 | - | winstate->nfaSkippedLen.max, | 24cfb8dRow pattern recognition patch (executor and commands).
3993 | - | avgSkipped); | 24cfb8dRow pattern recognition patch (executor and commands).
3994 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3995 | - | else | 24cfb8dRow pattern recognition patch (executor and commands).
3996 | - | { | 24cfb8dRow pattern recognition patch (executor and commands).
3997 | 16 | appendStringInfoString(es->str, ", 0 skipped"); | 24cfb8dRow pattern recognition patch (executor and commands).
3998 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
3999 | - |  | 24cfb8dRow pattern recognition patch (executor and commands).
4000 | 380 | appendStringInfoChar(es->str, '\n'); | 24cfb8dRow pattern recognition patch (executor and commands).
4001 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4002 | - | } | 24cfb8dRow pattern recognition patch (executor and commands).
4003 | - | } | -