Dead code in _bt_split?
This piece of code in _bt_split, starting at line 859, looks curious to me:
/* cope with possibility that newitem goes at the end */
if (i <= newitemoff)
{
if (newitemonleft)
{
_bt_pgaddtup(rel, leftpage, newitemsz, newitem, leftoff,
"left sibling");
itup_off = leftoff;
itup_blkno = BufferGetBlockNumber(buf);
leftoff = OffsetNumberNext(leftoff);
}
else
{
_bt_pgaddtup(rel, rightpage, newitemsz, newitem, rightoff,
"right sibling");
itup_off = rightoff;
itup_blkno = BufferGetBlockNumber(rbuf);
rightoff = OffsetNumberNext(rightoff);
}
}
This is right after a for-loop, which exits when i = maxoff + 1. So the
first if-statement could be written as "if (newitemoff > maxoff)". If
that's true, newitemonleft shouldn't be true, because that would mean
that we've split a page so that all items went to the left page, and the
right page is empty.
Is that really dead code, or am I missing something? How about putting
an Assert in there instead?
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
"Heikki Linnakangas" <heikki@enterprisedb.com> writes:
This is right after a for-loop, which exits when i = maxoff + 1. So the
first if-statement could be written as "if (newitemoff > maxoff)". If
that's true, newitemonleft shouldn't be true, because that would mean
that we've split a page so that all items went to the left page, and the
right page is empty.
No, it would mean that we split the page in such a way that only the new
item is going to the right page. Probably not hard to duplicate if you
use near-maximal-sized keys.
regards, tom lane
Tom Lane wrote:
"Heikki Linnakangas" <heikki@enterprisedb.com> writes:
This is right after a for-loop, which exits when i = maxoff + 1. So the
first if-statement could be written as "if (newitemoff > maxoff)". If
that's true, newitemonleft shouldn't be true, because that would mean
that we've split a page so that all items went to the left page, and the
right page is empty.No, it would mean that we split the page in such a way that only the new
item is going to the right page. Probably not hard to duplicate if you
use near-maximal-sized keys.
In that case, newitemleft would be false, right?
I'm saying the piece marked with X> below is unreachable:
/* cope with possibility that newitem goes at the end */
if (i <= newitemoff)
{
if (newitemonleft)
{
X> _bt_pgaddtup(rel, leftpage, newitemsz, newitem, leftoff,
X> "left sibling");
X> itup_off = leftoff;
X> itup_blkno = BufferGetBlockNumber(buf);
X> leftoff = OffsetNumberNext(leftoff);
}
else
{
_bt_pgaddtup(rel, rightpage, newitemsz, newitem, rightoff,
"right sibling");
itup_off = rightoff;
itup_blkno = BufferGetBlockNumber(rbuf);
rightoff = OffsetNumberNext(rightoff);
}
}
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Heikki Linnakangas <heikki@enterprisedb.com> writes:
In that case, newitemleft would be false, right?
I'm saying the piece marked with X> below is unreachable:
Oh, I see. Hmm ... probably so, I think that chunk of code was just
copied and pasted from where it occurs within the loop.
regards, tom lane
Heikki, did this code cleanup get included in your recent btree split
fix?
---------------------------------------------------------------------------
Tom Lane wrote:
Heikki Linnakangas <heikki@enterprisedb.com> writes:
In that case, newitemleft would be false, right?
I'm saying the piece marked with X> below is unreachable:Oh, I see. Hmm ... probably so, I think that chunk of code was just
copied and pasted from where it occurs within the loop.regards, tom lane
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend
--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
Bruce Momjian wrote:
Heikki, did this code cleanup get included in your recent btree split
fix?
No.
---------------------------------------------------------------------------
Tom Lane wrote:
Heikki Linnakangas <heikki@enterprisedb.com> writes:
In that case, newitemleft would be false, right?
I'm saying the piece marked with X> below is unreachable:Oh, I see. Hmm ... probably so, I think that chunk of code was just
copied and pasted from where it occurs within the loop.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Heikki Linnakangas wrote:
Bruce Momjian wrote:
Heikki, did this code cleanup get included in your recent btree split
fix?No.
OK, would you please send a patch to remove the unused code. Thanks.
--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
Bruce Momjian wrote:
Heikki Linnakangas wrote:
Bruce Momjian wrote:
Heikki, did this code cleanup get included in your recent btree split
fix?No.
OK, would you please send a patch to remove the unused code. Thanks.
Ok, here you are.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Attachments:
deadcode_in_split.patchtext/x-patch; name=deadcode_in_split.patchDownload
Index: src/backend/access/nbtree/nbtinsert.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/nbtree/nbtinsert.c,v
retrieving revision 1.148
diff -c -r1.148 nbtinsert.c
*** src/backend/access/nbtree/nbtinsert.c 27 Jan 2007 20:53:30 -0000 1.148
--- src/backend/access/nbtree/nbtinsert.c 6 Feb 2007 10:23:26 -0000
***************
*** 855,876 ****
/* cope with possibility that newitem goes at the end */
if (i <= newitemoff)
{
! if (newitemonleft)
! {
! _bt_pgaddtup(rel, leftpage, newitemsz, newitem, leftoff,
! "left sibling");
! itup_off = leftoff;
! itup_blkno = BufferGetBlockNumber(buf);
! leftoff = OffsetNumberNext(leftoff);
! }
! else
! {
! _bt_pgaddtup(rel, rightpage, newitemsz, newitem, rightoff,
! "right sibling");
! itup_off = rightoff;
! itup_blkno = BufferGetBlockNumber(rbuf);
! rightoff = OffsetNumberNext(rightoff);
! }
}
/*
--- 855,865 ----
/* cope with possibility that newitem goes at the end */
if (i <= newitemoff)
{
! _bt_pgaddtup(rel, rightpage, newitemsz, newitem, rightoff,
! "right sibling");
! itup_off = rightoff;
! itup_blkno = BufferGetBlockNumber(rbuf);
! rightoff = OffsetNumberNext(rightoff);
}
/*
Heikki Linnakangas <heikki@enterprisedb.com> writes:
Bruce Momjian wrote:
OK, would you please send a patch to remove the unused code. Thanks.
Ok, here you are.
Applied with an added comment and Assert.
While testing it I realized that there seems to be a nearby bug in
_bt_findsplitloc: it fails to consider the possibility of moving all the
extant items to the left side. It will always return a firstright <=
maxoff. ISTM this would mean that it could choose a bad split if the
incoming item goes at the end and both it and the last extant item are
large: in this case they should be split apart, but they won't be.
Heikki, do you feel like looking at that, or shall I?
regards, tom lane
Tom Lane wrote:
Heikki Linnakangas <heikki@enterprisedb.com> writes:
Bruce Momjian wrote:
OK, would you please send a patch to remove the unused code. Thanks.
Ok, here you are.
Applied with an added comment and Assert.
While testing it I realized that there seems to be a nearby bug in
_bt_findsplitloc: it fails to consider the possibility of moving all the
extant items to the left side. It will always return a firstright <=
maxoff. ISTM this would mean that it could choose a bad split if the
incoming item goes at the end and both it and the last extant item are
large: in this case they should be split apart, but they won't be.Heikki, do you feel like looking at that, or shall I?
I'll take a look at it.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Tom Lane wrote:
While testing it I realized that there seems to be a nearby bug in
_bt_findsplitloc: it fails to consider the possibility of moving all the
extant items to the left side. It will always return a firstright <=
maxoff. ISTM this would mean that it could choose a bad split if the
incoming item goes at the end and both it and the last extant item are
large: in this case they should be split apart, but they won't be.Heikki, do you feel like looking at that, or shall I?
I refactored findsplitloc and checksplitloc so that the division of
labor is more clear IMO. I pushed all the space calculation inside the
loop to checksplitloc.
I also fixed the off by 4 in free space calculation caused by
PageGetFreeSpace subtracting sizeof(ItemIdData), even though it was
harmless, because it was distracting and I felt it might come back to
bite us in the future if we change the page layout or alignments.
There's now a new function PageGetExactFreeSpace that doesn't do the
subtraction.
findsplitloc now tries the "just the new item to right page" split as
well. If people don't like the refactoring, I can write a patch to just
add that.
Some of the long variable names look ugly. camelCase or underscores
between words would be more readable, but I retained the old style for
the sake of consistency.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Attachments:
checksplitloc-refactoring.patchtext/x-patch; name=checksplitloc-refactoring.patchDownload
Index: src/backend/access/nbtree/nbtinsert.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/nbtree/nbtinsert.c,v
retrieving revision 1.150
diff -c -r1.150 nbtinsert.c
*** src/backend/access/nbtree/nbtinsert.c 8 Feb 2007 05:05:53 -0000 1.150
--- src/backend/access/nbtree/nbtinsert.c 8 Feb 2007 13:24:50 -0000
***************
*** 29,34 ****
--- 29,38 ----
int fillfactor; /* needed when splitting rightmost page */
bool is_leaf; /* T if splitting a leaf page */
bool is_rightmost; /* T if splitting a rightmost page */
+ OffsetNumber newitemoff; /* where the new item is to be inserted */
+ int leftspace; /* space available for items on left page */
+ int rightspace; /* space available for items on right page */
+ int olddataitemstotal; /* space taken by old items */
bool have_split; /* found a valid split? */
***************
*** 57,65 ****
OffsetNumber newitemoff,
Size newitemsz,
bool *newitemonleft);
! static void _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
! int leftfree, int rightfree,
! bool newitemonleft, Size firstrightitemsz);
static void _bt_pgaddtup(Relation rel, Page page,
Size itemsize, IndexTuple itup,
OffsetNumber itup_off, const char *where);
--- 61,69 ----
OffsetNumber newitemoff,
Size newitemsz,
bool *newitemonleft);
! static void _bt_checksplitloc(FindSplitData *state,
! OffsetNumber firstoldonright, bool newitemonleft,
! int dataitemstoleft, Size firstoldonrightsz);
static void _bt_pgaddtup(Relation rel, Page page,
Size itemsize, IndexTuple itup,
OffsetNumber itup_off, const char *where);
***************
*** 1101,1113 ****
int leftspace,
rightspace,
goodenough,
! dataitemtotal,
! dataitemstoleft;
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* Passed-in newitemsz is MAXALIGNED but does not include line pointer */
newitemsz += sizeof(ItemIdData);
state.newitemsz = newitemsz;
state.is_leaf = P_ISLEAF(opaque);
state.is_rightmost = P_RIGHTMOST(opaque);
--- 1105,1135 ----
int leftspace,
rightspace,
goodenough,
! olddataitemstotal,
! olddataitemstoleft;
! bool goodenoughfound;
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* Passed-in newitemsz is MAXALIGNED but does not include line pointer */
newitemsz += sizeof(ItemIdData);
+
+ /* Total free space available on a btree page, after fixed overhead */
+ leftspace = rightspace =
+ PageGetPageSize(page) - SizeOfPageHeaderData -
+ MAXALIGN(sizeof(BTPageOpaqueData));
+
+ /* The right page will have the same high key as the old page */
+ if (!P_RIGHTMOST(opaque))
+ {
+ itemid = PageGetItemId(page, P_HIKEY);
+ rightspace -= (int) (MAXALIGN(ItemIdGetLength(itemid)) +
+ sizeof(ItemIdData));
+ }
+
+ /* Count up total space in data items without actually scanning 'em */
+ olddataitemstotal = rightspace - (int) PageGetExactFreeSpace(page);
+
state.newitemsz = newitemsz;
state.is_leaf = P_ISLEAF(opaque);
state.is_rightmost = P_RIGHTMOST(opaque);
***************
*** 1120,1130 ****
state.newitemonleft = false; /* these just to keep compiler quiet */
state.firstright = 0;
state.best_delta = 0;
!
! /* Total free space available on a btree page, after fixed overhead */
! leftspace = rightspace =
! PageGetPageSize(page) - SizeOfPageHeaderData -
! MAXALIGN(sizeof(BTPageOpaqueData));
/*
* Finding the best possible split would require checking all the possible
--- 1142,1151 ----
state.newitemonleft = false; /* these just to keep compiler quiet */
state.firstright = 0;
state.best_delta = 0;
! state.leftspace = leftspace;
! state.rightspace = rightspace;
! state.olddataitemstotal = olddataitemstotal;
! state.newitemoff = newitemoff;
/*
* Finding the best possible split would require checking all the possible
***************
*** 1137,1210 ****
*/
goodenough = leftspace / 16;
- /* The right page will have the same high key as the old page */
- if (!P_RIGHTMOST(opaque))
- {
- itemid = PageGetItemId(page, P_HIKEY);
- rightspace -= (int) (MAXALIGN(ItemIdGetLength(itemid)) +
- sizeof(ItemIdData));
- }
-
- /* Count up total space in data items without actually scanning 'em */
- dataitemtotal = rightspace - (int) PageGetFreeSpace(page);
-
/*
* Scan through the data items and calculate space usage for a split at
* each possible position.
*/
! dataitemstoleft = 0;
maxoff = PageGetMaxOffsetNumber(page);
!
for (offnum = P_FIRSTDATAKEY(opaque);
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
{
Size itemsz;
- int leftfree,
- rightfree;
itemid = PageGetItemId(page, offnum);
itemsz = MAXALIGN(ItemIdGetLength(itemid)) + sizeof(ItemIdData);
/*
- * We have to allow for the current item becoming the high key of the
- * left page; therefore it counts against left space as well as right
- * space.
- */
- leftfree = leftspace - dataitemstoleft - (int) itemsz;
- rightfree = rightspace - (dataitemtotal - dataitemstoleft);
-
- /*
* Will the new item go to left or right of split?
*/
if (offnum > newitemoff)
! _bt_checksplitloc(&state, offnum, leftfree, rightfree,
! true, itemsz);
else if (offnum < newitemoff)
! _bt_checksplitloc(&state, offnum, leftfree, rightfree,
! false, itemsz);
else
{
/* need to try it both ways! */
! _bt_checksplitloc(&state, offnum, leftfree, rightfree,
! true, itemsz);
! /*
! * Here we are contemplating newitem as first on right. In this
! * case it, not the current item, will become the high key of the
! * left page, and so we have to correct the allowance made above.
! */
! leftfree += (int) itemsz - (int) newitemsz;
! _bt_checksplitloc(&state, offnum, leftfree, rightfree,
! false, newitemsz);
}
/* Abort scan once we find a good-enough choice */
if (state.have_split && state.best_delta <= goodenough)
break;
! dataitemstoleft += itemsz;
}
/*
* I believe it is not possible to fail to find a feasible split, but just
* in case ...
--- 1158,1217 ----
*/
goodenough = leftspace / 16;
/*
* Scan through the data items and calculate space usage for a split at
* each possible position.
*/
! olddataitemstoleft = 0;
! goodenoughfound = false;
maxoff = PageGetMaxOffsetNumber(page);
!
for (offnum = P_FIRSTDATAKEY(opaque);
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
{
Size itemsz;
itemid = PageGetItemId(page, offnum);
itemsz = MAXALIGN(ItemIdGetLength(itemid)) + sizeof(ItemIdData);
/*
* Will the new item go to left or right of split?
*/
if (offnum > newitemoff)
! _bt_checksplitloc(&state, offnum, true,
! olddataitemstoleft, itemsz);
!
else if (offnum < newitemoff)
! _bt_checksplitloc(&state, offnum, false,
! olddataitemstoleft, itemsz);
else
{
/* need to try it both ways! */
! _bt_checksplitloc(&state, offnum, true,
! olddataitemstoleft, itemsz);
!
! _bt_checksplitloc(&state, offnum, false,
! olddataitemstoleft, itemsz);
}
/* Abort scan once we find a good-enough choice */
if (state.have_split && state.best_delta <= goodenough)
+ {
+ goodenoughfound = true;
break;
+ }
! olddataitemstoleft += itemsz;
}
+ /* If the new item goes as the last item, check for splitting so that
+ * all the old items go to the left page and the new item goes to the
+ * right page.
+ */
+ if (newitemoff > maxoff && !goodenoughfound)
+ _bt_checksplitloc(&state, newitemoff, false, olddataitemstotal, 0);
+
/*
* I believe it is not possible to fail to find a feasible split, but just
* in case ...
***************
*** 1220,1234 ****
/*
* Subroutine to analyze a particular possible split choice (ie, firstright
* and newitemonleft settings), and record the best split so far in *state.
*/
static void
! _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
! int leftfree, int rightfree,
! bool newitemonleft, Size firstrightitemsz)
{
/*
! * Account for the new item on whichever side it is to be put.
*/
if (newitemonleft)
leftfree -= (int) state->newitemsz;
else
--- 1227,1276 ----
/*
* Subroutine to analyze a particular possible split choice (ie, firstright
* and newitemonleft settings), and record the best split so far in *state.
+ *
+ * firstoldonright is the offset of the first item on the original page
+ * that goes to the right page, and firstoldonrightsz is the size of that
+ * tuple. firstoldonright can be > max offset, which means that all the old
+ * items go to the left page and only the new item goes to the right page.
+ * In that case, firstoldonrightsz is not used.
+ *
+ * olddataitemstoleft is the total size of all old items to the left of
+ * firstoldonright.
*/
static void
! _bt_checksplitloc(FindSplitData *state,
! OffsetNumber firstoldonright,
! bool newitemonleft,
! int olddataitemstoleft,
! Size firstoldonrightsz)
{
+ int leftfree,
+ rightfree;
+ Size firstrightitemsz;
+ bool newitemisfirstonright;
+
+ /* Is the new item going to be the first item on the right page? */
+ newitemisfirstonright = (firstoldonright == state->newitemoff
+ && !newitemonleft);
+
+ if(newitemisfirstonright)
+ firstrightitemsz = state->newitemsz;
+ else
+ firstrightitemsz = firstoldonrightsz;
+
+ /* Account for all the old tuples */
+ leftfree = state->leftspace - olddataitemstoleft;
+ rightfree = state->rightspace -
+ (state->olddataitemstotal - olddataitemstoleft);
+
/*
! * The first item on the right page becomes the high key of the
! * left page; therefore it counts against left space as well as right
! * space.
*/
+ leftfree -= firstrightitemsz;
+
+ /* account for the new item */
if (newitemonleft)
leftfree -= (int) state->newitemsz;
else
***************
*** 1270,1276 ****
{
state->have_split = true;
state->newitemonleft = newitemonleft;
! state->firstright = firstright;
state->best_delta = delta;
}
}
--- 1312,1318 ----
{
state->have_split = true;
state->newitemonleft = newitemonleft;
! state->firstright = firstoldonright;
state->best_delta = delta;
}
}
Index: src/backend/storage/page/bufpage.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/storage/page/bufpage.c,v
retrieving revision 1.70
diff -c -r1.70 bufpage.c
*** src/backend/storage/page/bufpage.c 5 Jan 2007 22:19:38 -0000 1.70
--- src/backend/storage/page/bufpage.c 8 Feb 2007 13:02:11 -0000
***************
*** 418,424 ****
/*
* PageGetFreeSpace
! * Returns the size of the free (allocatable) space on a page.
*/
Size
PageGetFreeSpace(Page page)
--- 418,425 ----
/*
* PageGetFreeSpace
! * Returns the size of the free (allocatable) space on a page,
! * deducted by the space needed for a new line pointer.
*/
Size
PageGetFreeSpace(Page page)
***************
*** 434,440 ****
if (space < (int) sizeof(ItemIdData))
return 0;
! space -= sizeof(ItemIdData); /* XXX not always appropriate */
return (Size) space;
}
--- 435,460 ----
if (space < (int) sizeof(ItemIdData))
return 0;
! space -= sizeof(ItemIdData);
!
! return (Size) space;
! }
!
! /*
! * PageGetExactFreeSpace
! * Returns the size of the free (allocatable) space on a page.
! */
! Size
! PageGetExactFreeSpace(Page page)
! {
! int space;
!
! /*
! * Use signed arithmetic here so that we behave sensibly if pd_lower >
! * pd_upper.
! */
! space = (int) ((PageHeader) page)->pd_upper -
! (int) ((PageHeader) page)->pd_lower;
return (Size) space;
}
Index: src/include/storage/bufpage.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/storage/bufpage.h,v
retrieving revision 1.69
diff -c -r1.69 bufpage.h
*** src/include/storage/bufpage.h 5 Jan 2007 22:19:57 -0000 1.69
--- src/include/storage/bufpage.h 7 Feb 2007 13:13:42 -0000
***************
*** 321,326 ****
--- 321,327 ----
extern void PageRestoreTempPage(Page tempPage, Page oldPage);
extern int PageRepairFragmentation(Page page, OffsetNumber *unused);
extern Size PageGetFreeSpace(Page page);
+ extern Size PageGetExactFreeSpace(Page page);
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems);
Your patch has been added to the PostgreSQL unapplied patches list at:
http://momjian.postgresql.org/cgi-bin/pgpatches
It will be applied as soon as one of the PostgreSQL committers reviews
and approves it.
---------------------------------------------------------------------------
Heikki Linnakangas wrote:
Tom Lane wrote:
While testing it I realized that there seems to be a nearby bug in
_bt_findsplitloc: it fails to consider the possibility of moving all the
extant items to the left side. It will always return a firstright <=
maxoff. ISTM this would mean that it could choose a bad split if the
incoming item goes at the end and both it and the last extant item are
large: in this case they should be split apart, but they won't be.Heikki, do you feel like looking at that, or shall I?
I refactored findsplitloc and checksplitloc so that the division of
labor is more clear IMO. I pushed all the space calculation inside the
loop to checksplitloc.I also fixed the off by 4 in free space calculation caused by
PageGetFreeSpace subtracting sizeof(ItemIdData), even though it was
harmless, because it was distracting and I felt it might come back to
bite us in the future if we change the page layout or alignments.
There's now a new function PageGetExactFreeSpace that doesn't do the
subtraction.findsplitloc now tries the "just the new item to right page" split as
well. If people don't like the refactoring, I can write a patch to just
add that.Some of the long variable names look ugly. camelCase or underscores
between words would be more readable, but I retained the old style for
the sake of consistency.--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://www.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
Patch applied. Thanks.
---------------------------------------------------------------------------
Heikki Linnakangas wrote:
Tom Lane wrote:
While testing it I realized that there seems to be a nearby bug in
_bt_findsplitloc: it fails to consider the possibility of moving all the
extant items to the left side. It will always return a firstright <=
maxoff. ISTM this would mean that it could choose a bad split if the
incoming item goes at the end and both it and the last extant item are
large: in this case they should be split apart, but they won't be.Heikki, do you feel like looking at that, or shall I?
I refactored findsplitloc and checksplitloc so that the division of
labor is more clear IMO. I pushed all the space calculation inside the
loop to checksplitloc.I also fixed the off by 4 in free space calculation caused by
PageGetFreeSpace subtracting sizeof(ItemIdData), even though it was
harmless, because it was distracting and I felt it might come back to
bite us in the future if we change the page layout or alignments.
There's now a new function PageGetExactFreeSpace that doesn't do the
subtraction.findsplitloc now tries the "just the new item to right page" split as
well. If people don't like the refactoring, I can write a patch to just
add that.Some of the long variable names look ugly. camelCase or underscores
between words would be more readable, but I retained the old style for
the sake of consistency.--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://www.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +