On 4/8/21 8:13 AM, Tom Lane wrote:
I wrote:
Peter Eisentraut <peter.eisentr...@enterprisedb.com> writes:
Can we move forward with this?

We could just push the change and see what happens.  But I was thinking
more in terms of doing that early in the v15 cycle.  I remain skeptical
that we need a near-term fix.

To make sure we don't forget, I added an entry to the next CF for this.
Thanks for your efforts.

I tried to dive deeper: replace ROWID_VAR with -4 and explicitly change types of varnos in the description of functions that can only work with special varnos. Use cases of OUTER_VAR looks simple (i guess). Use cases of INNER_VAR is more complex because of the map_variable_attnos(). It is needed to analyze how negative value of INNER_VAR can affect on this function.

INDEX_VAR causes potential problem:
in ExecInitForeignScan() and ExecInitForeignScan() we do
tlistvarno = INDEX_VAR;

here tlistvarno has non-negative type.


ROWID_VAR caused two problems in the check-world tests:
set_pathtarget_cost_width():
if (var->varno < root->simple_rel_array_size)
{
        RelOptInfo *rel = root->simple_rel_array[var->varno];
...

and

replace_nestloop_params_mutator():
if (!bms_is_member(var->varno, root->curOuterRels))

I skipped this problems to see other weak points, but check-world couldn't find another.

--
regards,
Andrey Lepikhov
Postgres Professional
>From 6ba9441cc43a2ccf868ca271494bf5b9950692e6 Mon Sep 17 00:00:00 2001
From: Andrey Lepikhov <a.lepik...@postgrespro.ru>
Date: Thu, 8 Apr 2021 08:43:04 +0500
Subject: [PATCH] Remove 64k rangetable limit.

---
 src/backend/nodes/bitmapset.c           |  1 +
 src/backend/nodes/outfuncs.c            |  2 +-
 src/backend/nodes/readfuncs.c           |  2 +-
 src/backend/optimizer/path/costsize.c   |  3 ++-
 src/backend/optimizer/plan/createplan.c |  3 ++-
 src/backend/optimizer/plan/setrefs.c    | 30 +++++++++----------------
 src/include/nodes/primnodes.h           | 12 +++++-----
 7 files changed, 23 insertions(+), 30 deletions(-)

diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 649478b0d4..c0d50c85da 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -23,6 +23,7 @@
 #include "common/hashfn.h"
 #include "nodes/bitmapset.h"
 #include "nodes/pg_list.h"
+#include "nodes/primnodes.h"
 #include "port/pg_bitutils.h"
 
 
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4a8dc2d86d..4c3de615d1 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1115,7 +1115,7 @@ _outVar(StringInfo str, const Var *node)
 {
 	WRITE_NODE_TYPE("VAR");
 
-	WRITE_UINT_FIELD(varno);
+	WRITE_INT_FIELD(varno);
 	WRITE_INT_FIELD(varattno);
 	WRITE_OID_FIELD(vartype);
 	WRITE_INT_FIELD(vartypmod);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 9924727851..d084eee6ef 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -577,7 +577,7 @@ _readVar(void)
 {
 	READ_LOCALS(Var);
 
-	READ_UINT_FIELD(varno);
+	READ_INT_FIELD(varno);
 	READ_INT_FIELD(varattno);
 	READ_OID_FIELD(vartype);
 	READ_INT_FIELD(vartypmod);
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 05686d0194..ac72bddfae 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -5934,7 +5934,8 @@ set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
 			Assert(var->varlevelsup == 0);
 
 			/* Try to get data from RelOptInfo cache */
-			if (var->varno < root->simple_rel_array_size)
+			if (!IS_SPECIAL_VARNO(var->varno) &&
+				var->varno < root->simple_rel_array_size)
 			{
 				RelOptInfo *rel = root->simple_rel_array[var->varno];
 
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 22f10fa339..defd179bca 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -4809,7 +4809,8 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
 		/* Upper-level Vars should be long gone at this point */
 		Assert(var->varlevelsup == 0);
 		/* If not to be replaced, we can just return the Var unmodified */
-		if (!bms_is_member(var->varno, root->curOuterRels))
+		if (IS_SPECIAL_VARNO(var->varno) ||
+			!bms_is_member(var->varno, root->curOuterRels))
 			return node;
 		/* Replace the Var with a nestloop Param */
 		return (Node *) replace_nestloop_param_var(root, var);
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 70c0fa07e6..6009eabaf2 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -66,7 +66,7 @@ typedef struct
 {
 	PlannerInfo *root;
 	indexed_tlist *subplan_itlist;
-	Index		newvarno;
+	int			refvarno;
 	int			rtoffset;
 	double		num_exec;
 } fix_upper_expr_context;
@@ -147,7 +147,7 @@ static Var *search_indexed_tlist_for_var(Var *var,
 										 int rtoffset);
 static Var *search_indexed_tlist_for_non_var(Expr *node,
 											 indexed_tlist *itlist,
-											 Index newvarno);
+											 int refvarno);
 static Var *search_indexed_tlist_for_sortgroupref(Expr *node,
 												  Index sortgroupref,
 												  indexed_tlist *itlist,
@@ -163,7 +163,7 @@ static Node *fix_join_expr_mutator(Node *node,
 static Node *fix_upper_expr(PlannerInfo *root,
 							Node *node,
 							indexed_tlist *subplan_itlist,
-							Index newvarno,
+							int refvarno,
 							int rtoffset, double num_exec);
 static Node *fix_upper_expr_mutator(Node *node,
 									fix_upper_expr_context *context);
@@ -468,16 +468,6 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
 
 	glob->finalrtable = lappend(glob->finalrtable, newrte);
 
-	/*
-	 * Check for RT index overflow; it's very unlikely, but if it did happen,
-	 * the executor would get confused by varnos that match the special varno
-	 * values.
-	 */
-	if (IS_SPECIAL_VARNO(list_length(glob->finalrtable)))
-		ereport(ERROR,
-				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
-				 errmsg("too many range table entries")));
-
 	/*
 	 * If it's a plain relation RTE, add the table to relationOids.
 	 *
@@ -2503,7 +2493,7 @@ search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
  */
 static Var *
 search_indexed_tlist_for_non_var(Expr *node,
-								 indexed_tlist *itlist, Index newvarno)
+								 indexed_tlist *itlist, int refvarno)
 {
 	TargetEntry *tle;
 
@@ -2523,7 +2513,7 @@ search_indexed_tlist_for_non_var(Expr *node,
 		/* Found a matching subplan output expression */
 		Var		   *newvar;
 
-		newvar = makeVarFromTargetEntry(newvarno, tle);
+		newvar = makeVarFromTargetEntry(refvarno, tle);
 		newvar->varnosyn = 0;	/* wasn't ever a plain Var */
 		newvar->varattnosyn = 0;
 		return newvar;
@@ -2763,7 +2753,7 @@ static Node *
 fix_upper_expr(PlannerInfo *root,
 			   Node *node,
 			   indexed_tlist *subplan_itlist,
-			   Index newvarno,
+			   int refvarno,
 			   int rtoffset,
 			   double num_exec)
 {
@@ -2771,7 +2761,7 @@ fix_upper_expr(PlannerInfo *root,
 
 	context.root = root;
 	context.subplan_itlist = subplan_itlist;
-	context.newvarno = newvarno;
+	context.refvarno = refvarno;
 	context.rtoffset = rtoffset;
 	context.num_exec = num_exec;
 	return fix_upper_expr_mutator(node, &context);
@@ -2790,7 +2780,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
 
 		newvar = search_indexed_tlist_for_var(var,
 											  context->subplan_itlist,
-											  context->newvarno,
+											  context->refvarno,
 											  context->rtoffset);
 		if (!newvar)
 			elog(ERROR, "variable not found in subplan target list");
@@ -2805,7 +2795,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
 		{
 			newvar = search_indexed_tlist_for_non_var((Expr *) phv,
 													  context->subplan_itlist,
-													  context->newvarno);
+													  context->refvarno);
 			if (newvar)
 				return (Node *) newvar;
 		}
@@ -2817,7 +2807,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
 	{
 		newvar = search_indexed_tlist_for_non_var((Expr *) node,
 												  context->subplan_itlist,
-												  context->newvarno);
+												  context->refvarno);
 		if (newvar)
 			return (Node *) newvar;
 	}
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index f2ac4e51f1..34effe0f44 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -172,12 +172,12 @@ typedef struct Expr
  * in the planner and doesn't correspond to any simple relation column may
  * have varnosyn = varattnosyn = 0.
  */
-#define    INNER_VAR		65000	/* reference to inner subplan */
-#define    OUTER_VAR		65001	/* reference to outer subplan */
-#define    INDEX_VAR		65002	/* reference to index column */
-#define    ROWID_VAR		65003	/* row identity column during planning */
+#define    INNER_VAR		(-1)	/* reference to inner subplan */
+#define    OUTER_VAR		(-2)	/* reference to outer subplan */
+#define    INDEX_VAR		(-3)	/* reference to index column */
+#define    ROWID_VAR		(-4)	/* row identity column during planning */
 
-#define IS_SPECIAL_VARNO(varno)		((varno) >= INNER_VAR)
+#define IS_SPECIAL_VARNO(varno)		((varno) < 0)
 
 /* Symbols for the indexes of the special RTE entries in rules */
 #define    PRS2_OLD_VARNO			1
@@ -186,7 +186,7 @@ typedef struct Expr
 typedef struct Var
 {
 	Expr		xpr;
-	Index		varno;			/* index of this var's relation in the range
+	int			varno;			/* index of this var's relation in the range
 								 * table, or INNER_VAR/OUTER_VAR/INDEX_VAR */
 	AttrNumber	varattno;		/* attribute number of this var, or zero for
 								 * all attrs ("whole-row Var") */
-- 
2.25.1

Reply via email to