From ad3e63eea24c4f80f8d18ef7b5cc40fff14e4828 Mon Sep 17 00:00:00 2001 From: Henson Choi Date: Mon, 8 Jun 2026 13:59:43 +0900 Subject: [PATCH 64/68] Modernize idioms in row pattern recognition code Replace appendStringInfo() with appendStringInfoString() for the eight constant string literals that contain no format specifiers, avoiding an unnecessary trip through vsnprintf(). Replace the four palloc(n * sizeof(type)) calls in _copyRPRPattern() and _readRPRPattern() with palloc_array()/palloc0_array(), which make the element type and count explicit and guard against size multiplication overflow. Replace an open-coded maximum in scanRPRPatternRecursive() with Max(). These are mechanical idiom changes only; behavior, output, and ABI are unchanged, and the row pattern regression tests pass with no .out diffs. --- src/backend/commands/explain.c | 15 ++++++++------- src/backend/nodes/copyfuncs.c | 4 ++-- src/backend/nodes/readfuncs.c | 4 ++-- src/backend/optimizer/plan/rpr.c | 3 +-- src/backend/utils/adt/ruleutils.c | 3 ++- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 7ba0b6df849..7992829d5c4 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -2932,7 +2932,8 @@ append_rpr_quantifier(StringInfo buf, RPRPatternElement *elem) if (RPRElemIsReluctant(elem)) { if (elem->min == 1 && elem->max == 1) - appendStringInfo(buf, "{1}"); /* make reluctant ? unambiguous */ + appendStringInfoString(buf, "{1}"); /* make reluctant ? + * unambiguous */ appendStringInfoChar(buf, '?'); } @@ -3929,7 +3930,7 @@ show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) /* Match/mismatch counts with length min/max/avg */ ExplainIndentText(es); - appendStringInfo(es->str, "NFA: "); + appendStringInfoString(es->str, "NFA: "); if (winstate->nfaMatchesSucceeded > 0) { double avgLen = (double) winstate->nfaMatchLen.total / winstate->nfaMatchesSucceeded; @@ -3943,7 +3944,7 @@ show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) } else { - appendStringInfo(es->str, "0 matched"); + appendStringInfoString(es->str, "0 matched"); } if (winstate->nfaMatchesFailed > 0) { @@ -3958,7 +3959,7 @@ show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) } else { - appendStringInfo(es->str, ", 0 mismatched"); + appendStringInfoString(es->str, ", 0 mismatched"); } appendStringInfoChar(es->str, '\n'); @@ -3966,7 +3967,7 @@ show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) if (winstate->nfaContextsAbsorbed > 0 || winstate->nfaContextsSkipped > 0) { ExplainIndentText(es); - appendStringInfo(es->str, "NFA: "); + appendStringInfoString(es->str, "NFA: "); if (winstate->nfaContextsAbsorbed > 0) { @@ -3981,7 +3982,7 @@ show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) } else { - appendStringInfo(es->str, "0 absorbed"); + appendStringInfoString(es->str, "0 absorbed"); } if (winstate->nfaContextsSkipped > 0) @@ -3997,7 +3998,7 @@ show_rpr_nfa_stats(WindowAggState *winstate, ExplainState *es) } else { - appendStringInfo(es->str, ", 0 skipped"); + appendStringInfoString(es->str, ", 0 skipped"); } appendStringInfoChar(es->str, '\n'); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index e67ad39bdb8..17d45930d7b 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -178,13 +178,13 @@ _copyRPRPattern(const RPRPattern *from) /* Deep copy the varNames array (DEFINE clause is required) */ Assert(from->numVars > 0); - newnode->varNames = palloc0(from->numVars * sizeof(char *)); + newnode->varNames = palloc0_array(char *, from->numVars); for (int i = 0; i < from->numVars; i++) newnode->varNames[i] = pstrdup(from->varNames[i]); /* Deep copy the elements array (always has at least one element + FIN) */ Assert(from->numElements >= 2); - newnode->elements = palloc(from->numElements * sizeof(RPRPatternElement)); + newnode->elements = palloc_array(RPRPatternElement, from->numElements); memcpy(newnode->elements, from->elements, from->numElements * sizeof(RPRPatternElement)); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 5bbde5bcad2..6c39c6fe06d 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -582,7 +582,7 @@ _readRPRPattern(void) token = pg_strtok(&length); /* get '(' or '<>' */ if (local_node->numVars > 0 && token[0] == '(') { - local_node->varNames = palloc(local_node->numVars * sizeof(char *)); + local_node->varNames = palloc_array(char *, local_node->numVars); for (int i = 0; i < local_node->numVars; i++) { token = pg_strtok(&length); @@ -600,7 +600,7 @@ _readRPRPattern(void) token = pg_strtok(&length); /* get '(' or '<>' */ if (local_node->numElements > 0 && token[0] == '(') { - local_node->elements = palloc0(local_node->numElements * sizeof(RPRPatternElement)); + local_node->elements = palloc0_array(RPRPatternElement, local_node->numElements); for (int i = 0; i < local_node->numElements; i++) { RPRPatternElement *elem = &local_node->elements[i]; diff --git a/src/backend/optimizer/plan/rpr.c b/src/backend/optimizer/plan/rpr.c index 143ea034fb3..9364136b071 100644 --- a/src/backend/optimizer/plan/rpr.c +++ b/src/backend/optimizer/plan/rpr.c @@ -1048,8 +1048,7 @@ scanRPRPatternRecursive(RPRPatternNode *node, char **varNames, int *numVars, depth, RPR_DEPTH_MAX - 1)); /* Track maximum depth */ - if (depth > *maxDepth) - *maxDepth = depth; + *maxDepth = Max(*maxDepth, depth); switch (node->nodeType) { diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 2b8439e452e..e8087d4316a 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -7140,7 +7140,8 @@ append_pattern_quantifier(StringInfo buf, RPRPatternNode *node) if (node->reluctant) { if (!has_quantifier) - appendStringInfo(buf, "{1}"); /* make reluctant ? unambiguous */ + appendStringInfoString(buf, "{1}"); /* make reluctant ? + * unambiguous */ appendStringInfoChar(buf, '?'); } } -- 2.50.1 (Apple Git-155)