diff options
Diffstat (limited to 'src/backend/access/gist')
-rw-r--r-- | src/backend/access/gist/README | 2 | ||||
-rw-r--r-- | src/backend/access/gist/gist.c | 14 | ||||
-rw-r--r-- | src/backend/access/gist/gistxlog.c | 16 |
3 files changed, 23 insertions, 9 deletions
diff --git a/src/backend/access/gist/README b/src/backend/access/gist/README index 2d78dcb0dfa..b24673e624a 100644 --- a/src/backend/access/gist/README +++ b/src/backend/access/gist/README @@ -128,7 +128,7 @@ that didn't need to be split. This differs from the insertion algorithm in the original paper. In the original paper, you first walk down the tree until you reach a leaf page, and -then you adjust the downlink in the parent, and propagating the adjustment up, +then you adjust the downlink in the parent, and propagate the adjustment up, all the way up to the root in the worst case. But we adjust the downlinks to cover the new key already when we walk down, so that when we reach the leaf page, we don't need to update the parents anymore, except to insert the diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 7dbc5dd08ec..7172f210286 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -356,6 +356,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate, SplitedPageLayout rootpg; BlockNumber blkno = BufferGetBlockNumber(buffer); bool is_rootsplit; + int npage; is_rootsplit = (blkno == GIST_ROOT_BLKNO); @@ -377,6 +378,19 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate, dist = gistSplit(state->r, page, itvec, tlen, giststate); /* + * Check that split didn't produce too many pages. + */ + npage = 0; + for (ptr = dist; ptr; ptr = ptr->next) + npage++; + /* in a root split, we'll add one more page to the list below */ + if (is_rootsplit) + npage++; + if (npage > GIST_MAX_SPLIT_PAGES) + elog(ERROR, "GiST page split into too many halves (%d, maximum %d)", + npage, GIST_MAX_SPLIT_PAGES); + + /* * Set up pages to work with. Allocate new buffers for all but the * leftmost page. The original page becomes the new leftmost page, and * is just replaced with the new contents. diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index b7de92c8865..d0ca2ffa439 100644 --- a/src/backend/access/gist/gistxlog.c +++ b/src/backend/access/gist/gistxlog.c @@ -434,7 +434,7 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf, BlockNumber origrlink, GistNSN orignsn, Buffer leftchildbuf) { - XLogRecData *rdata; + XLogRecData rdata[GIST_MAX_SPLIT_PAGES * 2 + 2]; gistxlogPageSplit xlrec; SplitedPageLayout *ptr; int npage = 0, @@ -443,8 +443,12 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf, for (ptr = dist; ptr; ptr = ptr->next) npage++; - - rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (npage * 2 + 2)); + /* + * the caller should've checked this already, but doesn't hurt to check + * again. + */ + if (npage > GIST_MAX_SPLIT_PAGES) + elog(ERROR, "GiST page split into too many halves"); xlrec.node = node; xlrec.origblkno = blkno; @@ -493,7 +497,6 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf, recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT, rdata); - pfree(rdata); return recptr; } @@ -516,14 +519,12 @@ gistXLogUpdate(RelFileNode node, Buffer buffer, IndexTuple *itup, int ituplen, Buffer leftchildbuf) { - XLogRecData *rdata; + XLogRecData rdata[MaxIndexTuplesPerPage + 3]; gistxlogPageUpdate xlrec; int cur, i; XLogRecPtr recptr; - rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (3 + ituplen)); - xlrec.node = node; xlrec.blkno = BufferGetBlockNumber(buffer); xlrec.ntodelete = ntodelete; @@ -570,6 +571,5 @@ gistXLogUpdate(RelFileNode node, Buffer buffer, recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_UPDATE, rdata); - pfree(rdata); return recptr; } |