Skip to content

Commit 3b4a9db

Browse files
committed
Avoid some zero-divide hazards in the planner.
Although I think on all modern machines floating division by zero results in Infinity not SIGFPE, we still don't want infinities running around in the planner's costing estimates; too much risk of that leading to insane behavior. grouping_planner() failed to consider the possibility that final_rel might be known dummy and hence have zero rowcount. (I wonder if it would be better to set a rows estimate of 1 for dummy relations? But at least in the back branches, changing this convention seems like a bad idea, so I'll leave that for another day.) Make certain that get_variable_numdistinct() produces a nonzero result. The case that can be shown to be broken is with stadistinct < 0.0 and small ntuples; we did not prevent the result from rounding to zero. For good luck I applied clamp_row_est() to all the nonconstant return values. In ExecChooseHashTableSize(), Assert that we compute positive nbuckets and nbatch. I know of no reason to think this isn't the case, but it seems like a good safety check. Per reports from Piotr Stefaniak. Back-patch to all active branches.
1 parent 76cf5f1 commit 3b4a9db

File tree

3 files changed

+12
-7
lines changed

3 files changed

+12
-7
lines changed

src/backend/executor/nodeHash.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,9 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
509509
i++;
510510
nbuckets = (1 << i);
511511

512+
Assert(nbuckets > 0);
513+
Assert(nbatch > 0);
514+
512515
*numbuckets = nbuckets;
513516
*numbatches = nbatch;
514517
}

src/backend/optimizer/plan/planner.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,9 +1365,11 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
13651365
standard_qp_callback, &qp_extra);
13661366

13671367
/*
1368-
* Extract rowcount and width estimates for use below.
1368+
* Extract rowcount and width estimates for use below. If final_rel
1369+
* has been proven dummy, its rows estimate will be zero; clamp it to
1370+
* one to avoid zero-divide in subsequent calculations.
13691371
*/
1370-
path_rows = final_rel->rows;
1372+
path_rows = clamp_row_est(final_rel->rows);
13711373
path_width = final_rel->width;
13721374

13731375
/*

src/backend/utils/adt/selfuncs.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4622,8 +4622,8 @@ examine_simple_variable(PlannerInfo *root, Var *var,
46224622
* *isdefault: set to TRUE if the result is a default rather than based on
46234623
* anything meaningful.
46244624
*
4625-
* NB: be careful to produce an integral result, since callers may compare
4626-
* the result to exact integer counts.
4625+
* NB: be careful to produce a positive integral result, since callers may
4626+
* compare the result to exact integer counts, or might divide by it.
46274627
*/
46284628
double
46294629
get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
@@ -4699,7 +4699,7 @@ get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
46994699
* If we had an absolute estimate, use that.
47004700
*/
47014701
if (stadistinct > 0.0)
4702-
return stadistinct;
4702+
return clamp_row_est(stadistinct);
47034703

47044704
/*
47054705
* Otherwise we need to get the relation size; punt if not available.
@@ -4720,15 +4720,15 @@ get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
47204720
* If we had a relative estimate, use that.
47214721
*/
47224722
if (stadistinct < 0.0)
4723-
return floor((-stadistinct * ntuples) + 0.5);
4723+
return clamp_row_est(-stadistinct * ntuples);
47244724

47254725
/*
47264726
* With no data, estimate ndistinct = ntuples if the table is small, else
47274727
* use default. We use DEFAULT_NUM_DISTINCT as the cutoff for "small" so
47284728
* that the behavior isn't discontinuous.
47294729
*/
47304730
if (ntuples < DEFAULT_NUM_DISTINCT)
4731-
return ntuples;
4731+
return clamp_row_est(ntuples);
47324732

47334733
*isdefault = true;
47344734
return DEFAULT_NUM_DISTINCT;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy