rewriter-patch.txt
text/plain
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 0b2a164057..baded88201 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -428,6 +428,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);
@@ -6459,6 +6463,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_var, *lc_def;
+
+ sep = " ";
+ Assert(list_length(patternVariables) == list_length(defineClause));
+
+ forboth(lc_var, patternVariables, lc_def, defineClause)
+ {
+ char *varName = strVal(lfirst(lc_var));
+ TargetEntry *te = (TargetEntry *) lfirst(lc_def);
+
+ appendStringInfo(buf, "%s%s AS ", sep, varName);
+ get_rule_expr((Node *) te->expr, context, false);
+ sep = ",\n ";
+ }
+}
+
/*
* Display a WINDOW clause.
*
@@ -6596,6 +6658,34 @@ get_rule_windowspec(WindowClause *wc, List *targetList,
appendStringInfoString(buf, "EXCLUDE GROUP ");
else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
appendStringInfoString(buf, "EXCLUDE TIES ");
+ /* RPR */
+ if (wc->rpSkipTo == ST_NEXT_ROW)
+ appendStringInfoString(buf, "\n AFTER MATCH SKIP TO NEXT ROW ");
+ else if (wc->rpSkipTo == ST_PAST_LAST_ROW)
+ appendStringInfoString(buf, "\n AFTER MATCH SKIP PAST LAST ROW ");
+ else if (wc->rpSkipTo == ST_FIRST_VARIABLE)
+ appendStringInfo(buf, "\n AFTER MATCH SKIP TO FIRST %s ", wc->rpSkipVariable);
+ else if (wc->rpSkipTo == ST_LAST_VARIABLE)
+ appendStringInfo(buf, "\n AFTER MATCH SKIP TO LAST %s ", wc->rpSkipVariable);
+ else if (wc->rpSkipTo == ST_VARIABLE)
+ appendStringInfo(buf, "\n AFTER MATCH SKIP TO %s ", wc->rpSkipVariable);
+
+ if (wc->initial)
+ appendStringInfoString(buf, "\n INITIAL");
+
+ if (wc->patternVariable)
+ {
+ appendStringInfoString(buf, "\n PATTERN ");
+ get_rule_pattern(wc->patternVariable, wc->patternRegexp, false, context);
+ }
+
+ if (wc->defineClause)
+ {
+ appendStringInfoString(buf, "\n DEFINE\n");
+ get_rule_define(wc->defineClause, wc->patternVariable, false, context);
+ appendStringInfoChar(buf, ' ');
+ }
+
/* we will now have a trailing space; remove it */
buf->len--;
}
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 2b4c36a15f..104c0105c5 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -3851,6 +3851,9 @@ transformRPR(ParseState *pstate, WindowClause *wc, WindowDef *windef, List **tar
/* Transform AFTER MACH SKIP TO clause */
wc->rpSkipTo = windef->rpCommonSyntax->rpSkipTo;
+ /* Transform AFTER MACH SKIP TO variable */
+ wc->rpSkipVariable = windef->rpCommonSyntax->rpSkipVariable;
+
/* Transform SEEK or INITIAL clause */
wc->initial = windef->rpCommonSyntax->initial;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 5a9b162463..64e9df0a48 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1554,6 +1554,7 @@ typedef struct WindowClause
bool copiedOrder pg_node_attr(query_jumble_ignore);
/* Row Pattern AFTER MACH SKIP clause */
RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+ char *rpSkipVariable;/* Row Pattern Skip To variable */
bool initial; /* true if <row pattern initial or seek> is initial */
/* Row Pattern DEFINE clause (list of TargetEntry) */
List *defineClause;