| 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). |
| 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). |
| 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). |
| 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). |
UnreachableReason 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 fixReplace 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). |
| 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). |
UnreachableReason 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). |
| 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). |
| 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). |
| 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 |
UnreachableReason 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). |
ReachableHow 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). |
UnreachableReason 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). |
UnreachableReason 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 | - | } | - |
| 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). |
| 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 | - | } | - |