From 2e0120ab571281ac69fdf20356ea5e0f2bc9a84d Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Wed, 20 Aug 2025 18:10:00 +0900 Subject: [PATCH v1] Fix const-simplification of expressions loaded from catalogs --- src/backend/optimizer/util/plancat.c | 58 +++++++++++++++++++--------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 6ce4efea118..c507d3ec8e6 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -77,7 +77,8 @@ static List *get_relation_constraints(PlannerInfo *root, bool include_partition); static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index, Relation heapRelation); -static List *get_relation_statistics(RelOptInfo *rel, Relation relation); +static List *get_relation_statistics(PlannerInfo *root, RelOptInfo *rel, + Relation relation); static void set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel, Relation relation); static PartitionScheme find_partition_scheme(PlannerInfo *root, @@ -435,6 +436,18 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (info->indpred && varno != 1) ChangeVarNodes((Node *) info->indpred, 1, varno, 0); + /* + * We need to run the index expressions and predicate through + * const-simplification again after fixing the Vars to have the + * correct varno, and with a valid "root". This ensures that + * NullTest quals for Vars can be properly reduced. + */ + info->indexprs = (List *) + eval_const_expressions(root, (Node *) info->indexprs); + info->indpred = (List *) + eval_const_expressions(root, (Node *) make_ands_explicit(info->indpred)); + info->indpred = make_ands_implicit((Expr *) info->indpred); + /* Build targetlist using the completed indexprs data */ info->indextlist = build_index_tlist(root, info, relation); @@ -508,7 +521,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, rel->indexlist = indexinfos; - rel->statlist = get_relation_statistics(rel, relation); + rel->statlist = get_relation_statistics(root, rel, relation); /* Grab foreign-table info using the relcache, while we have it */ if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE) @@ -1406,6 +1419,14 @@ get_relation_constraints(PlannerInfo *root, cexpr = stringToNode(constr->check[i].ccbin); + /* + * Fix Vars to have the desired varno. This must be done before + * const-simplification because eval_const_expressions reduces + * NullTest for Vars based on varno. + */ + if (varno != 1) + ChangeVarNodes(cexpr, 1, varno, 0); + /* * Run each expression through const-simplification and * canonicalization. This is not just an optimization, but is @@ -1420,10 +1441,6 @@ get_relation_constraints(PlannerInfo *root, cexpr = (Node *) canonicalize_qual((Expr *) cexpr, true); - /* Fix Vars to have the desired varno */ - if (varno != 1) - ChangeVarNodes(cexpr, 1, varno, 0); - /* * Finally, convert to implicit-AND format (that is, a List) and * append the resulting item(s) to our output list. @@ -1572,7 +1589,8 @@ get_relation_statistics_worker(List **stainfos, RelOptInfo *rel, * just the identifying metadata. Only stats actually built are considered. */ static List * -get_relation_statistics(RelOptInfo *rel, Relation relation) +get_relation_statistics(PlannerInfo *root, RelOptInfo *rel, + Relation relation) { Index varno = rel->relid; List *statoidlist; @@ -1604,8 +1622,8 @@ get_relation_statistics(RelOptInfo *rel, Relation relation) keys = bms_add_member(keys, staForm->stxkeys.values[i]); /* - * Preprocess expressions (if any). We read the expressions, run them - * through eval_const_expressions, and fix the varnos. + * Preprocess expressions (if any). We read the expressions, fix the + * varnos, and run them through eval_const_expressions. * * XXX We don't know yet if there are any data for this stats object, * with either stxdinherit value. But it's reasonable to assume there @@ -1628,6 +1646,18 @@ get_relation_statistics(RelOptInfo *rel, Relation relation) exprs = (List *) stringToNode(exprsString); pfree(exprsString); + /* + * Modify the copies we obtain from the relcache to have the + * correct varno for the parent relation, so that they match + * up correctly against qual clauses. + * + * This must be done before const-simplification because + * eval_const_expressions reduces NullTest for Vars based on + * varno. + */ + if (varno != 1) + ChangeVarNodes((Node *) exprs, 1, varno, 0); + /* * Run the expressions through eval_const_expressions. This is * not just an optimization, but is necessary, because the @@ -1636,18 +1666,10 @@ get_relation_statistics(RelOptInfo *rel, Relation relation) * We must not use canonicalize_qual, however, since these * aren't qual expressions. */ - exprs = (List *) eval_const_expressions(NULL, (Node *) exprs); + exprs = (List *) eval_const_expressions(root, (Node *) exprs); /* May as well fix opfuncids too */ fix_opfuncids((Node *) exprs); - - /* - * Modify the copies we obtain from the relcache to have the - * correct varno for the parent relation, so that they match - * up correctly against qual clauses. - */ - if (varno != 1) - ChangeVarNodes((Node *) exprs, 1, varno, 0); } } -- 2.43.0