v50-0003-no-need-compile-and-evaluate-offset-in-expression-evaluation.partial
application/octet-stream
Filename: v50-0003-no-need-compile-and-evaluate-offset-in-expression-evaluation.partial
Type: application/octet-stream
Part: 3
Message:
Re: Row pattern recognition
From 6c877a423d04e7d9b641b7aee877b7aa5aadb239 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Thu, 2 Jul 2026 17:39:11 +0800
Subject: [PATCH v50 3/4] no need compile and evaluate offset in expression
evaluation
execExpr.c, execExprInterp.c offset, compound_offset value checking is not
necessary.
Based on https://github.com/assam258-5892/postgres/commits/RPR
---
src/backend/executor/execExpr.c | 56 +--------------------------
src/backend/executor/execExprInterp.c | 47 ++--------------------
src/backend/executor/nodeWindowAgg.c | 3 ++
src/backend/parser/parse_rpr.c | 2 +
src/include/executor/execExpr.h | 6 +--
src/include/nodes/primnodes.h | 25 +++++++++---
6 files changed, 34 insertions(+), 105 deletions(-)
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 3036782503..de13ac693f 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -1198,10 +1198,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
* swaps ecxt_outertuple to the target row, the argument
* expression is compiled normally (reads from the swapped
* slot), and the RESTORE opcode restores the original slot.
- *
- * Default offset when offset_arg is NULL: PREV/NEXT: 1
- * (physical offset from currentpos) FIRST/LAST: 0 (logical
- * offset from match boundary)
*/
RPRNavExpr *nav = (RPRNavExpr *) node;
WindowAggState *winstate;
@@ -1213,56 +1209,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
scratch.opcode = EEOP_RPR_NAV_SET;
scratch.d.rpr_nav.winstate = winstate;
scratch.d.rpr_nav.kind = nav->kind;
-
- if (nav->kind >= RPR_NAV_PREV_FIRST)
- {
- /*
- * Compound navigation: allocate array of 2 for inner [0]
- * and outer [1] offsets.
- */
- Datum *offset_values = palloc_array(Datum, 2);
- bool *offset_isnulls = palloc_array(bool, 2);
-
- /* Inner offset (default 0 for FIRST/LAST) */
- if (nav->offset_arg != NULL)
- ExecInitExprRec(nav->offset_arg, state,
- &offset_values[0], &offset_isnulls[0]);
- else
- {
- offset_values[0] = Int64GetDatum(0);
- offset_isnulls[0] = false;
- }
-
- /* Outer offset (default 1 for PREV/NEXT) */
- if (nav->compound_offset_arg != NULL)
- ExecInitExprRec(nav->compound_offset_arg, state,
- &offset_values[1], &offset_isnulls[1]);
- else
- {
- offset_values[1] = Int64GetDatum(1);
- offset_isnulls[1] = false;
- }
-
- scratch.d.rpr_nav.offset_value = offset_values;
- scratch.d.rpr_nav.offset_isnull = offset_isnulls;
- }
- else if (nav->offset_arg != NULL)
- {
- /* Simple navigation with explicit offset */
- Datum *offset_value = palloc_object(Datum);
- bool *offset_isnull = palloc_object(bool);
-
- ExecInitExprRec(nav->offset_arg, state,
- offset_value, offset_isnull);
- scratch.d.rpr_nav.offset_value = offset_value;
- scratch.d.rpr_nav.offset_isnull = offset_isnull;
- }
- else
- {
- /* Simple navigation with default offset */
- scratch.d.rpr_nav.offset_value = NULL;
- scratch.d.rpr_nav.offset_isnull = NULL;
- }
+ scratch.d.rpr_nav.offset = nav->offset;
+ scratch.d.rpr_nav.compound_offset = nav->compound_offset;
ExprEvalPushStep(state, &scratch);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index af50a2e16d..5c26c5e848 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -6011,20 +6011,6 @@ ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans,
MemoryContextSwitchTo(oldContext);
}
-/*
- * Extract compound (outer) offset from step data.
- * For compound nav, offset_value is an array: [0]=inner, [1]=outer.
- * Returns the outer offset; errors on NULL or negative.
- * Default is 1 (like PREV/NEXT implicit offset).
- */
-static int64
-rpr_nav_get_compound_offset(ExprEvalStep *op)
-{
- Assert(op->d.rpr_nav.offset_value != NULL);
-
- return DatumGetInt64(op->d.rpr_nav.offset_value[1]);
-}
-
/*
* Evaluate RPR navigation (PREV/NEXT/FIRST/LAST): swap slot to target row.
*
@@ -6040,32 +6026,15 @@ ExecEvalRPRNavSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
{
WindowAggState *winstate = op->d.rpr_nav.winstate;
int64 offset;
+ int64 compound_offset;
int64 target_pos;
TupleTableSlot *target_slot;
/* Save current slot for later restore */
winstate->nav_saved_outertuple = econtext->ecxt_outertuple;
- /*
- * Determine the inner offset. NULL or negative offsets are errors per
- * the SQL standard.
- *
- * Default offset when offset_arg is NULL: PREV/NEXT: 1 (standard 5.6.2)
- * FIRST/LAST and compound: 0 for inner, 1 for outer
- */
- if (op->d.rpr_nav.offset_value != NULL)
- {
- offset = DatumGetInt64(*op->d.rpr_nav.offset_value);
- }
- else
- {
- /* Default offset: 1 for simple PREV/NEXT, 0 otherwise */
- if (op->d.rpr_nav.kind == RPR_NAV_PREV ||
- op->d.rpr_nav.kind == RPR_NAV_NEXT)
- offset = 1;
- else
- offset = 0;
- }
+ offset = op->d.rpr_nav.offset;
+ compound_offset = op->d.rpr_nav.compound_offset;
/*
* Calculate target position based on navigation direction. On overflow,
@@ -6105,7 +6074,6 @@ ExecEvalRPRNavSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
case RPR_NAV_PREV_FIRST:
case RPR_NAV_NEXT_FIRST:
{
- int64 compound_offset;
int64 inner_pos;
/* Inner: match_start + offset */
@@ -6120,9 +6088,6 @@ ExecEvalRPRNavSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
break;
}
- /* Outer offset */
- compound_offset = rpr_nav_get_compound_offset(op);
-
/* Apply outer: PREV subtracts, NEXT adds */
if (op->d.rpr_nav.kind == RPR_NAV_PREV_FIRST)
{
@@ -6144,7 +6109,6 @@ ExecEvalRPRNavSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
case RPR_NAV_PREV_LAST:
case RPR_NAV_NEXT_LAST:
{
- int64 compound_offset;
int64 inner_pos;
/* Inner: currentpos - offset */
@@ -6159,9 +6123,6 @@ ExecEvalRPRNavSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
break;
}
- /* Outer offset */
- compound_offset = rpr_nav_get_compound_offset(op);
-
/* Apply outer: PREV subtracts, NEXT adds */
if (op->d.rpr_nav.kind == RPR_NAV_PREV_LAST)
{
@@ -6182,7 +6143,7 @@ ExecEvalRPRNavSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
break;
default:
elog(ERROR, "unrecognized RPR navigation kind: %d",
- op->d.rpr_nav.kind);
+ (int) op->d.rpr_nav.kind);
break;
}
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index fec21c2835..fdd69f494e 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -4074,6 +4074,9 @@ visit_nav_exec(NavTraversal *t, RPRNavExpr *nav)
outer = eval_nav_offset_helper(context->winstate,
nav->compound_offset_arg);
+ nav->offset = inner;
+ nav->compound_offset = outer;
+
/* Backward reach: PREV, LAST-with-offset */
if (!context->maxOverflow)
{
diff --git a/src/backend/parser/parse_rpr.c b/src/backend/parser/parse_rpr.c
index ac29c26e20..87b6d8f138 100644
--- a/src/backend/parser/parse_rpr.c
+++ b/src/backend/parser/parse_rpr.c
@@ -566,6 +566,8 @@ define_walker(Node *node, void *context)
nav->kind = RPR_NAV_NEXT_FIRST;
else if (nav->kind == RPR_NAV_NEXT && inner->kind == RPR_NAV_LAST)
nav->kind = RPR_NAV_NEXT_LAST;
+ else
+ elog(ERROR, "Invalid compound forms: outer: %d, inner: %d", (int) nav->kind, (int) inner->kind);
nav->compound_offset_arg = nav->offset_arg;
nav->offset_arg = inner->offset_arg;
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index db66ebe313..0561fd8f40 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -703,9 +703,9 @@ typedef struct ExprEvalStep
struct
{
WindowAggState *winstate;
- RPRNavKind kind; /* navigation kind (simple or compound) */
- Datum *offset_value; /* offset value(s), or NULL */
- bool *offset_isnull; /* offset null flag(s) */
+ RPRNavKind kind;
+ int64 offset;
+ int64 compound_offset;
/* For compound nav: offset_value[0] = inner, [1] = outer */
int16 resulttyplen; /* RESTORE: result type length */
bool resulttypbyval; /* RESTORE: result pass-by-value? */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 8ba530333b..902521ff83 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -682,11 +682,26 @@ typedef enum RPRNavKind
typedef struct RPRNavExpr
{
Expr xpr;
- RPRNavKind kind; /* navigation kind */
- Expr *arg; /* argument expression */
- Expr *offset_arg; /* offset expression, or NULL for default */
- Expr *compound_offset_arg; /* outer offset for compound nav, or
- * NULL if simple */
+ RPRNavKind kind;
+ /* argument expression */
+ Expr *arg;
+ /* offset expression */
+ Expr *offset_arg;
+ /* outer offset for compound navigation */
+ Expr *compound_offset_arg;
+
+ /*
+ * The computed offset value, for default value see RPRNavKind comments
+ * above. The value will be set in visit_nav_exec.
+ */
+ int64 offset;
+
+ /*
+ * The computeed compound_offset offset value, for default value see
+ * RPRNavKind comments above. The value will be set in visit_nav_exec.
+ */
+ int64 compound_offset;
+
/* result type (same as arg's type) */
Oid resulttype pg_node_attr(query_jumble_ignore);
/* OID of collation of result */
--
2.34.1