From 0ade8f4e9a0741fa4f1a6998abf2488c5b846aa7 Mon Sep 17 00:00:00 2001 From: Jian Guo Date: Mon, 21 Aug 2023 16:07:41 +0800 Subject: [PATCH] Examine simple variable for Var in CTE. Signed-off-by: Jian Guo --- src/backend/utils/adt/selfuncs.c | 37 +++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index c4fcd0076e..bcf0fb4e16 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -5598,13 +5598,43 @@ examine_simple_variable(PlannerInfo *root, Var *var, examine_simple_variable(rel->subroot, var, vardata); } } + else if (rte->rtekind == RTE_CTE && !rte->inh) + { + /* + * Punt if it's a whole-row var rather than a plain column reference. + */ + if (var->varattno == InvalidAttrNumber) + return; + /* + * OK, fetch RelOptInfo for subquery. + */ + RelOptInfo *rel = find_base_rel(root, var->varno); + /* Can only handle a simple Var of subquery's query level */ + if (var && IsA(var, Var) && + var->varlevelsup == 0) + { + /* + * OK, recurse into the subquery. Note that the original setting + * of vardata->isunique (which will surely be false) is left + * unchanged in this situation. That's what we want, since even + * if the underlying column is unique, the subquery may have + * joined to other tables in a way that creates duplicates. + */ + Index varnoSaved = var->varno; + /* Mock a fake index for CTE */ + var->varno = 1; + if (rel->subroot) + examine_simple_variable(rel->subroot, var, vardata); + var->varno = varnoSaved; + } + } else { /* - * Otherwise, the Var comes from a FUNCTION, VALUES, or CTE RTE. (We + * Otherwise, the Var comes from a FUNCTION, VALUES. (We * won't see RTE_JOIN here because join alias Vars have already been * flattened.) There's not much we can do with function outputs, but - * maybe someday try to be smarter about VALUES and/or CTEs. + * maybe someday try to be smarter about VALUES. */ } } @@ -5866,7 +5896,8 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata, * data. Proceed only if the MCVs represent the whole table (to within * roundoff error). */ - if (get_attstatsslot(&sslot, vardata->statsTuple, + bool has_mcv = (!vardata->rel || vardata->rel->rtekind != RTE_CTE); + if (has_mcv && get_attstatsslot(&sslot, vardata->statsTuple, STATISTIC_KIND_MCV, InvalidOid, have_data ? ATTSTATSSLOT_VALUES : (ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS))) -- 2.41.0