diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml index f6e31092aa1..78171cfa3fd 100644 --- a/doc/src/sgml/gist.sgml +++ b/doc/src/sgml/gist.sgml @@ -378,6 +378,8 @@ my_decompress(PG_FUNCTION_ARGS) 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 e61b676628b..1aabcc527ac 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/reloptions.h" #include "storage/freespace.h" @@ -526,16 +528,21 @@ gistpenalty(GISTSTATE *giststate, int attno, if (giststate->penaltyFn[attno].fn_strict == FALSE || (isNullOrig == FALSE && isNullAdd == FALSE)) + { FunctionCall3Coll(&giststate->penaltyFn[attno], giststate->supportCollation[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; }