agora inbox for [email protected]
help / color / mirror / Atom feed[PATCH] Suppress length of Notice/Error in PQtrace regress mode
39+ messages / 8 participants
[nested] [flat]
* [PATCH v2] Suppress length of Notice/Error in PQtrace regress mode
@ 2021-04-02 13:51 Alvaro Herrera <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Alvaro Herrera @ 2021-04-02 13:51 UTC (permalink / raw)
A (relatively minor) annoyance of ErrorResponse/NoticeResponse messages
as printed by PQtrace() is that their length might vary when we move
error messages from one file to another, one function to another, or
even when their location line number changes number of digits.
To avoid having to adjust expected files for some tests, make the
regress mode of PQtrace() suppress the length word of those messages.
Discussion: https://postgr.es/m/[email protected]
Reviewed-by: Tom Lane <[email protected]>
---
src/interfaces/libpq/fe-trace.c | 11 ++++++++++-
.../libpq_pipeline/traces/pipeline_abort.trace | 8 ++++----
.../modules/libpq_pipeline/traces/transaction.trace | 6 +++---
3 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/src/interfaces/libpq/fe-trace.c b/src/interfaces/libpq/fe-trace.c
index 9a4595f5c8..ca24869e91 100644
--- a/src/interfaces/libpq/fe-trace.c
+++ b/src/interfaces/libpq/fe-trace.c
@@ -540,7 +540,16 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
length = (int) pg_ntoh32(length);
logCursor += 4;
- fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
+ /*
+ * In regress mode, suppress the length of ErrorResponse and
+ * NoticeResponse. The F (file name), L (line number) and R (routine
+ * name) fields can change as server code is modified, and if their
+ * lengths differ from the originals, that would break tests.
+ */
+ if (regress && !toServer && (id == 'E' || id == 'N'))
+ fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
+ else
+ fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
switch (id)
{
diff --git a/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace b/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
index b061435785..254e485997 100644
--- a/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
+++ b/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
@@ -1,5 +1,5 @@
F 42 Query "DROP TABLE IF EXISTS pq_pipeline_demo"
-B 123 NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_demo" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_demo" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
B 15 CommandComplete "DROP TABLE"
B 5 ReadyForQuery I
F 99 Query "CREATE UNLOGGED TABLE pq_pipeline_demo(id serial primary key, itemno integer,int8filler int8);"
@@ -27,7 +27,7 @@ B 4 ParseComplete
B 4 BindComplete
B 4 NoData
B 15 CommandComplete "INSERT 0 1"
-B 217 ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" H "No function matches the given name and argument types. You might need to add explicit type casts." P "8" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" H "No function matches the given name and argument types. You might need to add explicit type casts." P "8" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I
B 4 ParseComplete
B 4 BindComplete
@@ -39,7 +39,7 @@ F 12 Bind "" "" 0 0 0
F 6 Describe P ""
F 9 Execute "" 0
F 4 Sync
-B 123 ErrorResponse S "ERROR" V "ERROR" C "42601" M "cannot insert multiple commands into a prepared statement" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "42601" M "cannot insert multiple commands into a prepared statement" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I
F 54 Parse "" "SELECT 1.0/g FROM generate_series(3, -1, -1) g" 0
F 12 Bind "" "" 0 0 0
@@ -52,7 +52,7 @@ B 33 RowDescription 1 "?column?" NNNN 0 NNNN 65535 -1 0
B 32 DataRow 1 22 '0.33333333333333333333'
B 32 DataRow 1 22 '0.50000000000000000000'
B 32 DataRow 1 22 '1.00000000000000000000'
-B 70 ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I
F 40 Query "SELECT itemno FROM pq_pipeline_demo"
B 31 RowDescription 1 "itemno" NNNN 2 NNNN 4 -1 0
diff --git a/src/test/modules/libpq_pipeline/traces/transaction.trace b/src/test/modules/libpq_pipeline/traces/transaction.trace
index 0267a534fa..1dcc2373c0 100644
--- a/src/test/modules/libpq_pipeline/traces/transaction.trace
+++ b/src/test/modules/libpq_pipeline/traces/transaction.trace
@@ -1,5 +1,5 @@
F 79 Query "DROP TABLE IF EXISTS pq_pipeline_tst;CREATE TABLE pq_pipeline_tst (id int)"
-B 122 NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_tst" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_tst" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
B 15 CommandComplete "DROP TABLE"
B 17 CommandComplete "CREATE TABLE"
B 5 ReadyForQuery I
@@ -40,9 +40,9 @@ B 4 BindComplete
B 4 NoData
B 10 CommandComplete "BEGIN"
B 4 ParseComplete
-B 65 ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery E
-B 145 ErrorResponse S "ERROR" V "ERROR" C "25P02" M "current transaction is aborted, commands ignored until end of transaction block" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "25P02" M "current transaction is aborted, commands ignored until end of transaction block" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery E
B 4 BindComplete
B 4 NoData
--
2.20.1
--a8Wt8u1KmwUX3Y2C--
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH] Suppress length of Notice/Error in PQtrace regress mode
@ 2021-04-02 13:51 Alvaro Herrera <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Alvaro Herrera @ 2021-04-02 13:51 UTC (permalink / raw)
---
src/interfaces/libpq/fe-trace.c | 9 ++++++++-
.../modules/libpq_pipeline/traces/pipeline_abort.trace | 8 ++++----
src/test/modules/libpq_pipeline/traces/transaction.trace | 6 +++---
3 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/interfaces/libpq/fe-trace.c b/src/interfaces/libpq/fe-trace.c
index 9a4595f5c8..298713c602 100644
--- a/src/interfaces/libpq/fe-trace.c
+++ b/src/interfaces/libpq/fe-trace.c
@@ -540,7 +540,14 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
length = (int) pg_ntoh32(length);
logCursor += 4;
- fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
+ /*
+ * In regress mode, suppress the length of ErrorResponse and
+ * NoticeResponse -- they vary depending on compiler.
+ */
+ if (regress && !toServer && (id == 'E' || id == 'N'))
+ fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
+ else
+ fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
switch (id)
{
diff --git a/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace b/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
index b061435785..254e485997 100644
--- a/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
+++ b/src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
@@ -1,5 +1,5 @@
F 42 Query "DROP TABLE IF EXISTS pq_pipeline_demo"
-B 123 NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_demo" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_demo" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
B 15 CommandComplete "DROP TABLE"
B 5 ReadyForQuery I
F 99 Query "CREATE UNLOGGED TABLE pq_pipeline_demo(id serial primary key, itemno integer,int8filler int8);"
@@ -27,7 +27,7 @@ B 4 ParseComplete
B 4 BindComplete
B 4 NoData
B 15 CommandComplete "INSERT 0 1"
-B 217 ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" H "No function matches the given name and argument types. You might need to add explicit type casts." P "8" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" H "No function matches the given name and argument types. You might need to add explicit type casts." P "8" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I
B 4 ParseComplete
B 4 BindComplete
@@ -39,7 +39,7 @@ F 12 Bind "" "" 0 0 0
F 6 Describe P ""
F 9 Execute "" 0
F 4 Sync
-B 123 ErrorResponse S "ERROR" V "ERROR" C "42601" M "cannot insert multiple commands into a prepared statement" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "42601" M "cannot insert multiple commands into a prepared statement" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I
F 54 Parse "" "SELECT 1.0/g FROM generate_series(3, -1, -1) g" 0
F 12 Bind "" "" 0 0 0
@@ -52,7 +52,7 @@ B 33 RowDescription 1 "?column?" NNNN 0 NNNN 65535 -1 0
B 32 DataRow 1 22 '0.33333333333333333333'
B 32 DataRow 1 22 '0.50000000000000000000'
B 32 DataRow 1 22 '1.00000000000000000000'
-B 70 ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery I
F 40 Query "SELECT itemno FROM pq_pipeline_demo"
B 31 RowDescription 1 "itemno" NNNN 2 NNNN 4 -1 0
diff --git a/src/test/modules/libpq_pipeline/traces/transaction.trace b/src/test/modules/libpq_pipeline/traces/transaction.trace
index 0267a534fa..1dcc2373c0 100644
--- a/src/test/modules/libpq_pipeline/traces/transaction.trace
+++ b/src/test/modules/libpq_pipeline/traces/transaction.trace
@@ -1,5 +1,5 @@
F 79 Query "DROP TABLE IF EXISTS pq_pipeline_tst;CREATE TABLE pq_pipeline_tst (id int)"
-B 122 NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_tst" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_tst" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
B 15 CommandComplete "DROP TABLE"
B 17 CommandComplete "CREATE TABLE"
B 5 ReadyForQuery I
@@ -40,9 +40,9 @@ B 4 BindComplete
B 4 NoData
B 10 CommandComplete "BEGIN"
B 4 ParseComplete
-B 65 ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery E
-B 145 ErrorResponse S "ERROR" V "ERROR" C "25P02" M "current transaction is aborted, commands ignored until end of transaction block" F "SSSS" L "SSSS" R "SSSS" \x00
+B NN ErrorResponse S "ERROR" V "ERROR" C "25P02" M "current transaction is aborted, commands ignored until end of transaction block" F "SSSS" L "SSSS" R "SSSS" \x00
B 5 ReadyForQuery E
B 4 BindComplete
B 4 NoData
--
2.20.1
--6c2NcOVqGQ03X4Wi--
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v1 3/7] Row pattern recognition patch (planner).
@ 2023-06-25 11:48 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-06-25 11:48 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 13 ++++++++++---
src/include/nodes/plannodes.h | 9 +++++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 4bb38160b3..5ac65248a2 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,8 +287,8 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ List *runCondition, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2684,6 +2684,9 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6581,7 +6584,8 @@ make_windowagg(List *tlist, Index winref,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ List *runCondition, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6607,6 +6611,9 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..eb511176ac 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,15 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern Recognition PATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern Recognition DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Sun_Jun_25_21_05_09_2023_126)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v1-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v2 3/7] Row pattern recognition patch (planner).
@ 2023-06-26 08:05 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-06-26 08:05 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 19 ++++++++++++++-----
src/include/nodes/plannodes.h | 12 ++++++++++++
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 4bb38160b3..c10ac65a4c 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,9 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2684,6 +2684,10 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6580,8 +6584,9 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6607,6 +6612,10 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..cc942b9c12 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,18 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern Recognition PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern Recognition PATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern Recognition DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Mon_Jun_26_17_45_07_2023_724)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v2-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v3 3/7] Row pattern recognition patch (planner).
@ 2023-07-26 10:49 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-07-26 10:49 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 19 ++++++++++++++-----
src/include/nodes/plannodes.h | 12 ++++++++++++
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index af48109058..4b1ae0fb21 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,9 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2679,6 +2679,10 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6582,8 +6586,9 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6609,6 +6614,10 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..cc942b9c12 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,18 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern Recognition PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern Recognition PATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern Recognition DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Wed_Jul_26_21_21_34_2023_317)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v3-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v4 3/7] Row pattern recognition patch (planner).
@ 2023-08-09 07:56 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-08-09 07:56 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index af48109058..828d8d5b62 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2679,6 +2680,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6582,8 +6588,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6609,6 +6617,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 97fa561e4e..2ed00b5d41 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..19815a98bb 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Wed_Aug__9_17_41_12_2023_134)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v4-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v5 3/7] Row pattern recognition patch (planner).
@ 2023-09-02 06:32 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-09-02 06:32 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..e3c07ded65 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 97fa561e4e..2ed00b5d41 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..19815a98bb 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Sat_Sep__2_15_52_35_2023_273)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v5-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v6 3/7] Row pattern recognition patch (planner).
@ 2023-09-12 05:22 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-09-12 05:22 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 97fa561e4e..2ed00b5d41 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..afa27bb45a 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Tue_Sep_12_15_18_43_2023_359)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v6-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v7 3/7] Row pattern recognition patch (planner).
@ 2023-09-22 04:53 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-09-22 04:53 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 5700bfb5cd..648bf5a425 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..afa27bb45a 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Fri_Sep_22_14_16_40_2023_530)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v7-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v8 3/7] Row pattern recognition patch (planner).
@ 2023-09-25 05:01 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-09-25 05:01 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 5700bfb5cd..648bf5a425 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1b787fe031..afa27bb45a 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Mon_Sep_25_14_26_30_2023_752)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v8-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v9 3/7] Row pattern recognition patch (planner).
@ 2023-10-04 05:51 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-10-04 05:51 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 7962200885..20ce399763 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 8cafbf3f8a..e48b59517d 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Wed_Oct__4_15_03_28_2023_821)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v9-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v10 3/7] Row pattern recognition patch (planner).
@ 2023-10-22 02:22 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-10-22 02:22 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 23 +++++++++++++++++++++++
src/include/nodes/plannodes.h | 15 +++++++++++++++
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 7962200885..20ce399763 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2456,6 +2456,29 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes reference outputs of a subplan.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 8cafbf3f8a..e48b59517d 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1096,6 +1096,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Sun_Oct_22_11_39_20_2023_140)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v10-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v11 3/7] Row pattern recognition patch (planner).
@ 2023-11-08 06:57 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-11-08 06:57 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++-----
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 16 ++++++++++++++
4 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index fc3709510d..bda99d1c51 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -211,7 +211,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2456,6 +2455,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 73ff40721c..378644b2c4 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2129,6 +2129,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index d40af8e59f..827b86fea9 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1096,6 +1097,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Wed_Nov__8_16_37_05_2023_872)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v11-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v12 3/7] Row pattern recognition patch (planner).
@ 2023-12-04 11:23 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2023-12-04 11:23 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 16 ++++++++++++++
5 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 34ca6d4ac2..469fcd156b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index a8cea5efe1..7d4324e5e3 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -868,6 +868,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
wc->runCondition = (List *) preprocess_expression(root,
(Node *) wc->runCondition,
EXPRKIND_TARGET);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 4bb68ac90e..aa781494d3 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -211,7 +211,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2456,6 +2455,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 73ff40721c..378644b2c4 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2129,6 +2129,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index d40af8e59f..827b86fea9 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1096,6 +1097,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Fri_Dec__8_10_16_13_2023_489)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v12-0004-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v13 4/8] Row pattern recognition patch (planner).
@ 2024-01-22 09:45 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-01-22 09:45 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 23 ++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 16 ++++++++++++++
5 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index ca619eab94..3c7fd3867b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,10 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6601,8 +6607,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6628,6 +6636,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 2e2458b128..98fdfb06e3 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -868,6 +868,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
wc->runCondition = (List *) preprocess_expression(root,
(Node *) wc->runCondition,
EXPRKIND_TARGET);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 22a1fa29f3..d96bf6d3a0 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -211,7 +211,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2456,6 +2455,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index aa83dd3636..95d7399ab4 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2129,6 +2129,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index b4ef6bc44c..1b928e5a49 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1096,6 +1097,21 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /* Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of String) */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Mon_Jan_22_19_26_18_2024_011)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v13-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v14 4/8] Row pattern recognition patch (planner).
@ 2024-02-28 13:59 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-02-28 13:59 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 610f4a56d6..a9138e3395 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -286,9 +286,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2698,6 +2700,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6610,8 +6617,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6637,6 +6646,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index be4e182869..1ddfc3ed2d 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -870,6 +870,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
wc->runCondition = (List *) preprocess_expression(root,
(Node *) wc->runCondition,
EXPRKIND_TARGET);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 22a1fa29f3..6ab4eb759e 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -211,7 +211,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2456,6 +2455,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index aa83dd3636..95d7399ab4 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2129,6 +2129,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index b4ef6bc44c..3425796212 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1096,6 +1097,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Thu_Feb_29_09_19_54_2024_640)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v14-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v15 4/8] Row pattern recognition patch (planner).
@ 2024-03-28 10:30 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-03-28 10:30 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 5f479fc56c..fe51ad351e 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,9 +287,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2699,6 +2701,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6627,8 +6634,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6654,6 +6663,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 38d070fa00..82c370c4b4 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -869,6 +869,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
wc->runCondition = (List *) preprocess_expression(root,
(Node *) wc->runCondition,
EXPRKIND_TARGET);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 42603dbc7c..f7abb2be96 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2455,6 +2454,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 300691cc4d..3220072a51 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2147,6 +2147,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7f3db5105d..b0e50ae886 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1096,6 +1097,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Thu_Mar_28_19_59_25_2024_076)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v15-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v16 4/8] Row pattern recognition patch (planner).
@ 2024-04-12 06:49 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-04-12 06:49 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 3b77886567..c8d96be7d7 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,9 +287,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2700,6 +2702,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6629,8 +6636,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6656,6 +6665,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 5320da51a0..5eb66c709b 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -873,6 +873,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
wc->runCondition = (List *) preprocess_expression(root,
(Node *) wc->runCondition,
EXPRKIND_TARGET);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 37abcb4701..cd0e7c57d8 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2471,6 +2470,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 4badb6ff58..1c34360c7c 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2178,6 +2178,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index e025679f89..90441f4d90 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1098,6 +1099,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Fri_Apr_12_16_09_08_2024_262)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v16-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v17 4/8] Row pattern recognition patch (planner).
@ 2024-04-28 11:00 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-04-28 11:00 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 4 ++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 3b77886567..c8d96be7d7 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,9 +287,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2700,6 +2702,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
wc->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6629,8 +6636,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6656,6 +6665,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 5320da51a0..5eb66c709b 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -873,6 +873,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
wc->runCondition = (List *) preprocess_expression(root,
(Node *) wc->runCondition,
EXPRKIND_TARGET);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 37abcb4701..cd0e7c57d8 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2471,6 +2470,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 41da670f15..b453977178 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2182,6 +2182,10 @@ perform_pullup_replace_vars(PlannerInfo *root,
if (wc->runCondition != NIL)
wc->runCondition = (List *)
pullup_replace_vars((Node *) wc->runCondition, rvcontext);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
}
if (parse->onConflict)
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index e025679f89..90441f4d90 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1098,6 +1099,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Sun_Apr_28_20_28_26_2024_444)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v17-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v18 4/8] Row pattern recognition patch (planner).
@ 2024-05-11 07:11 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-05-11 07:11 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 9 ++++++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 6b64c4a362..ef2101e216 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,9 +287,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2700,6 +2702,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
best_path->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6629,8 +6636,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6656,6 +6665,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 032818423f..a5d17e3fda 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -870,6 +870,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
EXPRKIND_LIMIT);
wc->endOffset = preprocess_expression(root, wc->endOffset,
EXPRKIND_LIMIT);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 37abcb4701..cd0e7c57d8 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2471,6 +2470,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 5482ab85a7..f54db3f044 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2175,6 +2175,15 @@ perform_pullup_replace_vars(PlannerInfo *root,
parse->returningList = (List *)
pullup_replace_vars((Node *) parse->returningList, rvcontext);
+ foreach(lc, parse->windowClause)
+ {
+ WindowClause *wc = lfirst_node(WindowClause, lc);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
+ }
+
if (parse->onConflict)
{
parse->onConflict->onConflictSet = (List *)
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index e025679f89..90441f4d90 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1098,6 +1099,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Sat_May_11_16_23_07_2024_789)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v18-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v19 4/8] Row pattern recognition patch (planner).
@ 2024-05-14 23:26 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-05-14 23:26 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 9 ++++++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 6b64c4a362..ef2101e216 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,9 +287,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2700,6 +2702,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
best_path->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6629,8 +6636,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6656,6 +6665,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 032818423f..a5d17e3fda 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -870,6 +870,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
EXPRKIND_LIMIT);
wc->endOffset = preprocess_expression(root, wc->endOffset,
EXPRKIND_LIMIT);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 37abcb4701..cd0e7c57d8 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2471,6 +2470,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 5482ab85a7..f54db3f044 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2175,6 +2175,15 @@ perform_pullup_replace_vars(PlannerInfo *root,
parse->returningList = (List *)
pullup_replace_vars((Node *) parse->returningList, rvcontext);
+ foreach(lc, parse->windowClause)
+ {
+ WindowClause *wc = lfirst_node(WindowClause, lc);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
+ }
+
if (parse->onConflict)
{
parse->onConflict->onConflictSet = (List *)
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index e025679f89..90441f4d90 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1098,6 +1099,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Wed_May_15_09_02_03_2024_008)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v19-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v20 4/8] Row pattern recognition patch (planner).
@ 2024-05-24 02:26 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-05-24 02:26 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 9 ++++++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 6b64c4a362..ef2101e216 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -287,9 +287,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2700,6 +2702,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
best_path->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6629,8 +6636,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6656,6 +6665,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 032818423f..a5d17e3fda 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -870,6 +870,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
EXPRKIND_LIMIT);
wc->endOffset = preprocess_expression(root, wc->endOffset,
EXPRKIND_LIMIT);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 37abcb4701..cd0e7c57d8 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2471,6 +2470,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 5482ab85a7..f54db3f044 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2175,6 +2175,15 @@ perform_pullup_replace_vars(PlannerInfo *root,
parse->returningList = (List *)
pullup_replace_vars((Node *) parse->returningList, rvcontext);
+ foreach(lc, parse->windowClause)
+ {
+ WindowClause *wc = lfirst_node(WindowClause, lc);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
+ }
+
if (parse->onConflict)
{
parse->onConflict->onConflictSet = (List *)
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1aeeaec95e..5b8d8a6dac 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1098,6 +1099,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Fri_May_24_11_39_19_2024_763)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v20-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v21 4/8] Row pattern recognition patch (planner).
@ 2024-08-26 04:32 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-08-26 04:32 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 9 ++++++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 8e0e5977a9..a1b2c71364 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -288,9 +288,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2697,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
best_path->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6631,8 +6638,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6658,6 +6667,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index b5827d3980..ccb66336a8 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -870,6 +870,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
EXPRKIND_LIMIT);
wc->endOffset = preprocess_expression(root, wc->endOffset,
EXPRKIND_LIMIT);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 7aed84584c..7d726729ae 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -210,7 +210,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2471,6 +2470,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 969e257f70..3cedb5c8e5 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2175,6 +2175,15 @@ perform_pullup_replace_vars(PlannerInfo *root,
parse->returningList = (List *)
pullup_replace_vars((Node *) parse->returningList, rvcontext);
+ foreach(lc, parse->windowClause)
+ {
+ WindowClause *wc = lfirst_node(WindowClause, lc);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
+ }
+
if (parse->onConflict)
{
parse->onConflict->onConflictSet = (List *)
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 62cd6a6666..b7b2ac4aaf 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1099,6 +1100,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Mon_Aug_26_13_39_47_2024_878)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v21-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* [PATCH v22 4/8] Row pattern recognition patch (planner).
@ 2024-09-19 04:48 Tatsuo Ishii <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Tatsuo Ishii @ 2024-09-19 04:48 UTC (permalink / raw)
---
src/backend/optimizer/plan/createplan.c | 24 +++++++++++++++-----
src/backend/optimizer/plan/planner.c | 3 +++
src/backend/optimizer/plan/setrefs.c | 27 ++++++++++++++++++++++-
src/backend/optimizer/prep/prepjointree.c | 9 ++++++++
src/include/nodes/plannodes.h | 19 ++++++++++++++++
5 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index bb45ef318f..b0adb9cbd8 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -288,9 +288,11 @@ static WindowAgg *make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow,
- Plan *lefttree);
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp,
+ List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree);
static Group *make_group(List *tlist, List *qual, int numGroupCols,
AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
Plan *lefttree);
@@ -2697,6 +2699,11 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeAsc,
wc->inRangeNullsFirst,
best_path->runCondition,
+ wc->rpSkipTo,
+ wc->patternVariable,
+ wc->patternRegexp,
+ wc->defineClause,
+ wc->defineInitial,
best_path->qual,
best_path->topwindow,
subplan);
@@ -6631,8 +6638,10 @@ make_windowagg(List *tlist, Index winref,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
int frameOptions, Node *startOffset, Node *endOffset,
Oid startInRangeFunc, Oid endInRangeFunc,
- Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst,
- List *runCondition, List *qual, bool topWindow, Plan *lefttree)
+ Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition,
+ RPSkipTo rpSkipTo, List *patternVariable, List *patternRegexp, List *defineClause,
+ List *defineInitial,
+ List *qual, bool topWindow, Plan *lefttree)
{
WindowAgg *node = makeNode(WindowAgg);
Plan *plan = &node->plan;
@@ -6658,6 +6667,11 @@ make_windowagg(List *tlist, Index winref,
node->inRangeAsc = inRangeAsc;
node->inRangeNullsFirst = inRangeNullsFirst;
node->topWindow = topWindow;
+ node->rpSkipTo = rpSkipTo,
+ node->patternVariable = patternVariable;
+ node->patternRegexp = patternRegexp;
+ node->defineClause = defineClause;
+ node->defineInitial = defineInitial;
plan->targetlist = tlist;
plan->lefttree = lefttree;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index d92d43a17e..771b4b051d 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -879,6 +879,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
EXPRKIND_LIMIT);
wc->endOffset = preprocess_expression(root, wc->endOffset,
EXPRKIND_LIMIT);
+ wc->defineClause = (List *) preprocess_expression(root,
+ (Node *) wc->defineClause,
+ EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 91c7c4fe2f..b5310e0d72 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -211,7 +211,6 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
@@ -2495,6 +2494,32 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
NRM_EQUAL,
NUM_EXEC_QUAL(plan));
+ /*
+ * Modifies an expression tree in each DEFINE clause so that all Var
+ * nodes's varno refers to OUTER_VAR.
+ */
+ if (IsA(plan, WindowAgg))
+ {
+ WindowAgg *wplan = (WindowAgg *) plan;
+
+ if (wplan->defineClause != NIL)
+ {
+ foreach(l, wplan->defineClause)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+
+ tle->expr = (Expr *)
+ fix_upper_expr(root,
+ (Node *) tle->expr,
+ subplan_itlist,
+ OUTER_VAR,
+ rtoffset,
+ NRM_EQUAL,
+ NUM_EXEC_QUAL(plan));
+ }
+ }
+ }
+
pfree(subplan_itlist);
}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index a70404558f..d4b08a2e48 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2176,6 +2176,15 @@ perform_pullup_replace_vars(PlannerInfo *root,
parse->returningList = (List *)
pullup_replace_vars((Node *) parse->returningList, rvcontext);
+ foreach(lc, parse->windowClause)
+ {
+ WindowClause *wc = lfirst_node(WindowClause, lc);
+
+ if (wc->defineClause != NIL)
+ wc->defineClause = (List *)
+ pullup_replace_vars((Node *) wc->defineClause, rvcontext);
+ }
+
if (parse->onConflict)
{
parse->onConflict->onConflictSet = (List *)
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 62cd6a6666..b7b2ac4aaf 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -20,6 +20,7 @@
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
@@ -1099,6 +1100,24 @@ typedef struct WindowAgg
/* nulls sort first for in_range tests? */
bool inRangeNullsFirst;
+ /* Row Pattern Recognition AFTER MACH SKIP clause */
+ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */
+
+ /* Row Pattern PATTERN variable name (list of String) */
+ List *patternVariable;
+
+ /*
+ * Row Pattern RPATTERN regular expression quantifier ('+' or ''. list of
+ * String)
+ */
+ List *patternRegexp;
+
+ /* Row Pattern DEFINE clause (list of TargetEntry) */
+ List *defineClause;
+
+ /* Row Pattern DEFINE variable initial names (list of String) */
+ List *defineInitial;
+
/*
* false for all apart from the WindowAgg that's closest to the root of
* the plan
--
2.25.1
----Next_Part(Thu_Sep_19_13_59_47_2024_608)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="v22-0005-Row-pattern-recognition-patch-executor.patch"
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
@ 2026-02-18 07:16 Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Shinya Kato @ 2026-02-18 07:16 UTC (permalink / raw)
To: Nathan Bossart <[email protected]>; +Cc: pgsql-hackers
On Sat, Nov 15, 2025 at 2:05 AM Nathan Bossart <[email protected]> wrote:
> I don't know about you, but I start getting antsy around a quarter tank.
> In any case, I'm told that even 40M transactions aren't enough time to
> react these days. Attached are a few patches to enhance the wraparound
> warnings.
Thank you for the patch!
> * 0001 adds a "percent remaining" detail message to the existing WARNING.
> The idea is that "1.86% of transaction IDs" is both easier to understand
> and better indicates urgency than "39985967 transactions".
I like this idea and this is helpful information for DBA. 0001 looks good to me.
> * 0002 bumps the warning limit from 40M to 100M to give folks some more
> time to react.
I don't have a strong opinion on whether 100M is the right value, but
I noticed a documentation issue in 0002.
<programlisting>
WARNING: database "mydb" must be vacuumed within 39985967 transactions
DETAIL: Approximately 1.86% of transaction IDs are available for use.
HINT: To avoid XID assignment failures, execute a database-wide
VACUUM in that database.
</programlisting>
In maintenance.sgml, above "39985967" and "1.86%" should be updated.
> * 0003 adds an early warning system for when fewer than 500M transactions
> remain. This system sends a LOG only to the server log every 1M
> transactions. The hope is that this gets someone's attention sooner
> without flooding the application and server log.
I'm not sure 0003 is worth the added complexity. It adds a new field
to TransamVariablesData and a modulo check in GetNewTransactionId(),
which is a hot path. DBAs who need early warning can already monitor
age(datfrozenxid) with more flexible thresholds.
--
Best regards,
Shinya Kato
NTT OSS Center
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
@ 2026-03-03 20:31 ` Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Nathan Bossart @ 2026-03-03 20:31 UTC (permalink / raw)
To: Shinya Kato <[email protected]>; +Cc: pgsql-hackers
On Wed, Feb 18, 2026 at 04:16:16PM +0900, Shinya Kato wrote:
> On Sat, Nov 15, 2025 at 2:05 AM Nathan Bossart <[email protected]> wrote:
>> I don't know about you, but I start getting antsy around a quarter tank.
>> In any case, I'm told that even 40M transactions aren't enough time to
>> react these days. Attached are a few patches to enhance the wraparound
>> warnings.
>
> Thank you for the patch!
Thanks for reviewing.
> I don't have a strong opinion on whether 100M is the right value, but
> I noticed a documentation issue in 0002.
>
> <programlisting>
> WARNING: database "mydb" must be vacuumed within 39985967 transactions
> DETAIL: Approximately 1.86% of transaction IDs are available for use.
> HINT: To avoid XID assignment failures, execute a database-wide
> VACUUM in that database.
> </programlisting>
>
> In maintenance.sgml, above "39985967" and "1.86%" should be updated.
Fixed.
> I'm not sure 0003 is worth the added complexity. It adds a new field
> to TransamVariablesData and a modulo check in GetNewTransactionId(),
> which is a hot path. DBAs who need early warning can already monitor
> age(datfrozenxid) with more flexible thresholds.
Yeah, looking at this one again, I'm less sure it's worth pursuing. I've
removed it.
--
nathan
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
@ 2026-03-06 22:15 ` Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Nathan Bossart @ 2026-03-06 22:15 UTC (permalink / raw)
To: Shinya Kato <[email protected]>; +Cc: pgsql-hackers
Barring additional feedback or objections, I'm planning to commit this in
the next week or two.
--
nathan
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
@ 2026-03-09 12:08 ` wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: wenhui qiu @ 2026-03-09 12:08 UTC (permalink / raw)
To: Nathan Bossart <[email protected]>; +Cc: Shinya Kato <[email protected]>; pgsql-hackers
Hi Nathan Bossart
> Barring additional feedback or objections, I'm planning to commit this in
> the next week or two.
Thank you for working on this. The path LGTM,But I have a small request,There
are many reasons why the table's age can’t be frozen. Now have a path that
can report the reason to users(https://commitfest.postgresql.org/patch/6188/).
Would you be interested in reviewing it? I think we should tell users the
root cause of why the age can’t be reduced, so they can clearly understand
where the issue is.I think we should not only tell users that the XID is
close to wraparound, but also report why this causes the table‘s age to be
unable to freeze.
Thanks
On Sat, Mar 7, 2026 at 6:15 AM Nathan Bossart <[email protected]>
wrote:
> Barring additional feedback or objections, I'm planning to commit this in
> the next week or two.
>
> --
> nathan
>
>
>
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
@ 2026-03-20 19:16 ` Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Nathan Bossart @ 2026-03-20 19:16 UTC (permalink / raw)
To: wenhui qiu <[email protected]>; +Cc: Shinya Kato <[email protected]>; pgsql-hackers
On Mon, Mar 09, 2026 at 08:08:54PM +0800, wenhui qiu wrote:
> Thank you for working on this. The path LGTM,...
Thanks for looking. Committed.
> ...But I have a small request,There
> are many reasons why the table's age can’t be frozen. Now have a path that
> can report the reason to users(https://commitfest.postgresql.org/patch/6188/).
> Would you be interested in reviewing it? I think we should tell users the
> root cause of why the age can’t be reduced, so they can clearly understand
> where the issue is.I think we should not only tell users that the XID is
> close to wraparound, but also report why this causes the table‘s age to be
> unable to freeze.
Thanks for alerting me to this patch.
--
nathan
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
@ 2026-06-19 18:13 ` Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Fujii Masao @ 2026-06-19 18:13 UTC (permalink / raw)
To: Nathan Bossart <[email protected]>; +Cc: wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
On Sat, Mar 21, 2026 at 4:16 AM Nathan Bossart <[email protected]> wrote:
>
> On Mon, Mar 09, 2026 at 08:08:54PM +0800, wenhui qiu wrote:
> > Thank you for working on this. The path LGTM,...
>
> Thanks for looking. Committed.
Thanks for working on this feature! I have one comment.
ereport(WARNING,
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - xid),
+ errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ (double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
errhint("To avoid transaction ID assignment failures, execute a
database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared
transactions, or drop stale replication slots.")));
The new DETAIL messages for XID and MultiXactId wraparound warnings
seem misleading.
The percentage is calculated as (xidWrapLimit - xid) divided by half
of the ID space. This represents the remaining ID space before wraparound,
not the percentage of IDs that are still available for use. Since
PostgreSQL stops assigning new XIDs/MultiXactIds at the stop limit
before reaching the wraparound limit, the current wording could be
interpreted as overstating how many IDs remain usable.
So, how about changing the wording to match the calculation? For example:
Approximately XX.XX% of transaction ID space remains before wraparound.
and similarly for MultiXactIds.
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v1-0001-Clarify-wraparound-warning-percentage-messages.patch (7.2K, ../../CAHGQGwHWZTsR6bjdfpa+pOkBPjoXXm2LuJ+5nh+CvdyqEASHcQ@mail.gmail.com/2-v1-0001-Clarify-wraparound-warning-percentage-messages.patch)
download | inline diff:
From 37d758c78186e6848026a659ca1b35f94c49c248 Mon Sep 17 00:00:00 2001
From: "masao.fujii" <[email protected]'s-MacBook-Pro>
Date: Sat, 20 Jun 2026 02:33:37 +0900
Subject: [PATCH v1] Clarify wraparound warning percentage messages
Commit e646450e609 added DETAIL messages for XID and MultiXactId
wraparound warnings describing the reported percentage as the IDs
available for use. However, the percentage is actually calculated from
the remaining distance to the wraparound limit, not the stop limit
where new IDs are refused. As a result, the wording could be
misinterpreted as meaning that the reported percentage of IDs can still
be allocated.
Update the wording to clarify that the reported percentage represents
the remaining ID space before wraparound.
---
doc/src/sgml/maintenance.sgml | 2 +-
src/backend/access/transam/multixact.c | 8 ++++----
src/backend/access/transam/varsup.c | 8 ++++----
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index e341f165efd..a5a779e2e62 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -674,7 +674,7 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
<programlisting>
WARNING: database "mydb" must be vacuumed within 99985967 transactions
-DETAIL: Approximately 4.66% of transaction IDs are available for use.
+DETAIL: Approximately 4.66% of transaction ID space remains before wraparound.
HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.
</programlisting>
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 10cbc0d76bd..079f5967e74 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1070,7 +1070,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datname,
multiWrapLimit - result),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100),
errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -1081,7 +1081,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datoid,
multiWrapLimit - result),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100),
errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -2208,7 +2208,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datname,
multiWrapLimit - curMulti),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100),
errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -2219,7 +2219,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datoid,
multiWrapLimit - curMulti),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100),
errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index dc5e32d86f3..e0b280665cf 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -166,7 +166,7 @@ GetNewTransactionId(bool isSubXact)
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - xid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -175,7 +175,7 @@ GetNewTransactionId(bool isSubXact)
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - xid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -485,7 +485,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - curXid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -494,7 +494,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - curXid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
@ 2026-06-19 18:43 ` Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Nathan Bossart @ 2026-06-19 18:43 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
On Sat, Jun 20, 2026 at 03:13:23AM +0900, Fujii Masao wrote:
> The percentage is calculated as (xidWrapLimit - xid) divided by half
> of the ID space. This represents the remaining ID space before wraparound,
> not the percentage of IDs that are still available for use. Since
> PostgreSQL stops assigning new XIDs/MultiXactIds at the stop limit
> before reaching the wraparound limit, the current wording could be
> interpreted as overstating how many IDs remain usable.
>
> So, how about changing the wording to match the calculation? For example:
>
> Approximately XX.XX% of transaction ID space remains before wraparound.
>
> and similarly for MultiXactIds.
That seems reasonable to me, thanks.
--
nathan
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
@ 2026-06-20 11:54 ` Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Fujii Masao @ 2026-06-20 11:54 UTC (permalink / raw)
To: Nathan Bossart <[email protected]>; +Cc: wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
On Sat, Jun 20, 2026 at 3:43 AM Nathan Bossart <[email protected]> wrote:
>
> On Sat, Jun 20, 2026 at 03:13:23AM +0900, Fujii Masao wrote:
> > The percentage is calculated as (xidWrapLimit - xid) divided by half
> > of the ID space. This represents the remaining ID space before wraparound,
> > not the percentage of IDs that are still available for use. Since
> > PostgreSQL stops assigning new XIDs/MultiXactIds at the stop limit
> > before reaching the wraparound limit, the current wording could be
> > interpreted as overstating how many IDs remain usable.
> >
> > So, how about changing the wording to match the calculation? For example:
> >
> > Approximately XX.XX% of transaction ID space remains before wraparound.
> >
> > and similarly for MultiXactIds.
>
> That seems reasonable to me, thanks.
Thanks for the review!
While reading the related log messages again, I noticed that in three of
the four XID wraparound warnings in varsup.c, the HINT still uses "XID"
while the DETAIL message uses "transaction ID". Commit edee0c621de
updated the remaining warning to use "transaction ID",
but seems to have missed the other three. Since using different terms
for the same thing in the DETAIL and HINT messages seems
inconsistent, I included the following changes in the patch. Or would
it be better to do this in a separate patch?
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains
before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide
VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a
database-wide VACUUM in that database.\n"
I also updated the comments in
src/test/modules/xid_wraparound/t/002_limits.pl, which contain
examples of the XID wraparound warnings.
Attached is the updated patch.
While making these changes, I also noticed that although commit
edee0c621de updated the runtime XID wraparound messages to use
"transaction IDs", the corresponding examples and text in
maintenance.sgml still use the older "XID" terminology. I therefore
created an additional patch (0002) to update the documentation to
match the current messages. I think this should be backpatched to v17.
Thought?
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v2-0001-Clarify-wraparound-warning-percentage-messages.patch (8.5K, ../../CAHGQGwHTN-Xc5iDtbzNSjfxuab5Y9qAArw8cB4PrrDJpZ+1fgA@mail.gmail.com/2-v2-0001-Clarify-wraparound-warning-percentage-messages.patch)
download | inline diff:
From 011fa9d25af818d79c22b7159c3788dd294a1b09 Mon Sep 17 00:00:00 2001
From: "masao.fujii" <[email protected]'s-MacBook-Pro>
Date: Sat, 20 Jun 2026 19:49:58 +0900
Subject: [PATCH v2 1/2] Clarify wraparound warning percentage messages
Commit e646450e609 added DETAIL messages for XID and MultiXactId
wraparound warnings describing the reported percentage as the IDs
available for use. However, the percentage is actually calculated from
the remaining distance to the wraparound limit, not the stop limit
where new IDs are refused. As a result, the wording could be
misinterpreted as meaning that the reported percentage of IDs can still
be allocated.
Update the wording to clarify that the reported percentage represents
the remaining ID space before wraparound.
Also update the related XID warning hints to use "transaction ID"
terminology consistently.
---
doc/src/sgml/maintenance.sgml | 2 +-
src/backend/access/transam/multixact.c | 8 ++++----
src/backend/access/transam/varsup.c | 14 +++++++-------
src/test/modules/xid_wraparound/t/002_limits.pl | 3 ++-
4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index e341f165efd..a5a779e2e62 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -674,7 +674,7 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
<programlisting>
WARNING: database "mydb" must be vacuumed within 99985967 transactions
-DETAIL: Approximately 4.66% of transaction IDs are available for use.
+DETAIL: Approximately 4.66% of transaction ID space remains before wraparound.
HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.
</programlisting>
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 10cbc0d76bd..079f5967e74 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1070,7 +1070,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datname,
multiWrapLimit - result),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100),
errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -1081,7 +1081,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datoid,
multiWrapLimit - result),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100),
errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -2208,7 +2208,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datname,
multiWrapLimit - curMulti),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100),
errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -2219,7 +2219,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datoid,
multiWrapLimit - curMulti),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.",
(double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100),
errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index dc5e32d86f3..cb68d8fa974 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -166,7 +166,7 @@ GetNewTransactionId(bool isSubXact)
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - xid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -175,9 +175,9 @@ GetNewTransactionId(bool isSubXact)
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - xid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
}
@@ -485,18 +485,18 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - curXid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
else
ereport(WARNING,
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - curXid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.",
(double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
}
}
diff --git a/src/test/modules/xid_wraparound/t/002_limits.pl b/src/test/modules/xid_wraparound/t/002_limits.pl
index 86632a8d510..29d071a677b 100644
--- a/src/test/modules/xid_wraparound/t/002_limits.pl
+++ b/src/test/modules/xid_wraparound/t/002_limits.pl
@@ -70,7 +70,8 @@ $node->safe_psql('postgres',
# the warning:
#
# WARNING: database "postgres" must be vacuumed within 3000024 transactions
-# HINT: To avoid a database shutdown, execute a database-wide VACUUM in that database.
+# DETAIL: Approximately 0.14% of transaction ID space remains before wraparound.
+# HINT: To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.
# You might also need to commit or roll back old prepared transactions, or drop stale replication slots.
my $stderr;
my $warn_limit = 0;
--
2.53.0
[application/octet-stream] v2-0002-doc-Update-wraparound-examples-to-say-transaction.patch (2.2K, ../../CAHGQGwHTN-Xc5iDtbzNSjfxuab5Y9qAArw8cB4PrrDJpZ+1fgA@mail.gmail.com/3-v2-0002-doc-Update-wraparound-examples-to-say-transaction.patch)
download | inline diff:
From 6d1a0eb207cca2e70516fdffb60be7689ba4b8d7 Mon Sep 17 00:00:00 2001
From: "masao.fujii" <[email protected]'s-MacBook-Pro>
Date: Sat, 20 Jun 2026 19:50:03 +0900
Subject: [PATCH v2 2/2] doc: Update wraparound examples to say transaction IDs
Commit edee0c621de changed the runtime XID wraparound messages to
use "transaction IDs" terminology, but the corresponding
examples and text in maintenance.sgml still used the older XID wording.
Update those documentation examples into line with the current runtime
messages.
Backpatch to v17, where the runtime messages were changed.
---
doc/src/sgml/maintenance.sgml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index a5a779e2e62..8043fb36625 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -675,18 +675,18 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
<programlisting>
WARNING: database "mydb" must be vacuumed within 99985967 transactions
DETAIL: Approximately 4.66% of transaction ID space remains before wraparound.
-HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.
+HINT: To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.
</programlisting>
(A manual <command>VACUUM</command> should fix the problem, as suggested by the
hint; but note that the <command>VACUUM</command> should be performed by a
superuser, else it will fail to process system catalogs, which prevent it from
being able to advance the database's <structfield>datfrozenxid</structfield>.)
- If these warnings are ignored, the system will refuse to assign new XIDs once
+ If these warnings are ignored, the system will refuse to assign new transaction IDs once
there are fewer than three million transactions left until wraparound:
<programlisting>
-ERROR: database is not accepting commands that assign new XIDs to avoid wraparound data loss in database "mydb"
+ERROR: database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database "mydb"
HINT: Execute a database-wide VACUUM in that database.
</programlisting>
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
@ 2026-06-24 04:47 ` Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Bharath Rupireddy @ 2026-06-24 04:47 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Nathan Bossart <[email protected]>; wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
Hi,
On Sat, Jun 20, 2026 at 4:54 AM Fujii Masao <[email protected]> wrote:
>
> While making these changes, I also noticed that although commit
> edee0c621de updated the runtime XID wraparound messages to use
> "transaction IDs", the corresponding examples and text in
> maintenance.sgml still use the older "XID" terminology. I therefore
> created an additional patch (0002) to update the documentation to
> match the current messages. I think this should be backpatched to v17.
>
> Thought?
I happened to quickly review these patches. TBH, "transaction ID
space" and "MultiXactId space" seem a bit confusing because of the
word "space" - it reads fine without it. Is there a specific reason
for this wording?
Also, why not use "multixact IDs" instead of "MultiXactId"? The latter
reads like an internal structure name or such that might confuse users
reading the docs or error messages.
How about something like the following?
+ errdetail("Approximately %.2f%% of multixact IDs remain before wraparound.",
+ errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
@ 2026-06-24 12:53 ` Fujii Masao <[email protected]>
2026-06-25 17:19 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Fujii Masao @ 2026-06-24 12:53 UTC (permalink / raw)
To: Bharath Rupireddy <[email protected]>; +Cc: Nathan Bossart <[email protected]>; wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
On Wed, Jun 24, 2026 at 1:47 PM Bharath Rupireddy
<[email protected]> wrote:
> I happened to quickly review these patches.
Thanks for the review!
> TBH, "transaction ID
> space" and "MultiXactId space" seem a bit confusing because of the
> word "space" - it reads fine without it. Is there a specific reason
> for this wording?
I was thinking "space" was appropriate here because the message is intended
to express the percentage remaining before wraparound in the ID range.
The documentation also uses expressions such as "normal XID space is ...".
But I'm not a native English speaker, so this wording might be wrong.
> Also, why not use "multixact IDs" instead of "MultiXactId"? The latter
> reads like an internal structure name or such that might confuse users
> reading the docs or error messages.
I left "MultiXactId" unchanged because several existing log messages
use that term. I don't have any strong objection to changing it to
"multixact ID", which is already used in the documentation. However, if
we do that, I think it's better update all log messages that use
"MultiXactId" for consistency, probably as a separate patch. That seems
more like a v20 item to me, though.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
@ 2026-06-25 17:19 ` Bharath Rupireddy <[email protected]>
2026-06-26 00:51 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Bharath Rupireddy @ 2026-06-25 17:19 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Nathan Bossart <[email protected]>; wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
Hi,
On Wed, Jun 24, 2026 at 5:53 AM Fujii Masao <[email protected]> wrote:
>
> > TBH, "transaction ID
> > space" and "MultiXactId space" seem a bit confusing because of the
> > word "space" - it reads fine without it. Is there a specific reason
> > for this wording?
>
> I was thinking "space" was appropriate here because the message is intended
> to express the percentage remaining before wraparound in the ID range.
> The documentation also uses expressions such as "normal XID space is ...".
The use there is referring to the whole set of transaction IDs and how
one can visualize the use of them - so "XID space" in that context
seems fine to me.
But the wraparound warnings read better when they say how many more
transaction IDs are left:
+ errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
+ errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
> > Also, why not use "multixact IDs" instead of "MultiXactId"? The latter
> > reads like an internal structure name or such that might confuse users
> > reading the docs or error messages.
>
> I left "MultiXactId" unchanged because several existing log messages
> use that term. I don't have any strong objection to changing it to
> "multixact ID", which is already used in the documentation. However, if
> we do that, I think it's better update all log messages that use
> "MultiXactId" for consistency, probably as a separate patch. That seems
> more like a v20 item to me, though.
I'm fine to leave "MultiXactIds" as-is - IMHO, it's not worth the cycles.
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-25 17:19 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
@ 2026-06-26 00:51 ` Fujii Masao <[email protected]>
2026-06-26 01:55 ` Re: enhance wraparound warnings Kyotaro Horiguchi <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Fujii Masao @ 2026-06-26 00:51 UTC (permalink / raw)
To: Bharath Rupireddy <[email protected]>; +Cc: Nathan Bossart <[email protected]>; wenhui qiu <[email protected]>; Shinya Kato <[email protected]>; pgsql-hackers
On Fri, Jun 26, 2026 at 2:19 AM Bharath Rupireddy
<[email protected]> wrote:
> The use there is referring to the whole set of transaction IDs and how
> one can visualize the use of them - so "XID space" in that context
> seems fine to me.
>
> But the wraparound warnings read better when they say how many more
> transaction IDs are left:
>
> + errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
> + errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
Okay, I've updated the patches as suggested. The updated patches are attached.
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v3-0001-Clarify-wraparound-warning-percentage-messages.patch (8.4K, ../../CAHGQGwHHPzYw2qbtwdkmyC+3pLW1aT1p6gUKx4WWhANiJhob2g@mail.gmail.com/2-v3-0001-Clarify-wraparound-warning-percentage-messages.patch)
download | inline diff:
From 60833ae74d510e6b4f447905da260433f4546569 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Fri, 26 Jun 2026 09:11:03 +0900
Subject: [PATCH v3 1/2] Clarify wraparound warning percentage messages
Commit e646450e609 added DETAIL messages for XID and MultiXactId
wraparound warnings describing the reported percentage as the IDs
available for use. However, the percentage is actually calculated from
the remaining distance to the wraparound limit, not the stop limit
where new IDs are refused. As a result, the wording could be
misinterpreted as meaning that the reported percentage of IDs can still
be allocated.
Update the wording to clarify that the reported percentage represents
the remaining IDs before wraparound.
Also update the related XID warning hints to use "transaction ID"
terminology consistently.
---
doc/src/sgml/maintenance.sgml | 2 +-
src/backend/access/transam/multixact.c | 8 ++++----
src/backend/access/transam/varsup.c | 14 +++++++-------
src/test/modules/xid_wraparound/t/002_limits.pl | 3 ++-
4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index e341f165efd..2932ba6a30a 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -674,7 +674,7 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
<programlisting>
WARNING: database "mydb" must be vacuumed within 99985967 transactions
-DETAIL: Approximately 4.66% of transaction IDs are available for use.
+DETAIL: Approximately 4.66% of transaction IDs remain before wraparound.
HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.
</programlisting>
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 10cbc0d76bd..7ce615c3eb9 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1070,7 +1070,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datname,
multiWrapLimit - result),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
(double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100),
errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -1081,7 +1081,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datoid,
multiWrapLimit - result),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
(double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100),
errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -2208,7 +2208,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datname,
multiWrapLimit - curMulti),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
(double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100),
errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -2219,7 +2219,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datoid,
multiWrapLimit - curMulti),
- errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
(double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100),
errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index dc5e32d86f3..d61fe68210e 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -166,7 +166,7 @@ GetNewTransactionId(bool isSubXact)
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - xid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
@@ -175,9 +175,9 @@ GetNewTransactionId(bool isSubXact)
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - xid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
(double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
}
@@ -485,18 +485,18 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
(errmsg("database \"%s\" must be vacuumed within %u transactions",
oldest_datname,
xidWrapLimit - curXid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
(double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
else
ereport(WARNING,
(errmsg("database with OID %u must be vacuumed within %u transactions",
oldest_datoid,
xidWrapLimit - curXid),
- errdetail("Approximately %.2f%% of transaction IDs are available for use.",
+ errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
(double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
- errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n"
+ errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
}
}
diff --git a/src/test/modules/xid_wraparound/t/002_limits.pl b/src/test/modules/xid_wraparound/t/002_limits.pl
index 86632a8d510..236bea2588c 100644
--- a/src/test/modules/xid_wraparound/t/002_limits.pl
+++ b/src/test/modules/xid_wraparound/t/002_limits.pl
@@ -70,7 +70,8 @@ $node->safe_psql('postgres',
# the warning:
#
# WARNING: database "postgres" must be vacuumed within 3000024 transactions
-# HINT: To avoid a database shutdown, execute a database-wide VACUUM in that database.
+# DETAIL: Approximately 0.14% of transaction IDs remain before wraparound.
+# HINT: To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.
# You might also need to commit or roll back old prepared transactions, or drop stale replication slots.
my $stderr;
my $warn_limit = 0;
--
2.53.0
[application/octet-stream] v3-0002-doc-Update-wraparound-examples-to-say-transaction.patch (2.2K, ../../CAHGQGwHHPzYw2qbtwdkmyC+3pLW1aT1p6gUKx4WWhANiJhob2g@mail.gmail.com/3-v3-0002-doc-Update-wraparound-examples-to-say-transaction.patch)
download | inline diff:
From 27d395abaad4e8d9c2220245e7b5101d5e65b4d6 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Fri, 26 Jun 2026 08:33:10 +0900
Subject: [PATCH v3 2/2] doc: Update wraparound examples to say transaction IDs
Commit edee0c621de changed the runtime XID wraparound messages to
use "transaction IDs" terminology, but the corresponding
examples and text in maintenance.sgml still used the older XID wording.
Update those documentation examples into line with the current runtime
messages.
Backpatch to v17, where the runtime messages were changed.
---
doc/src/sgml/maintenance.sgml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 2932ba6a30a..add170e5737 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -675,18 +675,18 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
<programlisting>
WARNING: database "mydb" must be vacuumed within 99985967 transactions
DETAIL: Approximately 4.66% of transaction IDs remain before wraparound.
-HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.
+HINT: To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.
</programlisting>
(A manual <command>VACUUM</command> should fix the problem, as suggested by the
hint; but note that the <command>VACUUM</command> should be performed by a
superuser, else it will fail to process system catalogs, which prevent it from
being able to advance the database's <structfield>datfrozenxid</structfield>.)
- If these warnings are ignored, the system will refuse to assign new XIDs once
+ If these warnings are ignored, the system will refuse to assign new transaction IDs once
there are fewer than three million transactions left until wraparound:
<programlisting>
-ERROR: database is not accepting commands that assign new XIDs to avoid wraparound data loss in database "mydb"
+ERROR: database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database "mydb"
HINT: Execute a database-wide VACUUM in that database.
</programlisting>
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-25 17:19 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-26 00:51 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
@ 2026-06-26 01:55 ` Kyotaro Horiguchi <[email protected]>
2026-06-26 18:06 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Kyotaro Horiguchi @ 2026-06-26 01:55 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; pgsql-hackers
Hello,
At Fri, 26 Jun 2026 09:51:16 +0900, Fujii Masao <[email protected]> wrote in
> On Fri, Jun 26, 2026 at 2:19 AM Bharath Rupireddy
> <[email protected]> wrote:
> > The use there is referring to the whole set of transaction IDs and how
> > one can visualize the use of them - so "XID space" in that context
> > seems fine to me.
> >
> > But the wraparound warnings read better when they say how many more
> > transaction IDs are left:
> >
> > + errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
> > + errdetail("Approximately %.2f%% of transaction IDs remain before wraparound.",
>
> Okay, I've updated the patches as suggested. The updated patches are attached.
I'm not sure I'm following this correctly, but the explanation above
sounded to me as if the warning should report the number of IDs
remaining before wraparound, e.g. "Approximately N MultiXactIds remain
before wraparound", so I'm a bit confused by the proposed wording.
> + errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
The attached patch adopts that wording. However, I'm not sure how to
interpret it. The value is still expressed as a percentage, but it is
no longer clear what that percentage is relative to.
Whichever approach we choose, I think the wording should be explicit.
If the value is reported as a percentage, then something like "x.xx%
of MultiXactId space remains" seems clearer to me. If it is reported
as a count, then "N MultiXactIds remain" would make more sense.
Regards,
--
Kyotaro Horiguchi
NTT Open Source Software Center
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-25 17:19 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-26 00:51 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-26 01:55 ` Re: enhance wraparound warnings Kyotaro Horiguchi <[email protected]>
@ 2026-06-26 18:06 ` Nathan Bossart <[email protected]>
2026-06-26 22:18 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Nathan Bossart @ 2026-06-26 18:06 UTC (permalink / raw)
To: Kyotaro Horiguchi <[email protected]>; +Cc: [email protected]; [email protected]; [email protected]; [email protected]; pgsql-hackers
On Fri, Jun 26, 2026 at 10:55:39AM +0900, Kyotaro Horiguchi wrote:
> I'm not sure I'm following this correctly, but the explanation above
> sounded to me as if the warning should report the number of IDs
> remaining before wraparound, e.g. "Approximately N MultiXactIds remain
> before wraparound", so I'm a bit confused by the proposed wording.
We already report the number of IDs remaining in the WARNING message. In
v19, I've added a DETAIL message that also reports the percentage
remaining, with the hope that it makes the urgency clearer.
>> + errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
>
> The attached patch adopts that wording. However, I'm not sure how to
> interpret it. The value is still expressed as a percentage, but it is
> no longer clear what that percentage is relative to.
>
> Whichever approach we choose, I think the wording should be explicit.
> If the value is reported as a percentage, then something like "x.xx%
> of MultiXactId space remains" seems clearer to me. If it is reported
> as a count, then "N MultiXactIds remain" would make more sense.
I find both "percentage of IDs remaining" and "percentage of ID space
remaining" equally clear and have no strong opinion on the matter.
--
nathan
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: enhance wraparound warnings
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-25 17:19 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-26 00:51 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-26 01:55 ` Re: enhance wraparound warnings Kyotaro Horiguchi <[email protected]>
2026-06-26 18:06 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
@ 2026-06-26 22:18 ` Bharath Rupireddy <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Bharath Rupireddy @ 2026-06-26 22:18 UTC (permalink / raw)
To: Nathan Bossart <[email protected]>; +Cc: Kyotaro Horiguchi <[email protected]>; [email protected]; [email protected]; [email protected]; pgsql-hackers
Hi,
On Fri, Jun 26, 2026 at 11:06 AM Nathan Bossart
<[email protected]> wrote:
>
> On Fri, Jun 26, 2026 at 10:55:39AM +0900, Kyotaro Horiguchi wrote:
> > I'm not sure I'm following this correctly, but the explanation above
> > sounded to me as if the warning should report the number of IDs
> > remaining before wraparound, e.g. "Approximately N MultiXactIds remain
> > before wraparound", so I'm a bit confused by the proposed wording.
>
> We already report the number of IDs remaining in the WARNING message. In
> v19, I've added a DETAIL message that also reports the percentage
> remaining, with the hope that it makes the urgency clearer.
Yes. For example: WARNING: database "mydb" must be vacuumed within
99985967 transactions
> >> + errdetail("Approximately %.2f%% of MultiXactIds remain before wraparound.",
> >
> > The attached patch adopts that wording. However, I'm not sure how to
> > interpret it. The value is still expressed as a percentage, but it is
> > no longer clear what that percentage is relative to.
> >
> > Whichever approach we choose, I think the wording should be explicit.
> > If the value is reported as a percentage, then something like "x.xx%
> > of MultiXactId space remains" seems clearer to me. If it is reported
> > as a count, then "N MultiXactIds remain" would make more sense.
>
> I find both "percentage of IDs remaining" and "percentage of ID space
> remaining" equally clear and have no strong opinion on the matter.
My initial comment was that "IDs remaining" reads more naturally to me
than "ID space remaining," but I'm happy to go with the majority here.
IMHO, no need to spend more cycles on this.
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 39+ messages in thread
end of thread, other threads:[~2026-06-26 22:18 UTC | newest]
Thread overview: 39+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-04-02 13:51 [PATCH v2] Suppress length of Notice/Error in PQtrace regress mode Alvaro Herrera <[email protected]>
2021-04-02 13:51 [PATCH] Suppress length of Notice/Error in PQtrace regress mode Alvaro Herrera <[email protected]>
2023-06-25 11:48 [PATCH v1 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-06-26 08:05 [PATCH v2 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-07-26 10:49 [PATCH v3 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-08-09 07:56 [PATCH v4 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-09-02 06:32 [PATCH v5 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-09-12 05:22 [PATCH v6 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-09-22 04:53 [PATCH v7 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-09-25 05:01 [PATCH v8 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-10-04 05:51 [PATCH v9 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-10-22 02:22 [PATCH v10 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-11-08 06:57 [PATCH v11 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2023-12-04 11:23 [PATCH v12 3/7] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-01-22 09:45 [PATCH v13 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-02-28 13:59 [PATCH v14 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-03-28 10:30 [PATCH v15 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-04-12 06:49 [PATCH v16 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-04-28 11:00 [PATCH v17 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-05-11 07:11 [PATCH v18 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-05-14 23:26 [PATCH v19 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-05-24 02:26 [PATCH v20 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-08-26 04:32 [PATCH v21 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2024-09-19 04:48 [PATCH v22 4/8] Row pattern recognition patch (planner). Tatsuo Ishii <[email protected]>
2026-02-18 07:16 Re: enhance wraparound warnings Shinya Kato <[email protected]>
2026-03-03 20:31 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-06 22:15 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-03-09 12:08 ` Re: enhance wraparound warnings wenhui qiu <[email protected]>
2026-03-20 19:16 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-19 18:13 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-19 18:43 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-20 11:54 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-24 04:47 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-24 12:53 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-25 17:19 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
2026-06-26 00:51 ` Re: enhance wraparound warnings Fujii Masao <[email protected]>
2026-06-26 01:55 ` Re: enhance wraparound warnings Kyotaro Horiguchi <[email protected]>
2026-06-26 18:06 ` Re: enhance wraparound warnings Nathan Bossart <[email protected]>
2026-06-26 22:18 ` Re: enhance wraparound warnings Bharath Rupireddy <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox