On Thu, Sep 17, 2026 at 3:32 PM Tatsuo Ishii <[email protected]> wrote:
>
> Attached is v53 RPR patches. The v53 is basically just a rebased
> version of v52, due to recent large revert[1], except some very minor
> error messages and comment fixes in gram.y.
> v53 has been created against 999ce9bcd80.
>
> [1] 
> https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=999ce9bcd80890c3d723e113bb0337c900f9f249
>

Hi.

define_walker is kind of ugly, so i did the attached refactoring,
which make navigation expression check stay within ParseRPRNavCall.
Overall I feel it is more neat than define_walker.
It's based on v53.



--
jian
https://www.enterprisedb.com/
From 41a3f7593c13f3c5e9b712a036d5365875eca4c1 Mon Sep 17 00:00:00 2001
From: jian he <[email protected]>
Date: Thu, 1 Oct 2026 15:02:37 +0800
Subject: [PATCH v54 1/1] Remove define_walker and validate navigation at 
 ParseRPRNavCall

Check PREV/NEXT/FIRST/LAST navigation in ParseRPRNavCall, where the arguments
are already transformed, instead of in a separate walk over the finished DEFINE
expression.

This is way more neat than define_walker.
---
 src/backend/executor/README.rpr        |   4 -
 src/backend/parser/parse_func.c        | 268 +++++++++++++++++--------
 src/backend/parser/parse_rpr.c         | 242 ----------------------
 src/test/regress/expected/rpr.out      |  58 +++---
 src/test/regress/expected/rpr_base.out |  77 ++++---
 src/tools/pgindent/typedefs.list       |   2 -
 6 files changed, 250 insertions(+), 401 deletions(-)

diff --git a/src/backend/executor/README.rpr b/src/backend/executor/README.rpr
index 05bbcd76240..a852f4e077f 100644
--- a/src/backend/executor/README.rpr
+++ b/src/backend/executor/README.rpr
@@ -190,10 +190,6 @@ use.  After that it processes each DEFINE variable as 
follows:
       present in the query targetlist, so the planner propagates the
       referenced columns through the plan tree
 
-After all variables are processed:
-  (5) Validates navigation nesting and offsets (define_walker), marks
-      column origins and assigns collations
-
 Variables that are used in PATTERN but not defined in DEFINE are implicitly
 evaluated as TRUE (matching all rows).
 
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 4f8bfde6f96..5d55705f5c0 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -22,6 +22,7 @@
 #include "lib/stringinfo.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "optimizer/optimizer.h"
 #include "parser/parse_agg.h"
 #include "parser/parse_clause.h"
 #include "parser/parse_coerce.h"
@@ -48,6 +49,9 @@ static void unify_hypothetical_args(ParseState *pstate,
                                                                        List 
*fargs, int numAggregatedArgs,
                                                                        Oid 
*actual_arg_types, Oid *declared_arg_types);
 static Oid     FuncNameAsType(List *funcname);
+static const char *rpr_nav_lookup(const char *name, RPRNavKind *kind);
+static const char *rpr_nav_kind_form(RPRNavKind kind);
+static bool find_rpr_nav_walker(Node *node, RPRNavExpr **found);
 static Node *ParseRPRNavCall(ParseState *pstate, List *funcname,
                                                         List *fargs, List 
*argnames, FuncCall *fn,
                                                         int location);
@@ -232,16 +236,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List 
*fargs,
         */
        if (!is_column && !proc_call &&
                pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE &&
-               list_length(funcname) == 1)
-       {
-               const char *name = strVal(linitial(funcname));
-
-               if (strcmp(name, "prev") == 0 ||
-                       strcmp(name, "next") == 0 ||
-                       strcmp(name, "first") == 0 ||
-                       strcmp(name, "last") == 0)
-                       could_be_rpr_nav = true;
-       }
+               list_length(funcname) == 1 &&
+               rpr_nav_lookup(strVal(linitial(funcname)), NULL) != NULL)
+               could_be_rpr_nav = true;
 
        /*
         * Decide whether it's legitimate to consider the construct to be a 
column
@@ -2139,62 +2136,120 @@ FuncNameAsType(List *funcname)
        return result;
 }
 
+/*
+ * If name (as downcased by the parser) is a row pattern navigation function,
+ * return its upper-case spelling for messages and set *kind if kind is not
+ * NULL; otherwise return NULL.
+ */
+static const char *
+rpr_nav_lookup(const char *name, RPRNavKind *kind)
+{
+       RPRNavKind      k;
+       const char *navname;
+
+       if (strcmp(name, "prev") == 0)
+       {
+               k = RPR_NAV_PREV;
+               navname = "PREV";
+       }
+       else if (strcmp(name, "next") == 0)
+       {
+               k = RPR_NAV_NEXT;
+               navname = "NEXT";
+       }
+       else if (strcmp(name, "first") == 0)
+       {
+               k = RPR_NAV_FIRST;
+               navname = "FIRST";
+       }
+       else if (strcmp(name, "last") == 0)
+       {
+               k = RPR_NAV_LAST;
+               navname = "LAST";
+       }
+       else
+               return NULL;
+
+       if (kind)
+               *kind = k;
+       return navname;
+}
+
+/* Return how a navigation call of the given kind is spelled in messages. */
+static const char *
+rpr_nav_kind_form(RPRNavKind kind)
+{
+       switch (kind)
+       {
+               case RPR_NAV_PREV:
+                       return "PREV()";
+               case RPR_NAV_NEXT:
+                       return "NEXT()";
+               case RPR_NAV_FIRST:
+                       return "FIRST()";
+               case RPR_NAV_LAST:
+                       return "LAST()";
+               case RPR_NAV_PREV_FIRST:
+                       return "PREV(FIRST())";
+               case RPR_NAV_PREV_LAST:
+                       return "PREV(LAST())";
+               case RPR_NAV_NEXT_FIRST:
+                       return "NEXT(FIRST())";
+               case RPR_NAV_NEXT_LAST:
+                       return "NEXT(LAST())";
+       }
+       return "???";                           /* keep compiler quiet */
+}
+
+/* Find the first RPRNavExpr in an expression tree, if any. */
+static bool
+find_rpr_nav_walker(Node *node, RPRNavExpr **found)
+{
+       if (node == NULL)
+               return false;
+       if (IsA(node, RPRNavExpr))
+       {
+               *found = (RPRNavExpr *) node;
+               return true;
+       }
+       return expression_tree_walker(node, find_rpr_nav_walker, found);
+}
+
 /*
  * ParseRPRNavCall
  *             Recognize a row pattern navigation operation in a DEFINE clause.
  *
+ * The argument expressions (in fargs) must have been transformed already.
+ * However, nothing in *fn has been transformed.
+ *
  * Inside an EXPR_KIND_RPR_DEFINE clause an unqualified call to one of the
  * names PREV/NEXT/FIRST/LAST denotes the corresponding row pattern navigation
  * operation (ISO/IEC 19075-5 Subclause 5.6), not an ordinary function call.
- * The name is matched here, before any catalog lookup, with no fallback to
- * function resolution: once it matches, decoration and argument-count
- * violations are dedicated errors rather than letting an ordinary function of
- * the same name take over.  A schema-qualified call (the caller restricts us
- * to unqualified names) is the documented way to reach such a function
- * instead.
  *
  * The caller routes here only after the name has matched one of the four
  * navigation names and the common decoration/wrong-kind checks in
- * ParseFuncOrColumn have run, so this always returns an RPRNavExpr.
+ * ParseFuncOrColumn have run.
  */
 static Node *
 ParseRPRNavCall(ParseState *pstate, List *funcname, List *fargs,
                                List *argnames, FuncCall *fn, int location)
 {
-       const char *name = strVal(linitial(funcname));
        RPRNavKind      kind;
        const char *navname;
        int                     nargs = list_length(fargs);
        Node       *arg;
+       Node       *offset = NULL;
        RPRNavExpr *navexpr;
+       int                     loc;
+       Oid                     offtype;
+       RPRNavExpr *inner = NULL;
+       Node       *rawoffset = NULL;
 
-       /* match the parser-downcased identifier; otherwise not a navigation 
name */
-       if (strcmp(name, "prev") == 0)
-       {
-               kind = RPR_NAV_PREV;
-               navname = "PREV";
-       }
-       else if (strcmp(name, "next") == 0)
-       {
-               kind = RPR_NAV_NEXT;
-               navname = "NEXT";
-       }
-       else if (strcmp(name, "first") == 0)
-       {
-               kind = RPR_NAV_FIRST;
-               navname = "FIRST";
-       }
-       else if (strcmp(name, "last") == 0)
-       {
-               kind = RPR_NAV_LAST;
-               navname = "LAST";
-       }
-       else
-       {
-               /* the caller only routes here after matching one of the four 
names */
-               pg_unreachable();
-               return NULL;
-       }
+       navexpr = makeNode(RPRNavExpr);
+
+       /* the caller only routes here after matching one of the four names */
+       navname = rpr_nav_lookup(strVal(linitial(funcname)), &kind);
+       Assert(navname != NULL);
 
        /*
         * Once the name matches we never fall back to function resolution, so 
any
@@ -2236,49 +2291,100 @@ ParseRPRNavCall(ParseState *pstate, List *funcname, 
List *fargs,
                                                   navname),
                                 parser_errposition(pstate, location)));
 
-       /*
-        * Resolve a still-unknown first argument to text, the same way the
-        * anycompatible family does.  A navigation operation is not a 
polymorphic
-        * function, so the old "could not determine polymorphic type" error 
does
-        * not apply; an unknown literal cannot contain a column reference, so 
the
-        * walker still rejects it later.
-        */
        arg = linitial(fargs);
        if (exprType(arg) == UNKNOWNOID)
                arg = coerce_to_common_type(pstate, arg, TEXTOID, navname);
 
-       navexpr = makeNode(RPRNavExpr);
+       if (nargs == 2)
+               rawoffset = lsecond(fargs);
+
+       /* an explicit offset is coerced to int8, which the executor reads */
+       if (rawoffset != NULL)
+       {
+               loc = exprLocation(rawoffset);
+               offtype = exprType(rawoffset);
+
+               offset = coerce_to_target_type(pstate, rawoffset, offtype,
+                                                                          
INT8OID, -1, COERCION_IMPLICIT,
+                                                                          
COERCE_IMPLICIT_CAST, -1);
+               if (offset == NULL)
+                       ereport(ERROR,
+                                       errcode(ERRCODE_DATATYPE_MISMATCH),
+                                       errmsg("offset argument of %s must be 
type %s, not type %s",
+                                                  navname, 
format_type_be(INT8OID), format_type_be(offtype)),
+                                       parser_errposition(pstate, loc));
+
+               /* offset must be a run-time constant */
+               if (contain_var_clause(offset))
+                       ereport(ERROR,
+                                       errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                       errmsg("row pattern navigation offset 
must be a run-time constant"),
+                                       parser_errposition(pstate, loc));
+       }
+
+       (void) find_rpr_nav_walker(arg, &inner);
+
+       if (inner != NULL)
+       {
+               if ((kind != RPR_NAV_PREV && kind != RPR_NAV_NEXT) ||
+                       (inner->kind != RPR_NAV_FIRST && inner->kind != 
RPR_NAV_LAST))
+                       ereport(ERROR,
+                                       errcode(ERRCODE_SYNTAX_ERROR),
+                                       errmsg("invalid row pattern navigation 
function form: %s(%s)",
+                                                  navname, 
rpr_nav_kind_form(inner->kind)),
+                                       errhint("Row pattern navigation 
operations can only be nested as \"%s\", \"%s\", \"%s\", or \"%s\".",
+                                                       "PREV(FIRST())", 
"PREV(LAST())", "NEXT(FIRST())", "NEXT(LAST())"),
+                                       parser_errposition(pstate, 
inner->location));
+
+               /* Reject an inner nav that is not the whole argument */
+               if ((Node *) inner != arg)
+                       ereport(ERROR,
+                                       errcode(ERRCODE_SYNTAX_ERROR),
+                                       errmsg("nested row pattern navigation 
operation must be the direct argument of %s",
+                                                  navname),
+                                       errhint("Row pattern navigation 
operations can only be nested as \"%s\", \"%s\", \"%s\", or \"%s\".",
+                                                       "PREV(FIRST())", 
"PREV(LAST())", "NEXT(FIRST())", "NEXT(LAST())"),
+                                       parser_errposition(pstate, location));
+
+               /*
+                * transform PREV/NEXT(FIRST/LAST(arg, inner_off), outer_off) 
into one
+                * node
+                */
+               if (kind == RPR_NAV_PREV)
+               {
+                       if (inner->kind == RPR_NAV_FIRST)
+                               kind = RPR_NAV_PREV_FIRST;
+                       else
+                               kind = RPR_NAV_PREV_LAST;
+               }
+               else
+               {
+                       Assert(kind == RPR_NAV_NEXT);
+
+                       if (inner->kind == RPR_NAV_FIRST)
+                               kind = RPR_NAV_NEXT_FIRST;
+                       else
+                               kind = RPR_NAV_NEXT_LAST;
+               }
+
+               /* the outer offset becomes the compound offset; take the 
inner's rest */
+               navexpr->compound_offset_arg = (Expr *) offset;
+               offset = (Node *) inner->offset_arg;
+               arg = (Node *) inner->arg;
+       }
+       else
+       {
+               if (!contain_var_clause(arg))
+                       ereport(ERROR,
+                                       errcode(ERRCODE_SYNTAX_ERROR),
+                                       errmsg("argument of row pattern 
navigation operation must include at least one column reference"),
+                                       parser_errposition(pstate, 
exprLocation(arg)));
+       }
+
        navexpr->kind = kind;
        navexpr->arg = (Expr *) arg;
+       navexpr->offset_arg = (Expr *) offset;
        navexpr->navno = -1;            /* assigned while planning */
-
-       /* an explicit offset is coerced to int8, which the executor reads */
-       if (nargs == 2)
-       {
-               Node       *offset = lsecond(fargs);
-               Oid                     offtype = exprType(offset);
-
-               if (offtype != INT8OID)
-               {
-                       Node       *newoffset;
-
-                       newoffset = coerce_to_target_type(pstate, offset, 
offtype,
-                                                                               
          INT8OID, -1, COERCION_IMPLICIT,
-                                                                               
          COERCE_IMPLICIT_CAST, -1);
-                       if (newoffset == NULL)
-                               ereport(ERROR,
-                                               
(errcode(ERRCODE_DATATYPE_MISMATCH),
-                                                errmsg("offset argument of %s 
must be type %s, not type %s",
-                                                               navname, 
"bigint", format_type_be(offtype)),
-                                                parser_errposition(pstate, 
exprLocation(offset))));
-                       offset = newoffset;
-               }
-               navexpr->offset_arg = (Expr *) offset;
-       }
-       else
-               navexpr->offset_arg = NULL;
-
-       /* compound_offset_arg stays NULL; define_walker flattening fills it in 
*/
        navexpr->resulttype = exprType(arg);
        /* resultcollid will be set by parse_collate.c */
        navexpr->location = location;
diff --git a/src/backend/parser/parse_rpr.c b/src/backend/parser/parse_rpr.c
index 6292cd0547f..9d57bf5a195 100644
--- a/src/backend/parser/parse_rpr.c
+++ b/src/backend/parser/parse_rpr.c
@@ -34,30 +34,11 @@
 #include "parser/parse_rpr.h"
 #include "parser/parse_target.h"
 
-/* DEFINE clause walker context -- see define_walker for usage. */
-typedef enum
-{
-       DEFINE_PHASE_BODY,                      /* top-level DEFINE expression 
*/
-       DEFINE_PHASE_NAV_ARG,           /* inside an outer nav's arg subtree */
-       DEFINE_PHASE_NAV_OFFSET,        /* inside an outer nav's offset_arg /
-                                                                * 
compound_offset_arg */
-} DefinePhase;
-
-typedef struct
-{
-       ParseState *pstate;
-       DefinePhase phase;
-       int                     nav_count;              /* RPRNavExpr nodes 
seen in current nav.arg */
-       bool            has_column_ref; /* Var seen in current nav scope */
-       RPRNavKind      inner_kind;             /* kind of first nested nav in 
current arg */
-} DefineWalkCtx;
-
 /* Forward declarations */
 static void validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode 
*node,
                                                                           List 
**varNames);
 static List *transformDefineClause(ParseState *pstate, WindowDef *windef,
                                                                   List 
**targetlist);
-static bool define_walker(Node *node, void *context);
 
 /*
  * transformRPR
@@ -398,22 +379,6 @@ transformDefineClause(ParseState *pstate, WindowDef 
*windef,
        }
        pstate->p_rpr_pattern_vars = NIL;
 
-       /*
-        * Validate DEFINE expressions: nested PREV/NEXT, column references,
-        * compound flatten -- all in a single walk per variable.
-        */
-       foreach_ptr(TargetEntry, te, defineClause)
-       {
-               DefineWalkCtx ctx;
-
-               ctx.pstate = pstate;
-               ctx.phase = DEFINE_PHASE_BODY;
-               ctx.nav_count = 0;
-               ctx.has_column_ref = false;
-               ctx.inner_kind = 0;
-               (void) define_walker((Node *) te->expr, &ctx);
-       }
-
        /* mark column origins */
        markTargetListOrigins(pstate, defineClause);
 
@@ -422,210 +387,3 @@ transformDefineClause(ParseState *pstate, WindowDef 
*windef,
 
        return defineClause;
 }
-
-/*
- * define_walker
- *             Single-pass DEFINE clause validator.  At each node, enforces:
- *
- *               [1] for each outer RPRNavExpr (PHASE_BODY -> PHASE_NAV_ARG):
- *                       - nav.arg must contain at least one column reference
- *                       - PREV/NEXT wrapping FIRST/LAST is flattened in place
- *                             to a compound kind (PREV_FIRST, PREV_LAST, 
NEXT_FIRST,
- *                             NEXT_LAST)
- *                       - an inner navigation that is not nav.arg itself is
- *                             rejected as not being a direct argument
- *                       - any other nesting is rejected (FIRST(PREV()),
- *                             PREV(PREV()), FIRST(FIRST()), three-or-more 
deep)
- *               [2] for each nav offset (PHASE_NAV_OFFSET):
- *                       - must be a run-time constant (no column references)
- *                       - must not contain a row pattern navigation operation
- *
- * Entering an outer nav, the walker walks nav.arg in PHASE_NAV_ARG to collect
- * nesting and column-ref state, flattens a compound form or raises a nesting
- * error, then walks the post-flatten offset(s) in PHASE_NAV_OFFSET.  A
- * compound form's inner offset is walked in both passes: PHASE_NAV_ARG only
- * asks whether nav.arg as a whole holds a column reference, so the offset is
- * walked again to catch one it would have leaked.
- *
- * Var sightings feed the column-ref rule for the enclosing nav scope;
- * RPRNavExpr sightings inside PHASE_NAV_ARG feed the nesting decision.
- * The phases themselves are described where DefinePhase is declared.
- */
-static bool
-define_walker(Node *node, void *context)
-{
-       DefineWalkCtx *ctx = (DefineWalkCtx *) context;
-
-       if (node == NULL)
-               return false;
-
-       /* Var sighting feeds the column-ref rule for the enclosing nav scope. 
*/
-       if (IsA(node, Var) &&
-               (ctx->phase == DEFINE_PHASE_NAV_ARG ||
-                ctx->phase == DEFINE_PHASE_NAV_OFFSET))
-               ctx->has_column_ref = true;
-
-       if (IsA(node, RPRNavExpr))
-       {
-               RPRNavExpr *nav = (RPRNavExpr *) node;
-
-               if (ctx->phase == DEFINE_PHASE_NAV_ARG)
-               {
-                       /*
-                        * Nested nav inside an outer nav.arg: record for the 
outer's
-                        * compound / nesting decision, then keep recursing so 
deeper Vars
-                        * are still observed.
-                        */
-                       if (ctx->nav_count == 0)
-                               ctx->inner_kind = nav->kind;
-                       ctx->nav_count++;
-                       return expression_tree_walker(node, define_walker, ctx);
-               }
-               else if (ctx->phase == DEFINE_PHASE_NAV_OFFSET)
-               {
-                       /*
-                        * A navigation offset must be a run-time constant, so 
it cannot
-                        * contain a navigation operation.
-                        */
-                       ereport(ERROR,
-                                       errcode(ERRCODE_SYNTAX_ERROR),
-                                       errmsg("row pattern navigation offset 
cannot contain a row pattern navigation operation"),
-                                       errdetail("A navigation offset must be 
a run-time constant."),
-                                       parser_errposition(ctx->pstate, 
nav->location));
-               }
-               else
-               {
-                       /*
-                        * PHASE_BODY: this is an outer nav at top level.  Walk 
arg first
-                        * to collect nesting / column-ref state, then validate 
and (for
-                        * compound forms) flatten, then walk offset(s).
-                        */
-                       DefineWalkCtx saved = *ctx;
-                       bool            outer_phys = (nav->kind == RPR_NAV_PREV 
||
-                                                                         
nav->kind == RPR_NAV_NEXT);
-                       bool            flattened = false;
-
-                       ctx->phase = DEFINE_PHASE_NAV_ARG;
-                       ctx->nav_count = 0;
-                       ctx->has_column_ref = false;
-                       ctx->inner_kind = 0;
-                       (void) define_walker((Node *) nav->arg, ctx);
-
-                       if (ctx->nav_count > 0)
-                       {
-                               bool            inner_phys = (ctx->inner_kind 
== RPR_NAV_PREV ||
-                                                                               
  ctx->inner_kind == RPR_NAV_NEXT);
-
-                               if (outer_phys && !inner_phys)
-                               {
-                                       RPRNavExpr *inner;
-
-                                       /* Reject an inner nav that is not the 
whole argument */
-                                       if (!IsA(nav->arg, RPRNavExpr))
-                                               ereport(ERROR,
-                                                               
errcode(ERRCODE_SYNTAX_ERROR),
-                                                               errmsg("row 
pattern navigation operation must be a direct argument of the outer 
navigation"),
-                                                               errhint("Only 
PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) compound forms are 
allowed."),
-                                                               
parser_errposition(ctx->pstate, nav->location));
-
-                                       /* Reject triple-or-deeper nesting; 
siblings caught above */
-                                       if (ctx->nav_count > 1)
-                                               ereport(ERROR,
-                                                               
errcode(ERRCODE_SYNTAX_ERROR),
-                                                               errmsg("cannot 
nest row pattern navigation more than two levels deep"),
-                                                               errhint("Only 
PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) compound forms are 
allowed."),
-                                                               
parser_errposition(ctx->pstate, nav->location));
-
-                                       inner = (RPRNavExpr *) nav->arg;
-
-                                       if (nav->kind == RPR_NAV_PREV && 
inner->kind == RPR_NAV_FIRST)
-                                               nav->kind = RPR_NAV_PREV_FIRST;
-                                       else if (nav->kind == RPR_NAV_PREV && 
inner->kind == RPR_NAV_LAST)
-                                               nav->kind = RPR_NAV_PREV_LAST;
-                                       else if (nav->kind == RPR_NAV_NEXT && 
inner->kind == RPR_NAV_FIRST)
-                                               nav->kind = RPR_NAV_NEXT_FIRST;
-                                       else if (nav->kind == RPR_NAV_NEXT && 
inner->kind == RPR_NAV_LAST)
-                                               nav->kind = RPR_NAV_NEXT_LAST;
-
-                                       nav->compound_offset_arg = 
nav->offset_arg;
-                                       nav->offset_arg = inner->offset_arg;
-                                       nav->arg = inner->arg;
-                                       flattened = true;
-
-                                       /*
-                                        * The flattened argument must include 
a column reference,
-                                        * just like the simple-nav case below.
-                                        */
-                                       if (!ctx->has_column_ref)
-                                               ereport(ERROR,
-                                                               
errcode(ERRCODE_SYNTAX_ERROR),
-                                                               
errmsg("argument of row pattern navigation operation must include at least one 
column reference"),
-                                                               
parser_errposition(ctx->pstate, nav->location));
-                               }
-                               else if (!outer_phys && inner_phys)
-                                       ereport(ERROR,
-                                                       
errcode(ERRCODE_SYNTAX_ERROR),
-                                                       errmsg("FIRST and LAST 
cannot contain PREV or NEXT"),
-                                                       errhint("Only 
PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) compound forms are 
allowed."),
-                                                       
parser_errposition(ctx->pstate, nav->location));
-                               else if (outer_phys && inner_phys)
-                                       ereport(ERROR,
-                                                       
errcode(ERRCODE_SYNTAX_ERROR),
-                                                       errmsg("PREV and NEXT 
cannot contain PREV or NEXT"),
-                                                       errhint("Only 
PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) compound forms are 
allowed."),
-                                                       
parser_errposition(ctx->pstate, nav->location));
-                               else
-                                       ereport(ERROR,
-                                                       
errcode(ERRCODE_SYNTAX_ERROR),
-                                                       errmsg("FIRST and LAST 
cannot contain FIRST or LAST"),
-                                                       errhint("Only 
PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) compound forms are 
allowed."),
-                                                       
parser_errposition(ctx->pstate, nav->location));
-                       }
-                       else if (!ctx->has_column_ref)
-                       {
-                               ereport(ERROR,
-                                               errcode(ERRCODE_SYNTAX_ERROR),
-                                               errmsg("argument of row pattern 
navigation operation must include at least one column reference"),
-                                               parser_errposition(ctx->pstate, 
nav->location));
-                       }
-
-                       /*
-                        * Walk offset arg(s) in PHASE_NAV_OFFSET to enforce the
-                        * constant-offset rule.  For compound forms, both the 
inner
-                        * (post-flatten nav->offset_arg) and outer 
(compound_offset_arg)
-                        * offsets must be constants; the inner's column-ref 
status was
-                        * not separately tracked during the PHASE_NAV_ARG walk 
(which
-                        * only checks that nav.arg as a whole has at least one 
Var), so
-                        * it is re-walked here to catch column references the 
inner
-                        * offset would have leaked.
-                        */
-                       ctx->phase = DEFINE_PHASE_NAV_OFFSET;
-
-                       if (nav->offset_arg != NULL)
-                       {
-                               ctx->has_column_ref = false;
-                               (void) define_walker((Node *) nav->offset_arg, 
ctx);
-                               if (ctx->has_column_ref)
-                                       ereport(ERROR,
-                                                       
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                       errmsg("row pattern 
navigation offset must be a run-time constant"),
-                                                       
parser_errposition(ctx->pstate, exprLocation((Node *) nav->offset_arg)));
-                       }
-                       if (flattened && nav->compound_offset_arg != NULL)
-                       {
-                               ctx->has_column_ref = false;
-                               (void) define_walker((Node *) 
nav->compound_offset_arg, ctx);
-                               if (ctx->has_column_ref)
-                                       ereport(ERROR,
-                                                       
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                       errmsg("row pattern 
navigation offset must be a run-time constant"),
-                                                       
parser_errposition(ctx->pstate, exprLocation((Node *) 
nav->compound_offset_arg)));
-                       }
-
-                       *ctx = saved;
-                       return false;
-               }
-       }
-
-       return expression_tree_walker(node, define_walker, ctx);
-}
diff --git a/src/test/regress/expected/rpr.out 
b/src/test/regress/expected/rpr.out
index c4958c1b8d8..b789b729210 100644
--- a/src/test/regress/expected/rpr.out
+++ b/src/test/regress/expected/rpr.out
@@ -1017,10 +1017,10 @@ WINDOW w AS (
     PATTERN (A)
     DEFINE A AS price > PREV(PREV(price))
 );
-ERROR:  PREV and NEXT cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: PREV(PREV())
 LINE 7:     DEFINE A AS price > PREV(PREV(price))
-                                ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                     ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- Nested NEXT
 SELECT price FROM stock
 WINDOW w AS (
@@ -1030,10 +1030,10 @@ WINDOW w AS (
     PATTERN (A)
     DEFINE A AS price > NEXT(NEXT(price))
 );
-ERROR:  PREV and NEXT cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: NEXT(NEXT())
 LINE 7:     DEFINE A AS price > NEXT(NEXT(price))
-                                ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                     ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- PREV nested inside NEXT
 SELECT price FROM stock
 WINDOW w AS (
@@ -1043,10 +1043,10 @@ WINDOW w AS (
     PATTERN (A)
     DEFINE A AS price > NEXT(PREV(price))
 );
-ERROR:  PREV and NEXT cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: NEXT(PREV())
 LINE 7:     DEFINE A AS price > NEXT(PREV(price))
-                                ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                     ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- PREV nested inside expression inside NEXT
 SELECT price FROM stock
 WINDOW w AS (
@@ -1056,10 +1056,10 @@ WINDOW w AS (
     PATTERN (A)
     DEFINE A AS price > NEXT(price * PREV(price))
 );
-ERROR:  PREV and NEXT cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: NEXT(PREV())
 LINE 7:     DEFINE A AS price > NEXT(price * PREV(price))
-                                ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                             ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- Triple nesting: error reported at outermost PREV
 SELECT price FROM stock
 WINDOW w AS (
@@ -1069,10 +1069,10 @@ WINDOW w AS (
     PATTERN (A)
     DEFINE A AS price > PREV(PREV(PREV(price)))
 );
-ERROR:  PREV and NEXT cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: PREV(PREV())
 LINE 7:     DEFINE A AS price > PREV(PREV(PREV(price)))
-                                ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                          ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- No column reference in PREV/NEXT argument
 -- PREV(1): constant only, no column reference
 SELECT price FROM stock
@@ -1085,7 +1085,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS PREV(1) > 0
-                        ^
+                             ^
 -- NEXT(1 + 2): constant expression, no column reference
 SELECT price FROM stock
 WINDOW w AS (
@@ -1097,7 +1097,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS NEXT(1 + 2) > 0
-                        ^
+                             ^
 -- 2-arg form: PREV(1, 1): constant expression as first arg
 SELECT price FROM stock
 WINDOW w AS (
@@ -1109,7 +1109,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS PREV(1, 1) > 0
-                        ^
+                             ^
 -- Compound navigation without a column reference must be rejected too,
 -- consistent with the simple forms above.
 -- PREV(FIRST(1)): compound, constant only, no column reference
@@ -1123,7 +1123,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS PREV(FIRST(1)) > 0
-                        ^
+                                   ^
 -- NEXT(LAST(1 + 2)): compound, constant expression, no column reference
 SELECT price FROM stock
 WINDOW w AS (
@@ -1135,7 +1135,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS NEXT(LAST(1 + 2)) > 0
-                        ^
+                                  ^
 -- PREV(FIRST(1, 2)): compound, two-arg inner, no column reference
 SELECT price FROM stock
 WINDOW w AS (
@@ -1147,7 +1147,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS PREV(FIRST(1, 2)) > 0
-                        ^
+                                   ^
 -- PREV(FIRST(1), 2): compound, outer offset only, no column reference
 SELECT price FROM stock
 WINDOW w AS (
@@ -1159,7 +1159,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS PREV(FIRST(1), 2) > 0
-                        ^
+                                   ^
 -- PREV(FIRST(1, 2), 3): compound, inner and outer offsets, no column reference
 SELECT price FROM stock
 WINDOW w AS (
@@ -1171,7 +1171,7 @@ WINDOW w AS (
 );
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 7:     DEFINE A AS PREV(FIRST(1, 2), 3) > 0
-                        ^
+                                   ^
 -- Non-constant offset: column reference as offset
 SELECT price FROM stock
 WINDOW w AS (
@@ -2631,10 +2631,10 @@ SELECT id, val FROM rpr_nav WINDOW w AS (
     PATTERN (A B)
     DEFINE A AS TRUE, B AS FIRST(PREV(val)) > 0
 );
-ERROR:  FIRST and LAST cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: FIRST(PREV())
 LINE 5:     DEFINE A AS TRUE, B AS FIRST(PREV(val)) > 0
-                                   ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                         ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- Reverse nesting: LAST wrapping NEXT is prohibited
 SELECT id, val FROM rpr_nav WINDOW w AS (
     ORDER BY id
@@ -2642,10 +2642,10 @@ SELECT id, val FROM rpr_nav WINDOW w AS (
     PATTERN (A B)
     DEFINE A AS TRUE, B AS LAST(NEXT(val)) > 0
 );
-ERROR:  FIRST and LAST cannot contain PREV or NEXT
+ERROR:  invalid row pattern navigation function form: LAST(NEXT())
 LINE 5:     DEFINE A AS TRUE, B AS LAST(NEXT(val)) > 0
-                                   ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                        ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 DROP TABLE rpr_nav;
 --
 -- SKIP TO / Backtracking / Frame boundary
diff --git a/src/test/regress/expected/rpr_base.out 
b/src/test/regress/expected/rpr_base.out
index ed93bda2cfc..86f4a3f164f 100644
--- a/src/test/regress/expected/rpr_base.out
+++ b/src/test/regress/expected/rpr_base.out
@@ -2749,10 +2749,9 @@ SELECT id, val
     PATTERN (A+)
     DEFINE A AS PREV(val, FIRST(1)) > 0)
   ORDER BY id;
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 6:     DEFINE A AS PREV(val, FIRST(1)) > 0)
-                                  ^
-DETAIL:  A navigation offset must be a run-time constant.
+                                        ^
 DROP SCHEMA rpr_navns CASCADE;
 RESET search_path;
 -- ============================================================
@@ -4860,10 +4859,10 @@ WINDOW w AS (
     PATTERN (A+)
     DEFINE A AS PREV(v + FIRST(v)) > 0
 );
-ERROR:  row pattern navigation operation must be a direct argument of the 
outer navigation
+ERROR:  nested row pattern navigation operation must be the direct argument of 
PREV
 LINE 6:     DEFINE A AS PREV(v + FIRST(v)) > 0
                         ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- FIRST/LAST wrapping FIRST/LAST: prohibited
 SELECT count(*) OVER w
 FROM generate_series(1,10) s(v)
@@ -4872,10 +4871,10 @@ WINDOW w AS (
     PATTERN (A+)
     DEFINE A AS FIRST(FIRST(v)) > 0
 );
-ERROR:  FIRST and LAST cannot contain FIRST or LAST
+ERROR:  invalid row pattern navigation function form: FIRST(FIRST())
 LINE 6:     DEFINE A AS FIRST(FIRST(v)) > 0
-                        ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                              ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- Triple nesting: prohibited (3-level deep navigation)
 SELECT count(*) OVER w
 FROM generate_series(1,10) s(v)
@@ -4884,10 +4883,10 @@ WINDOW w AS (
     PATTERN (A+)
     DEFINE A AS PREV(FIRST(PREV(v))) > 0
 );
-ERROR:  cannot nest row pattern navigation more than two levels deep
+ERROR:  invalid row pattern navigation function form: FIRST(PREV())
 LINE 6:     DEFINE A AS PREV(FIRST(PREV(v))) > 0
-                        ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                   ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- Sibling navigations: prohibited, but they are not a deeper nesting,
 -- so the inner navigation must be reported as not being the direct
 -- argument rather than as a third level.
@@ -4898,10 +4897,10 @@ WINDOW w AS (
     PATTERN (A+)
     DEFINE A AS PREV(FIRST(v) + LAST(v)) > 0
 );
-ERROR:  row pattern navigation operation must be a direct argument of the 
outer navigation
+ERROR:  nested row pattern navigation operation must be the direct argument of 
PREV
 LINE 6:     DEFINE A AS PREV(FIRST(v) + LAST(v)) > 0
                         ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- Three navigations, but the inner one is again not the whole argument, so
 -- that is what gets reported and the depth is not reached
 SELECT count(*) OVER w
@@ -4911,75 +4910,67 @@ WINDOW w AS (
     PATTERN (A+)
     DEFINE A AS PREV(FIRST(PREV(v)) + 1) > 0
 );
-ERROR:  row pattern navigation operation must be a direct argument of the 
outer navigation
+ERROR:  invalid row pattern navigation function form: FIRST(PREV())
 LINE 6:     DEFINE A AS PREV(FIRST(PREV(v)) + 1) > 0
-                        ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                   ^
+HINT:  Row pattern navigation operations can only be nested as 
"PREV(FIRST())", "PREV(LAST())", "NEXT(FIRST())", or "NEXT(LAST())".
 -- A navigation offset must be a run-time constant, not a navigation operation
 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 PREV(v, FIRST(1)) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(v, FIRST(1)) > 0);
-                                             ^
-DETAIL:  A navigation offset must be a run-time constant.
+                                                   ^
 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 PREV(v, FIRST(1) + 1) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(v, FIRST(1) + 1) > 0);
-                                             ^
-DETAIL:  A navigation offset must be a run-time constant.
+                                                   ^
 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 PREV(v, NEXT(1, 0)) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(v, NEXT(1, 0)) > 0);
-                                             ^
-DETAIL:  A navigation offset must be a run-time constant.
+                                                  ^
 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 PREV(FIRST(v), LAST(1)) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(FIRST(v), LAST(1)) > 0);
-                                                    ^
-DETAIL:  A navigation offset must be a run-time constant.
+                                                         ^
 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 PREV(v, FIRST(v)) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  row pattern navigation offset must be a run-time constant
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(v, FIRST(v)) > 0);
                                              ^
-DETAIL:  A navigation offset must be a run-time constant.
 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(v, PREV(v, 1)) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  row pattern navigation offset must be a run-time constant
 LINE 4:     PATTERN (A+) DEFINE A AS NEXT(v, PREV(v, 1)) > 0);
                                              ^
-DETAIL:  A navigation offset must be a run-time constant.
 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 PREV(FIRST(v, LAST(1)), 2) > 0);
-ERROR:  cannot nest row pattern navigation more than two levels deep
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(FIRST(v, LAST(1)), 2) > 0)...
-                                     ^
-HINT:  Only PREV(FIRST()), PREV(LAST()), NEXT(FIRST()), and NEXT(LAST()) 
compound forms are allowed.
+                                                        ^
 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 PREV(v, FIRST(1::bigint)) > 0);
-ERROR:  row pattern navigation offset cannot contain a row pattern navigation 
operation
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(v, FIRST(1::bigint)) > 0);
-                                             ^
-DETAIL:  A navigation offset must be a run-time constant.
+                                                   ^
 -- An unknown literal argument resolves to text; it must still reference a 
column
 SELECT count(*) OVER w
 FROM generate_series(1,5) s(v)
@@ -4987,28 +4978,28 @@ WINDOW w AS (ROWS BETWEEN CURRENT ROW AND UNBOUNDED 
FOLLOWING
     PATTERN (A+) DEFINE A AS PREV('foo') = 'bar');
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV('foo') = 'bar');
-                                     ^
+                                          ^
 SELECT count(*) OVER w
 FROM generate_series(1,5) s(v)
 WINDOW w AS (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
     PATTERN (A+) DEFINE A AS PREV('foo'));
-ERROR:  argument of DEFINE must be type boolean, not type text
+ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV('foo'));
-                                     ^
+                                          ^
 SELECT count(*) OVER w
 FROM generate_series(1,5) s(v)
 WINDOW w AS (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
     PATTERN (A+) DEFINE A AS PREV(NULL) IS NULL);
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV(NULL) IS NULL);
-                                     ^
+                                          ^
 PREPARE rpr_navarg AS SELECT count(*) OVER w
 FROM generate_series(1,5) s(v)
 WINDOW w AS (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
     PATTERN (A+) DEFINE A AS PREV($1) IS NULL);
 ERROR:  argument of row pattern navigation operation must include at least one 
column reference
 LINE 4:     PATTERN (A+) DEFINE A AS PREV($1) IS NULL);
-                                     ^
+                                          ^
 -- An int2 offset is coerced to int8 like any implicit cast (same as plain 0)
 SELECT count(*) OVER w
 FROM generate_series(1,5) s(v)
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 57b1ef7ab6c..704762d0690 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -665,9 +665,7 @@ DefElem
 DefElemAction
 DefaultACLInfo
 DefineMetadataContext
-DefinePhase
 DefineStmt
-DefineWalkCtx
 DefnDumperPtr
 DeleteStmt
 DependenciesParseState
-- 
2.34.1

Reply via email to