Remove arbitrary 64K-or-so limit on rangetable size.
authorTom Lane
Wed, 15 Sep 2021 18:11:21 +0000 (14:11 -0400)
committerTom Lane
Wed, 15 Sep 2021 18:11:21 +0000 (14:11 -0400)
Up to now the size of a query's rangetable has been limited by the
constants INNER_VAR et al, which mustn't be equal to any real
rangetable index.  65000 doubtless seemed like enough for anybody,
and it still is orders of magnitude larger than the number of joins
we can realistically handle.  However, we need a rangetable entry
for each child partition that is (or might be) processed by a query.
Queries with a few thousand partitions are getting more realistic,
so that the day when that limit becomes a problem is in sight,
even if it's not here yet.  Hence, let's raise the limit.

Rather than just increase the values of INNER_VAR et al, this patch
adopts the approach of making them small negative values, so that
rangetables could theoretically become as long as INT_MAX.

The bulk of the patch is concerned with changing Var.varno and some
related variables from "Index" (unsigned int) to plain "int".  This
is basically cosmetic, with little actual effect other than to help
debuggers print their values nicely.  As such, I've only bothered
with changing places that could actually see INNER_VAR et al, which
the parser and most of the planner don't.  We do have to be careful
in places that are performing less/greater comparisons on varnos,
but there are very few such places, other than the IS_SPECIAL_VARNO
macro itself.

A notable side effect of this patch is that while it used to be
possible to add INNER_VAR et al to a Bitmapset, that will now
draw an error.  I don't see any likelihood that it wouldn't be a
bug to include these fake varnos in a bitmapset of real varnos,
so I think this is all to the good.

Although this touches outfuncs/readfuncs, I don't think a catversion
bump is required, since stored rules would never contain Vars
with these fake varnos.

Andrey Lepikhov and Tom Lane, after a suggestion by Peter Eisentraut

Discussion: https://postgr.es/m/43c7f2f5-1e27-27aa-8c65-c91859d15190@postgrespro.ru

15 files changed:
src/backend/executor/execScan.c
src/backend/executor/execUtils.c
src/backend/executor/nodeCustom.c
src/backend/executor/nodeForeignscan.c
src/backend/nodes/makefuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/prep/prepjointree.c
src/backend/utils/adt/ruleutils.c
src/include/executor/executor.h
src/include/nodes/makefuncs.h
src/include/nodes/primnodes.h

index 69ab34573ec595b3d0a31ff7d3425824645eab3b..9f1d8b6d1e9e18e727bd31d37f4b3d36176ff1fb 100644 (file)
@@ -282,7 +282,7 @@ ExecAssignScanProjectionInfo(ScanState *node)
  *     As above, but caller can specify varno expected in Vars in the tlist.
  */
 void
-ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno)
+ExecAssignScanProjectionInfoWithVarno(ScanState *node, int varno)
 {
    TupleDesc   tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
 
index ad11392b99de1927f65712e307224e742e081ea8..4ab1302313f98181964debc8294c6d4ab7451fe0 100644 (file)
@@ -65,7 +65,7 @@
 #include "utils/typcache.h"
 
 
-static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);
+static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc);
 static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
 
 
@@ -553,7 +553,7 @@ ExecAssignProjectionInfo(PlanState *planstate,
  */
 void
 ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
-                                   Index varno)
+                                   int varno)
 {
    if (tlist_matches_tupdesc(planstate,
                              planstate->plan->targetlist,
@@ -579,7 +579,7 @@ ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
 }
 
 static bool
-tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
+tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
 {
    int         numattrs = tupdesc->natts;
    int         attrno;
index c82060e6d1a8718fab503999bcf8c0de810c1d4f..1dfa53c38194d34c12b7a173250a7966b86cb4a6 100644 (file)
@@ -31,7 +31,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
    CustomScanState *css;
    Relation    scan_rel = NULL;
    Index       scanrelid = cscan->scan.scanrelid;
-   Index       tlistvarno;
+   int         tlistvarno;
 
    /*
     * Allocate the CustomScanState object.  We let the custom scan provider
index 1abd906b16952eec6374ec84332396acddfe781a..0a549afcc0982e5b46428e4c50f6b3edc186511f 100644 (file)
@@ -138,7 +138,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
    ForeignScanState *scanstate;
    Relation    currentRelation = NULL;
    Index       scanrelid = node->scan.scanrelid;
-   Index       tlistvarno;
+   int         tlistvarno;
    FdwRoutine *fdwroutine;
 
    /* check for unsupported flags */
index 01c110cd2fc17a52228b77f41c2b6d0dca707e5d..7d1a01d1ed6d27279dba1ea3935dbaa8fb94e618 100644 (file)
@@ -63,7 +63,7 @@ makeSimpleA_Expr(A_Expr_Kind kind, char *name,
  *   creates a Var node
  */
 Var *
-makeVar(Index varno,
+makeVar(int varno,
        AttrNumber varattno,
        Oid vartype,
        int32 vartypmod,
@@ -85,7 +85,7 @@ makeVar(Index varno,
     * them, but just initialize them to the given varno/varattno.  This
     * reduces code clutter and chance of error for most callers.
     */
-   var->varnosyn = varno;
+   var->varnosyn = (Index) varno;
    var->varattnosyn = varattno;
 
    /* Likewise, we just set location to "unknown" here */
@@ -100,7 +100,7 @@ makeVar(Index varno,
  *     TargetEntry
  */
 Var *
-makeVarFromTargetEntry(Index varno,
+makeVarFromTargetEntry(int varno,
                       TargetEntry *tle)
 {
    return makeVar(varno,
@@ -131,7 +131,7 @@ makeVarFromTargetEntry(Index varno,
  */
 Var *
 makeWholeRowVar(RangeTblEntry *rte,
-               Index varno,
+               int varno,
                Index varlevelsup,
                bool allowScalar)
 {
index 6b290737a6d6d506025b3465fcdf28e20159b5e7..2e5ed77e1897916d207b3bc25831ae668aafac46 100644 (file)
@@ -1123,7 +1123,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);
index 01aee85bd4592ce396f0545c04182727ce23682f..abf08b7a2f3b19159511e1e9a8a514f1c57970f6 100644 (file)
@@ -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);
index 1fd53b40bb082db208c91c08ec27367ec6ad0b58..1e4d404f024456f3c3f9bcc8039335bc9474fb97 100644 (file)
@@ -5961,7 +5961,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];
 
index a5f6d678ccda22ebca3d2a3c59169005142094e6..3dc0176a5169a5fb40b457971f17b42a3d980e63 100644 (file)
@@ -4805,7 +4805,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);
index 3d23a2e5ac71423d18d5c165a31397513ce9c719..6ccec759bd2ad4a844c70d6cce727a1a72f334a5 100644 (file)
@@ -31,7 +31,7 @@
 
 typedef struct
 {
-   Index       varno;          /* RT index of Var */
+   int         varno;          /* RT index of Var */
    AttrNumber  varattno;       /* attr number of Var */
    AttrNumber  resno;          /* TLE position of Var */
 } tlist_vinfo;
@@ -66,7 +66,7 @@ typedef struct
 {
    PlannerInfo *root;
    indexed_tlist *subplan_itlist;
-   Index       newvarno;
+   int         newvarno;
    int         rtoffset;
    double      num_exec;
 } fix_upper_expr_context;
@@ -143,15 +143,15 @@ static void set_dummy_tlist_references(Plan *plan, int rtoffset);
 static indexed_tlist *build_tlist_index(List *tlist);
 static Var *search_indexed_tlist_for_var(Var *var,
                                         indexed_tlist *itlist,
-                                        Index newvarno,
+                                        int newvarno,
                                         int rtoffset);
 static Var *search_indexed_tlist_for_non_var(Expr *node,
                                             indexed_tlist *itlist,
-                                            Index newvarno);
+                                            int newvarno);
 static Var *search_indexed_tlist_for_sortgroupref(Expr *node,
                                                  Index sortgroupref,
                                                  indexed_tlist *itlist,
-                                                 Index newvarno);
+                                                 int newvarno);
 static List *fix_join_expr(PlannerInfo *root,
                           List *clauses,
                           indexed_tlist *outer_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 newvarno,
                            int rtoffset, double num_exec);
 static Node *fix_upper_expr_mutator(Node *node,
                                    fix_upper_expr_context *context);
@@ -505,16 +505,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.
     *
@@ -1947,10 +1937,8 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
    {
        CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
 
-       Assert(cexpr->cvarno != INNER_VAR);
-       Assert(cexpr->cvarno != OUTER_VAR);
-       if (!IS_SPECIAL_VARNO(cexpr->cvarno))
-           cexpr->cvarno += context->rtoffset;
+       Assert(!IS_SPECIAL_VARNO(cexpr->cvarno));
+       cexpr->cvarno += context->rtoffset;
        return (Node *) cexpr;
    }
    if (IsA(node, PlaceHolderVar))
@@ -2447,7 +2435,7 @@ build_tlist_index(List *tlist)
  * (so nothing other than Vars and PlaceHolderVars can be matched).
  */
 static indexed_tlist *
-build_tlist_index_other_vars(List *tlist, Index ignore_rel)
+build_tlist_index_other_vars(List *tlist, int ignore_rel)
 {
    indexed_tlist *itlist;
    tlist_vinfo *vinfo;
@@ -2499,9 +2487,9 @@ build_tlist_index_other_vars(List *tlist, Index ignore_rel)
  */
 static Var *
 search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
-                            Index newvarno, int rtoffset)
+                            int newvarno, int rtoffset)
 {
-   Index       varno = var->varno;
+   int         varno = var->varno;
    AttrNumber  varattno = var->varattno;
    tlist_vinfo *vinfo;
    int         i;
@@ -2539,7 +2527,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 newvarno)
 {
    TargetEntry *tle;
 
@@ -2581,7 +2569,7 @@ static Var *
 search_indexed_tlist_for_sortgroupref(Expr *node,
                                      Index sortgroupref,
                                      indexed_tlist *itlist,
-                                     Index newvarno)
+                                     int newvarno)
 {
    ListCell   *lc;
 
@@ -2799,7 +2787,7 @@ static Node *
 fix_upper_expr(PlannerInfo *root,
               Node *node,
               indexed_tlist *subplan_itlist,
-              Index newvarno,
+              int newvarno,
               int rtoffset,
               double num_exec)
 {
index 224c5153b1586c32aaf3f61244851d94767bcb6f..387a35e11228cc41a2f3f50d5356e25775bda726 100644 (file)
@@ -80,7 +80,7 @@ static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
 static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
                                       int parentRTindex, Query *setOpQuery,
                                       int childRToffset);
-static void make_setop_translation_list(Query *query, Index newvarno,
+static void make_setop_translation_list(Query *query, int newvarno,
                                        AppendRelInfo *appinfo);
 static bool is_simple_subquery(PlannerInfo *root, Query *subquery,
                               RangeTblEntry *rte,
@@ -1372,7 +1372,7 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
  *   Also create the rather trivial reverse-translation array.
  */
 static void
-make_setop_translation_list(Query *query, Index newvarno,
+make_setop_translation_list(Query *query, int newvarno,
                            AppendRelInfo *appinfo)
 {
    List       *vars = NIL;
index ccd2835c2223c151f979e2fe701824a5256ca0e5..b932a83827f7185cf248145d5ad3108c331b62f3 100644 (file)
@@ -6949,7 +6949,7 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
    AttrNumber  attnum;
    int         netlevelsup;
    deparse_namespace *dpns;
-   Index       varno;
+   int         varno;
    AttrNumber  varattno;
    deparse_columns *colinfo;
    char       *refname;
@@ -6995,7 +6995,7 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
         */
        if (context->appendparents && dpns->appendrels)
        {
-           Index       pvarno = varno;
+           int         pvarno = varno;
            AttrNumber  pvarattno = varattno;
            AppendRelInfo *appinfo = dpns->appendrels[pvarno];
            bool        found = false;
@@ -7305,7 +7305,7 @@ get_name_for_var_field(Var *var, int fieldno,
    AttrNumber  attnum;
    int         netlevelsup;
    deparse_namespace *dpns;
-   Index       varno;
+   int         varno;
    AttrNumber  varattno;
    TupleDesc   tupleDesc;
    Node       *expr;
index 3dc03c913e3f905767ed6dc15abbc12dcf8451cb..cd57a704adc3bbafcf06728dd5a0187641aed3e0 100644 (file)
@@ -459,7 +459,7 @@ typedef bool (*ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot);
 extern TupleTableSlot *ExecScan(ScanState *node, ExecScanAccessMtd accessMtd,
                                ExecScanRecheckMtd recheckMtd);
 extern void ExecAssignScanProjectionInfo(ScanState *node);
-extern void ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno);
+extern void ExecAssignScanProjectionInfoWithVarno(ScanState *node, int varno);
 extern void ExecScanReScan(ScanState *node);
 
 /*
@@ -552,7 +552,7 @@ extern const TupleTableSlotOps *ExecGetResultSlotOps(PlanState *planstate,
 extern void ExecAssignProjectionInfo(PlanState *planstate,
                                     TupleDesc inputDesc);
 extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
-                                               TupleDesc inputDesc, Index varno);
+                                               TupleDesc inputDesc, int varno);
 extern void ExecFreeExprContext(PlanState *planstate);
 extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
 extern void ExecCreateScanSlotFromOuterPlan(EState *estate,
index 48a7ebfe450ecb81570ab3e077dcc84f82421331..eea87f847d87a02e2cdb3095ea89e03e1083cbf1 100644 (file)
@@ -24,18 +24,18 @@ extern A_Expr *makeA_Expr(A_Expr_Kind kind, List *name,
 extern A_Expr *makeSimpleA_Expr(A_Expr_Kind kind, char *name,
                                Node *lexpr, Node *rexpr, int location);
 
-extern Var *makeVar(Index varno,
+extern Var *makeVar(int varno,
                    AttrNumber varattno,
                    Oid vartype,
                    int32 vartypmod,
                    Oid varcollid,
                    Index varlevelsup);
 
-extern Var *makeVarFromTargetEntry(Index varno,
+extern Var *makeVarFromTargetEntry(int varno,
                                   TargetEntry *tle);
 
 extern Var *makeWholeRowVar(RangeTblEntry *rte,
-                           Index varno,
+                           int varno,
                            Index varlevelsup,
                            bool allowScalar);
 
index 7b125904b4d9653feaabf6587cbb63a46942e6b6..433437643e0ef34fa6152a47fa3fe29b4087389c 100644 (file)
@@ -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)        ((int) (varno) < 0)
 
 /* Symbols for the indexes of the special RTE entries in rules */
 #define    PRS2_OLD_VARNO          1
@@ -186,8 +186,8 @@ typedef struct Expr
 typedef struct Var
 {
    Expr        xpr;
-   Index       varno;          /* index of this var's relation in the range
-                                * table, or INNER_VAR/OUTER_VAR/INDEX_VAR */
+   int         varno;          /* index of this var's relation in the range
+                                * table, or INNER_VAR/OUTER_VAR/etc */
    AttrNumber  varattno;       /* attribute number of this var, or zero for
                                 * all attrs ("whole-row Var") */
    Oid         vartype;        /* pg_type OID for the type of this var */
@@ -1351,6 +1351,7 @@ typedef struct SetToDefault
  * of the target relation being constrained; this aids placing the expression
  * correctly during planning.  We can assume however that its "levelsup" is
  * always zero, due to the syntactic constraints on where it can appear.
+ * Also, cvarno will always be a true RT index, never INNER_VAR etc.
  *
  * The referenced cursor can be represented either as a hardwired string
  * or as a reference to a run-time parameter of type REFCURSOR.  The latter