Skip to content

Commit 8693ebe

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 5515ec0 commit 8693ebe

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
@@ -542,6 +542,9 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
542542
nbatch <<= 1;
543543
}
544544

545+
Assert(nbuckets > 0);
546+
Assert(nbatch > 0);
547+
545548
*numbuckets = nbuckets;
546549
*numbatches = nbatch;
547550
}

src/backend/optimizer/plan/planner.c

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

15381538
/*
1539-
* Extract rowcount and width estimates for use below.
1539+
* Extract rowcount and width estimates for use below. If final_rel
1540+
* has been proven dummy, its rows estimate will be zero; clamp it to
1541+
* one to avoid zero-divide in subsequent calculations.
15401542
*/
1541-
path_rows = final_rel->rows;
1543+
path_rows = clamp_row_est(final_rel->rows);
15421544
path_width = final_rel->width;
15431545

15441546
/*

src/backend/utils/adt/selfuncs.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4632,8 +4632,8 @@ examine_simple_variable(PlannerInfo *root, Var *var,
46324632
* *isdefault: set to TRUE if the result is a default rather than based on
46334633
* anything meaningful.
46344634
*
4635-
* NB: be careful to produce an integral result, since callers may compare
4636-
* the result to exact integer counts.
4635+
* NB: be careful to produce a positive integral result, since callers may
4636+
* compare the result to exact integer counts, or might divide by it.
46374637
*/
46384638
double
46394639
get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
@@ -4709,7 +4709,7 @@ get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
47094709
* If we had an absolute estimate, use that.
47104710
*/
47114711
if (stadistinct > 0.0)
4712-
return stadistinct;
4712+
return clamp_row_est(stadistinct);
47134713

47144714
/*
47154715
* Otherwise we need to get the relation size; punt if not available.
@@ -4730,15 +4730,15 @@ get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
47304730
* If we had a relative estimate, use that.
47314731
*/
47324732
if (stadistinct < 0.0)
4733-
return floor((-stadistinct * ntuples) + 0.5);
4733+
return clamp_row_est(-stadistinct * ntuples);
47344734

47354735
/*
47364736
* With no data, estimate ndistinct = ntuples if the table is small, else
47374737
* use default. We use DEFAULT_NUM_DISTINCT as the cutoff for "small" so
47384738
* that the behavior isn't discontinuous.
47394739
*/
47404740
if (ntuples < DEFAULT_NUM_DISTINCT)
4741-
return ntuples;
4741+
return clamp_row_est(ntuples);
47424742

47434743
*isdefault = true;
47444744
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