On Mon, 19 Oct 2020 at 12:10, Tom Lane <t...@sss.pgh.pa.us> wrote: > > David Rowley <dgrowle...@gmail.com> writes: > > For the backbranches, I think I go with something more minimal in the > > form of adding: > > TBH, I see no need to do anything in the back branches. This is not > an issue for production usage.
I understand the Assert failure is pretty harmless, so non-assert builds shouldn't suffer too greatly. I just assumed that any large stakeholders invested in upgrading to a newer version of PostgreSQL may like to run various tests with their application against an assert enabled version of PostgreSQL perhaps to gain some confidence in the upgrade. A failing assert is unlikely to inspire additional confidence. I'm not set on backpatching, but that's just my thoughts. FWIW, the patch I'd thought of is attached. David
From a309f1f0dc0329e16e328d6c3766c4014a64319b Mon Sep 17 00:00:00 2001 From: "dgrow...@gmail.com" <dgrow...@gmail.com> Date: Mon, 19 Oct 2020 11:49:51 +1300 Subject: [PATCH] Fix Assert failure in join costing code In the planner, it was possible, given an extreme enough case containing a large number of joins for the number of estimated rows to become infinite. This was a problem in initial_cost_mergejoin() where the row estimate could be multiplied by 0 which resulted in NaN. This could cause the Asserts which verified the skip rows was <= rows to fail due to the fact that NaN <= Inf is false. To fix this, modify the join costing functions to look for isinf() row estimates and explicitly set those to DBL_MAX. It seems the various places which perform calculations on these values only multiply by a selectivity estimate, which should be between 0.0 and 1.0, so we should never end up with infinity again after the multiplication takes place. In the reported case, only initial_cost_mergejoin() suffered from the failing Assert(). However, both final_cost_nestloop() and final_cost_mergejoin() seem to make similar assumptions about the row estimates not being infinite, so change those too. This particular problem was fixed in master in a90c950fc, however, that fix seemed a little too generic to go backpatching, so this is the minimal fix for the same problem. Reported-by: Onder Kalaci Discussion: https://postgr.es/m/dm6pr21mb1211ff360183bca901b27f04d8...@dm6pr21mb1211.namprd21.prod.outlook.com --- src/backend/optimizer/path/costsize.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index f39e6a9f80..f1eb9194ba 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -71,6 +71,7 @@ #include "postgres.h" +#include <float.h> #include <math.h> #include "access/amapi.h" @@ -2737,11 +2738,18 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path, QualCost restrict_qual_cost; double ntuples; - /* Protect some assumptions below that rowcounts aren't zero or NaN */ + /* + * Protect some assumptions below that rowcounts aren't zero, NaN or + * infinite. + */ if (outer_path_rows <= 0 || isnan(outer_path_rows)) outer_path_rows = 1; + else if (isinf(outer_path_rows)) + outer_path_rows = DBL_MAX; if (inner_path_rows <= 0 || isnan(inner_path_rows)) inner_path_rows = 1; + else if (isinf(inner_path_rows)) + inner_path_rows = DBL_MAX; /* Mark the path with the correct row estimate */ if (path->path.param_info) @@ -2952,11 +2960,18 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, innerendsel; Path sort_path; /* dummy for result of cost_sort */ - /* Protect some assumptions below that rowcounts aren't zero or NaN */ + /* + * Protect some assumptions below that rowcounts aren't zero, NaN or + * infinite. + */ if (outer_path_rows <= 0 || isnan(outer_path_rows)) outer_path_rows = 1; + else if (isinf(outer_path_rows)) + outer_path_rows = DBL_MAX; if (inner_path_rows <= 0 || isnan(inner_path_rows)) inner_path_rows = 1; + else if (isinf(inner_path_rows)) + inner_path_rows = DBL_MAX; /* * A merge join will stop as soon as it exhausts either input stream @@ -3185,9 +3200,14 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path, rescannedtuples; double rescanratio; - /* Protect some assumptions below that rowcounts aren't zero or NaN */ + /* + * Protect some assumptions below that rowcounts aren't zero, NaN or + * infinite. + */ if (inner_path_rows <= 0 || isnan(inner_path_rows)) inner_path_rows = 1; + else if (isinf(inner_path_rows)) + inner_path_rows = DBL_MAX; /* Mark the path with the correct row estimate */ if (path->jpath.path.param_info) -- 2.21.0.windows.1