diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml index 587517da1d1..b0ac8e52b6a 100644 --- a/doc/src/sgml/gist.sgml +++ b/doc/src/sgml/gist.sgml @@ -147,6 +147,8 @@ Returns a value indicating the cost of inserting the new entry into a particular branch of the tree. items will be inserted down the path of least penalty in the tree. + Values returned by penalty should be non-negative. + If a negative value is returned, it will be treated as zero. diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index d88f5ea0f81..5bd6a9893b0 100644 --- a/src/backend/access/gist/gistutil.c +++ b/src/backend/access/gist/gistutil.c @@ -13,6 +13,8 @@ */ #include "postgres.h" +#include + #include "access/gist_private.h" #include "access/heapam.h" #include "access/reloptions.h" @@ -530,16 +532,22 @@ gistpenalty(GISTSTATE *giststate, int attno, { float penalty = 0.0; - if (giststate->penaltyFn[attno].fn_strict == FALSE || (isNullOrig == FALSE && isNullAdd == FALSE)) + if (giststate->penaltyFn[attno].fn_strict == FALSE || + (isNullOrig == FALSE && isNullAdd == FALSE)) + { FunctionCall3(&giststate->penaltyFn[attno], PointerGetDatum(orig), PointerGetDatum(add), PointerGetDatum(&penalty)); + /* disallow negative or NaN penalty */ + if (isnan(penalty) || penalty < 0.0) + penalty = 0.0; + } else if (isNullOrig && isNullAdd) penalty = 0.0; else - penalty = 1e10; /* try to prevent to mix null and non-null - * value */ + penalty = 1e10; /* try to prevent mixing null and non-null + * values */ return penalty; }