postgres.git / summary / log / commit / refs

commit    dae9f16aa31a941f6b596dcb192dd3c29f4d302c
Author:   David Rowley <drowley@postgresql.org>
Date:     Tue Jun 18 22:21:52 2024 +0000

    Fix possible Assert failure in cost_memoize_rescan
    
    In cost_memoize_rescan(), when calculating the hit_ratio using the calls
    and ndistinct estimations, if the value that was set in
    MemoizePath.calls had not been processed through clamp_row_est(), then it
    was possible that it was set to some non-integer value which could result
    in ndistinct being 1 higher than calls due to estimate_num_groups()
    performing clamp_row_est() on its input_rows.  This could result in
    hit_ratio values slightly below 0.0, which would cause an Assert failure.
    
    The value of MemoizePath.calls comes from the final parameter in the
    create_memoize_path() function, of which we only have one true caller of.
    That caller passes outer_path->rows.  All the core code I looked at
    always seems to call clamp_row_est() on the Path.rows, so there might
    have been no issues with any core Paths causing troubles here.  The bug
    report was about a CustomPath with a non-clamped row estimated.
    
    The misbehavior as a result of this seems to be mostly limited to the
    Assert() failing.  Aside from that, it seems the Memoize costs would
    just come out slightly higher than they should have, which is likely
    fairly harmless.
    
    Reported-by: Kohei KaiGai <kaigai@heterodb.com>
    Discussion: https://postgr.es/m/CAOP8fzZnTU+N64UYJYogb1hN-5hFP+PwTb3m_cnGAD7EsQwrKw@mail.gmail.com
    Reviewed-by: Richard Guo
    Backpatch-through: 14, where Memoize was introduced


src/backend/optimizer/util/pathnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 7968db21740..33c40f375af 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -1609,7 +1609,7 @@ create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->param_exprs = param_exprs; pathnode->singlerow = singlerow; pathnode->binary_mode = binary_mode; - pathnode->calls = calls; + pathnode->calls = clamp_row_est(calls); /* * For now we set est_entries to 0. cost_memoize_rescan() does all the [parent: e4a55378f726]