diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c new file mode 100644 index 3a45781..fc88c5c *** a/src/backend/access/gist/gistproc.c --- b/src/backend/access/gist/gistproc.c *************** typedef struct *** 272,277 **** --- 272,310 ---- } SplitInterval; /* + * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations + */ + static int + float8_cmp_internal(float8 a, float8 b) + { + /* + * We consider all NANs to be equal and larger than any non-NAN. This is + * somewhat arbitrary; the important thing is to have a consistent sort + * order. + */ + if (isnan(a)) + { + if (isnan(b)) + return 0; /* NAN = NAN */ + else + return 1; /* NAN > non-NAN */ + } + else if (isnan(b)) + { + return -1; /* non-NAN < NAN */ + } + else + { + if (a > b) + return 1; + else if (a < b) + return -1; + else + return 0; + } + } + + /* * Interval comparison function by lower bound of the interval; */ static int *************** interval_cmp_lower(const void *i1, const *** 280,291 **** double lower1 = ((const SplitInterval *) i1)->lower, lower2 = ((const SplitInterval *) i2)->lower; ! if (lower1 < lower2) ! return -1; ! else if (lower1 > lower2) ! return 1; ! else ! return 0; } /* --- 313,319 ---- double lower1 = ((const SplitInterval *) i1)->lower, lower2 = ((const SplitInterval *) i2)->lower; ! return float8_cmp_internal(lower1, lower2); } /* *************** interval_cmp_upper(const void *i1, const *** 297,308 **** double upper1 = ((const SplitInterval *) i1)->upper, upper2 = ((const SplitInterval *) i2)->upper; ! if (upper1 < upper2) ! return -1; ! else if (upper1 > upper2) ! return 1; ! else ! return 0; } /* --- 325,331 ---- double upper1 = ((const SplitInterval *) i1)->upper, upper2 = ((const SplitInterval *) i2)->upper; ! return float8_cmp_internal(upper1, upper2); } /* *************** g_box_consider_split(ConsiderSplitContex *** 371,377 **** else range = context->boundingBox.high.y - context->boundingBox.low.y; ! overlap = (leftUpper - rightLower) / range; /* If there is no previous selection, select this */ if (context->first) --- 394,403 ---- else range = context->boundingBox.high.y - context->boundingBox.low.y; ! if (isnan(leftUpper) && !isnan(rightLower)) ! overlap = - get_float8_infinity(); ! else ! overlap = (leftUpper - rightLower) / range; /* If there is no previous selection, select this */ if (context->first) *************** static double *** 432,445 **** box_penalty(BOX *original, BOX *new) { double union_width, ! union_height; union_width = Max(original->high.x, new->high.x) - Min(original->low.x, new->low.x); union_height = Max(original->high.y, new->high.y) - Min(original->low.y, new->low.y); ! return union_width * union_height - (original->high.x - original->low.x) * ! (original->high.y - original->low.y); } /* --- 458,479 ---- box_penalty(BOX *original, BOX *new) { double union_width, ! union_height, ! original_width, ! original_height; + original_width = original->high.x - original->low.x; + original_height = original->high.y - original->low.y; union_width = Max(original->high.x, new->high.x) - Min(original->low.x, new->low.x); union_height = Max(original->high.y, new->high.y) - Min(original->low.y, new->low.y); ! ! if ((isnan(union_width) || isnan(union_height)) && ! isnan(original_width) || isnan(original_height)) ! return 0.0; ! ! return union_width * union_height - original_width * original_height; } /* *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 605,611 **** /* * Find next lower bound of right group. */ ! while (i1 < nentries && rightLower == intervalsLower[i1].lower) { leftUpper = Max(leftUpper, intervalsLower[i1].upper); i1++; --- 639,646 ---- /* * Find next lower bound of right group. */ ! while (i1 < nentries && ! !float8_cmp_internal(rightLower, intervalsLower[i1].lower)) { leftUpper = Max(leftUpper, intervalsLower[i1].upper); i1++; *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 618,624 **** * Find count of intervals which anyway should be placed to the * left group. */ ! while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper) i2++; /* --- 653,660 ---- * Find count of intervals which anyway should be placed to the * left group. */ ! while (i2 < nentries && float8_cmp_internal( ! intervalsUpper[i2].upper, leftUpper) <= 0) i2++; /* *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 640,646 **** /* * Find next upper bound of left group. */ ! while (i2 >= 0 && leftUpper == intervalsUpper[i2].upper) { rightLower = Min(rightLower, intervalsUpper[i2].lower); i2--; --- 676,683 ---- /* * Find next upper bound of left group. */ ! while (i2 >= 0 && ! !float8_cmp_internal(leftUpper, intervalsUpper[i2].upper)) { rightLower = Min(rightLower, intervalsUpper[i2].lower); i2--; *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 653,659 **** * Find count of intervals which anyway should be placed to the * right group. */ ! while (i1 >= 0 && intervalsLower[i1].lower >= rightLower) i1--; /* --- 690,697 ---- * Find count of intervals which anyway should be placed to the * right group. */ ! while (i1 >= 0 && float8_cmp_internal( ! intervalsLower[i1].lower, rightLower) >= 0) i1--; /* *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 741,750 **** upper = box->high.y; } ! if (upper <= context.leftUpper) { /* Fits to the left group */ ! if (lower >= context.rightLower) { /* Fits also to the right group, so "common entry" */ commonEntries[commonEntriesCount++].index = i; --- 779,788 ---- upper = box->high.y; } ! if (float8_cmp_internal(upper, context.leftUpper) <= 0) { /* Fits to the left group */ ! if (float8_cmp_internal(lower, context.rightLower) >= 0) { /* Fits also to the right group, so "common entry" */ commonEntries[commonEntriesCount++].index = i; *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 762,768 **** * entry didn't fit on the left group, it better fit in the right * group. */ ! Assert(lower >= context.rightLower); /* Doesn't fit to the left group, so join to the right group */ PLACE_RIGHT(box, i); --- 800,806 ---- * entry didn't fit on the left group, it better fit in the right * group. */ ! Assert(float8_cmp_internal(lower, context.rightLower) >= 0); /* Doesn't fit to the left group, so join to the right group */ PLACE_RIGHT(box, i);