From 68e91c3eb25e9bf2ced78a2bd4920c2e5bbc2260 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Tue, 23 Dec 2025 22:21:47 +0900 Subject: [PATCH v36 3/8] Row pattern recognition patch (rewriter). --- src/backend/utils/adt/ruleutils.c | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 9f85eb86da1..b643c0c4bf0 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -438,6 +438,10 @@ static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context); static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context); +static void get_rule_pattern(List *patternVariable, List *patternRegexp, + bool force_colno, deparse_context *context); +static void get_rule_define(List *defineClause, List *patternVariables, + bool force_colno, deparse_context *context); static void get_rule_windowclause(Query *query, deparse_context *context); static void get_rule_windowspec(WindowClause *wc, List *targetList, deparse_context *context); @@ -6744,6 +6748,64 @@ get_rule_orderby(List *orderList, List *targetList, } } +/* + * Display a PATTERN clause. + */ +static void +get_rule_pattern(List *patternVariable, List *patternRegexp, + bool force_colno, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *lc_var, + *lc_reg = list_head(patternRegexp); + + sep = ""; + appendStringInfoChar(buf, '('); + foreach(lc_var, patternVariable) + { + char *variable = strVal((String *) lfirst(lc_var)); + char *regexp = NULL; + + if (lc_reg != NULL) + { + regexp = strVal((String *) lfirst(lc_reg)); + + lc_reg = lnext(patternRegexp, lc_reg); + } + + appendStringInfo(buf, "%s%s", sep, variable); + if (regexp !=NULL) + appendStringInfoString(buf, regexp); + + sep = " "; + } + appendStringInfoChar(buf, ')'); +} + +/* + * Display a DEFINE clause. + */ +static void +get_rule_define(List *defineClause, List *patternVariables, + bool force_colno, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *lc_def; + + sep = " "; + + foreach(lc_def, defineClause) + { + TargetEntry *te = (TargetEntry *) lfirst(lc_def); + + appendStringInfo(buf, "%s%s AS ", sep, te->resname); + get_rule_expr((Node *) te->expr, context, false); + sep = ",\n "; + } +} + /* * Display a WINDOW clause. * @@ -6824,6 +6886,7 @@ get_rule_windowspec(WindowClause *wc, List *targetList, get_rule_orderby(wc->orderClause, targetList, false, context); needspace = true; } + /* framing clause is never inherited, so print unless it's default */ if (wc->frameOptions & FRAMEOPTION_NONDEFAULT) { @@ -6832,7 +6895,53 @@ get_rule_windowspec(WindowClause *wc, List *targetList, get_window_frame_options(wc->frameOptions, wc->startOffset, wc->endOffset, context); + needspace = true; } + + /* RPR */ + if (wc->rpSkipTo == ST_NEXT_ROW) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, + "\n AFTER MATCH SKIP TO NEXT ROW "); + needspace = true; + } + else if (wc->rpSkipTo == ST_PAST_LAST_ROW) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, + "\n AFTER MATCH SKIP PAST LAST ROW "); + needspace = true; + } + if (wc->initial) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "\n INITIAL"); + needspace = true; + } + if (wc->patternVariable) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "\n PATTERN "); + get_rule_pattern(wc->patternVariable, wc->patternRegexp, + false, context); + needspace = true; + } + + if (wc->defineClause) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "\n DEFINE\n"); + get_rule_define(wc->defineClause, wc->patternVariable, + false, context); + appendStringInfoChar(buf, ' '); + } + appendStringInfoChar(buf, ')'); } -- 2.43.0