Commit d544ec8b authored by Teodor Sigaev's avatar Teodor Sigaev

1. full functional WAL for GiST

2. improve vacuum for gist
   - use FSM
   - full vacuum:
      - reforms parent tuple if it's needed
        ( tuples was deleted on child page or parent tuple remains invalid
          after crash recovery )
      - truncate index file if possible
3. fixes bugs and mistakes
parent 0b62bbe0
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for access/gist # Makefile for access/gist
# #
# IDENTIFICATION # IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/access/gist/Makefile,v 1.13 2005/06/14 11:45:13 teodor Exp $ # $PostgreSQL: pgsql/src/backend/access/gist/Makefile,v 1.14 2005/06/20 10:29:36 teodor Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -12,7 +12,7 @@ subdir = src/backend/access/gist ...@@ -12,7 +12,7 @@ subdir = src/backend/access/gist
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = gist.o gistutil.o gistxlog.o gistget.o gistscan.o OBJS = gist.o gistutil.o gistxlog.o gistvacuum.o gistget.o gistscan.o
all: SUBSYS.o all: SUBSYS.o
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.48 2005/06/14 11:45:13 teodor Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.49 2005/06/20 10:29:36 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -112,7 +112,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir) ...@@ -112,7 +112,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir)
{ {
Page p; Page p;
OffsetNumber n; OffsetNumber n;
GISTPageOpaque po;
GISTScanOpaque so; GISTScanOpaque so;
GISTSTACK *stk; GISTSTACK *stk;
IndexTuple it; IndexTuple it;
...@@ -127,7 +126,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir) ...@@ -127,7 +126,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir)
} }
p = BufferGetPage(so->curbuf); p = BufferGetPage(so->curbuf);
po = (GISTPageOpaque) PageGetSpecialPointer(p);
if (ItemPointerIsValid(&scan->currentItemData) == false) if (ItemPointerIsValid(&scan->currentItemData) == false)
{ {
...@@ -169,7 +167,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir) ...@@ -169,7 +167,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir)
so->curbuf = ReleaseAndReadBuffer(so->curbuf, scan->indexRelation, so->curbuf = ReleaseAndReadBuffer(so->curbuf, scan->indexRelation,
stk->block); stk->block);
p = BufferGetPage(so->curbuf); p = BufferGetPage(so->curbuf);
po = (GISTPageOpaque) PageGetSpecialPointer(p);
if (ScanDirectionIsBackward(dir)) if (ScanDirectionIsBackward(dir))
n = OffsetNumberPrev(stk->offset); n = OffsetNumberPrev(stk->offset);
...@@ -182,7 +179,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir) ...@@ -182,7 +179,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir)
continue; continue;
} }
if (po->flags & F_LEAF) if (GistPageIsLeaf(p))
{ {
/* /*
* We've found a matching index entry in a leaf page, so * We've found a matching index entry in a leaf page, so
...@@ -219,7 +216,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir) ...@@ -219,7 +216,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir)
so->curbuf = ReleaseAndReadBuffer(so->curbuf, scan->indexRelation, so->curbuf = ReleaseAndReadBuffer(so->curbuf, scan->indexRelation,
child_block); child_block);
p = BufferGetPage(so->curbuf); p = BufferGetPage(so->curbuf);
po = (GISTPageOpaque) PageGetSpecialPointer(p);
if (ScanDirectionIsBackward(dir)) if (ScanDirectionIsBackward(dir))
n = PageGetMaxOffsetNumber(p); n = PageGetMaxOffsetNumber(p);
...@@ -256,6 +252,12 @@ gistindex_keytest(IndexTuple tuple, ...@@ -256,6 +252,12 @@ gistindex_keytest(IndexTuple tuple,
IncrIndexProcessed(); IncrIndexProcessed();
/*
* Tuple doesn't restore after crash recovery because of inclomplete insert
*/
if ( !GistPageIsLeaf(p) && GistTupleIsInvalid(tuple) )
return true;
while (keySize > 0) while (keySize > 0)
{ {
Datum datum; Datum datum;
...@@ -317,7 +319,6 @@ gistfindnext(IndexScanDesc scan, OffsetNumber n, ScanDirection dir) ...@@ -317,7 +319,6 @@ gistfindnext(IndexScanDesc scan, OffsetNumber n, ScanDirection dir)
{ {
OffsetNumber maxoff; OffsetNumber maxoff;
IndexTuple it; IndexTuple it;
GISTPageOpaque po;
GISTScanOpaque so; GISTScanOpaque so;
MemoryContext oldcxt; MemoryContext oldcxt;
Page p; Page p;
...@@ -325,7 +326,6 @@ gistfindnext(IndexScanDesc scan, OffsetNumber n, ScanDirection dir) ...@@ -325,7 +326,6 @@ gistfindnext(IndexScanDesc scan, OffsetNumber n, ScanDirection dir)
so = (GISTScanOpaque) scan->opaque; so = (GISTScanOpaque) scan->opaque;
p = BufferGetPage(so->curbuf); p = BufferGetPage(so->curbuf);
maxoff = PageGetMaxOffsetNumber(p); maxoff = PageGetMaxOffsetNumber(p);
po = (GISTPageOpaque) PageGetSpecialPointer(p);
/* /*
* Make sure we're in a short-lived memory context when we invoke * Make sure we're in a short-lived memory context when we invoke
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.1 2005/06/14 11:45:13 teodor Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.2 2005/06/20 10:29:36 teodor Exp $
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/freespace.h"
/* group flags ( in gistadjsubkey ) */ /* group flags ( in gistadjsubkey ) */
#define LEFT_ADDED 0x01 #define LEFT_ADDED 0x01
...@@ -132,9 +133,14 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate) ...@@ -132,9 +133,14 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
GistEntryVector *evec; GistEntryVector *evec;
int i; int i;
GISTENTRY centry[INDEX_MAX_KEYS]; GISTENTRY centry[INDEX_MAX_KEYS];
IndexTuple res;
evec = (GistEntryVector *) palloc(((len == 1) ? 2 : len) * sizeof(GISTENTRY) + GEVHDRSZ); evec = (GistEntryVector *) palloc(((len == 1) ? 2 : len) * sizeof(GISTENTRY) + GEVHDRSZ);
for(i = 0; i<len; i++)
if ( GistTupleIsInvalid( itvec[i] ) )
return gist_form_invalid_tuple( InvalidBlockNumber );
for (i = 0; i < r->rd_att->natts; i++) for (i = 0; i < r->rd_att->natts; i++)
{ {
Datum datum; Datum datum;
...@@ -191,7 +197,9 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate) ...@@ -191,7 +197,9 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
} }
} }
return index_form_tuple(giststate->tupdesc, attr, isnull); res = index_form_tuple(giststate->tupdesc, attr, isnull);
GistTupleSetValid( res );
return res;
} }
...@@ -215,11 +223,15 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis ...@@ -215,11 +223,15 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
IndexTuple newtup = NULL; IndexTuple newtup = NULL;
int i; int i;
if ( GistTupleIsInvalid(oldtup) || GistTupleIsInvalid(addtup) )
return gist_form_invalid_tuple( ItemPointerGetBlockNumber( &(oldtup->t_tid) ) );
evec = palloc(2 * sizeof(GISTENTRY) + GEVHDRSZ); evec = palloc(2 * sizeof(GISTENTRY) + GEVHDRSZ);
evec->n = 2; evec->n = 2;
ev0p = &(evec->vector[0]); ev0p = &(evec->vector[0]);
ev1p = &(evec->vector[1]); ev1p = &(evec->vector[1]);
gistDeCompressAtt(giststate, r, oldtup, NULL, gistDeCompressAtt(giststate, r, oldtup, NULL,
(OffsetNumber) 0, oldatt, oldisnull); (OffsetNumber) 0, oldatt, oldisnull);
...@@ -283,7 +295,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis ...@@ -283,7 +295,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
} }
void void
gistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITVEC *spl) gistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITVEC *spl, bool isall)
{ {
int lr; int lr;
...@@ -314,9 +326,9 @@ gistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITV ...@@ -314,9 +326,9 @@ gistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITV
isnull = spl->spl_risnull; isnull = spl->spl_risnull;
} }
evec = palloc(((len == 1) ? 2 : len) * sizeof(GISTENTRY) + GEVHDRSZ); evec = palloc(((len < 2) ? 2 : len) * sizeof(GISTENTRY) + GEVHDRSZ);
for (i = 1; i < r->rd_att->natts; i++) for (i = (isall) ? 0 : 1; i < r->rd_att->natts; i++)
{ {
int j; int j;
Datum datum; Datum datum;
...@@ -448,7 +460,7 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl) ...@@ -448,7 +460,7 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl)
void void
gistadjsubkey(Relation r, gistadjsubkey(Relation r,
IndexTuple *itup, /* contains compressed entry */ IndexTuple *itup, /* contains compressed entry */
int *len, int len,
GIST_SPLITVEC *v, GIST_SPLITVEC *v,
GISTSTATE *giststate) GISTSTATE *giststate)
{ {
...@@ -501,7 +513,7 @@ gistadjsubkey(Relation r, ...@@ -501,7 +513,7 @@ gistadjsubkey(Relation r,
ev1p = &(evec->vector[1]); ev1p = &(evec->vector[1]);
/* add equivalent tuple */ /* add equivalent tuple */
for (i = 0; i < *len; i++) for (i = 0; i < len; i++)
{ {
Datum datum; Datum datum;
...@@ -617,7 +629,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */ ...@@ -617,7 +629,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
maxoff = PageGetMaxOffsetNumber(p); maxoff = PageGetMaxOffsetNumber(p);
*which_grow = -1.0; *which_grow = -1.0;
which = -1; which = InvalidOffsetNumber;
sum_grow = 1; sum_grow = 1;
gistDeCompressAtt(giststate, r, gistDeCompressAtt(giststate, r,
it, NULL, (OffsetNumber) 0, it, NULL, (OffsetNumber) 0,
...@@ -627,6 +639,12 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */ ...@@ -627,6 +639,12 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
{ {
int j; int j;
IndexTuple itup = (IndexTuple) PageGetItem(p, PageGetItemId(p, i)); IndexTuple itup = (IndexTuple) PageGetItem(p, PageGetItemId(p, i));
if ( !GistPageIsLeaf(p) && GistTupleIsInvalid(itup) ) {
elog(LOG, "It's desirable to vacuum or reindex GiST index '%s' due to crash recovery",
RelationGetRelationName(r));
continue;
}
sum_grow = 0; sum_grow = 0;
for (j = 0; j < r->rd_att->natts; j++) for (j = 0; j < r->rd_att->natts; j++)
...@@ -660,6 +678,9 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */ ...@@ -660,6 +678,9 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
} }
} }
if ( which == InvalidOffsetNumber )
which = FirstOffsetNumber;
return which; return which;
} }
...@@ -721,6 +742,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r, ...@@ -721,6 +742,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
GISTENTRY centry[INDEX_MAX_KEYS]; GISTENTRY centry[INDEX_MAX_KEYS];
Datum compatt[INDEX_MAX_KEYS]; Datum compatt[INDEX_MAX_KEYS];
int i; int i;
IndexTuple res;
for (i = 0; i < r->rd_att->natts; i++) for (i = 0; i < r->rd_att->natts; i++)
{ {
...@@ -735,7 +757,9 @@ gistFormTuple(GISTSTATE *giststate, Relation r, ...@@ -735,7 +757,9 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
} }
} }
return index_form_tuple(giststate->tupdesc, compatt, isnull); res = index_form_tuple(giststate->tupdesc, compatt, isnull);
GistTupleSetValid(res);
return res;
} }
void void
...@@ -783,3 +807,79 @@ GISTInitBuffer(Buffer b, uint32 f) ...@@ -783,3 +807,79 @@ GISTInitBuffer(Buffer b, uint32 f)
opaque->flags = f; opaque->flags = f;
} }
void
gistUserPicksplit(Relation r, GistEntryVector *entryvec, GIST_SPLITVEC *v,
IndexTuple *itup, int len, GISTSTATE *giststate) {
/*
* now let the user-defined picksplit function set up the split
* vector; in entryvec have no null value!!
*/
FunctionCall2(&giststate->picksplitFn[0],
PointerGetDatum(entryvec),
PointerGetDatum(v));
/* compatibility with old code */
if (v->spl_left[v->spl_nleft - 1] == InvalidOffsetNumber)
v->spl_left[v->spl_nleft - 1] = (OffsetNumber) (entryvec->n - 1);
if (v->spl_right[v->spl_nright - 1] == InvalidOffsetNumber)
v->spl_right[v->spl_nright - 1] = (OffsetNumber) (entryvec->n - 1);
v->spl_lattr[0] = v->spl_ldatum;
v->spl_rattr[0] = v->spl_rdatum;
v->spl_lisnull[0] = false;
v->spl_risnull[0] = false;
/*
* if index is multikey, then we must to try get smaller bounding box
* for subkey(s)
*/
if (r->rd_att->natts > 1)
{
int MaxGrpId;
v->spl_idgrp = (int *) palloc0(sizeof(int) * entryvec->n);
v->spl_grpflag = (char *) palloc0(sizeof(char) * entryvec->n);
v->spl_ngrp = (int *) palloc(sizeof(int) * entryvec->n);
MaxGrpId = gistfindgroup(giststate, entryvec->vector, v);
/* form union of sub keys for each page (l,p) */
gistunionsubkey(r, giststate, itup, v, false);
/*
* if possible, we insert equivalent tuples with control by
* penalty for a subkey(s)
*/
if (MaxGrpId > 1)
gistadjsubkey(r, itup, len, v, giststate);
}
}
Buffer
gistReadBuffer(Relation r, BlockNumber blkno) {
Buffer buffer = InvalidBuffer;
if ( blkno != P_NEW ) {
buffer = ReadBuffer(r, blkno);
} else {
Page page;
while(true) {
blkno = GetFreeIndexPage(&r->rd_node);
if (blkno == InvalidBlockNumber)
break;
buffer = ReadBuffer(r, blkno);
page = BufferGetPage(buffer);
if ( GistPageIsDeleted( page ) ) {
GistPageSetNonDeleted( page );
return buffer;
}
ReleaseBuffer( buffer );
}
buffer = ReadBuffer(r, P_NEW);
}
return buffer;
}
This diff is collapsed.
This diff is collapsed.
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.46 2005/05/17 03:34:18 neilc Exp $ * $PostgreSQL: pgsql/src/include/access/gist.h,v 1.47 2005/06/20 10:29:36 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
* Page opaque data in a GiST index page. * Page opaque data in a GiST index page.
*/ */
#define F_LEAF (1 << 0) #define F_LEAF (1 << 0)
#define F_DELETED (1 << 1)
#define F_TUPLES_DELETED (1 << 2)
typedef struct GISTPageOpaqueData typedef struct GISTPageOpaqueData
{ {
...@@ -56,6 +58,7 @@ typedef struct GIST_SPLITVEC ...@@ -56,6 +58,7 @@ typedef struct GIST_SPLITVEC
* spl_left */ * spl_left */
int spl_lattrsize[INDEX_MAX_KEYS]; int spl_lattrsize[INDEX_MAX_KEYS];
bool spl_lisnull[INDEX_MAX_KEYS]; bool spl_lisnull[INDEX_MAX_KEYS];
bool spl_leftvalid;
OffsetNumber *spl_right; /* array of entries that go right */ OffsetNumber *spl_right; /* array of entries that go right */
int spl_nright; /* size of the array */ int spl_nright; /* size of the array */
...@@ -64,6 +67,7 @@ typedef struct GIST_SPLITVEC ...@@ -64,6 +67,7 @@ typedef struct GIST_SPLITVEC
* spl_right */ * spl_right */
int spl_rattrsize[INDEX_MAX_KEYS]; int spl_rattrsize[INDEX_MAX_KEYS];
bool spl_risnull[INDEX_MAX_KEYS]; bool spl_risnull[INDEX_MAX_KEYS];
bool spl_rightvalid;
int *spl_idgrp; int *spl_idgrp;
int *spl_ngrp; /* number in each group */ int *spl_ngrp; /* number in each group */
...@@ -86,7 +90,18 @@ typedef struct GISTENTRY ...@@ -86,7 +90,18 @@ typedef struct GISTENTRY
bool leafkey; bool leafkey;
} GISTENTRY; } GISTENTRY;
#define GIST_LEAF(entry) (((GISTPageOpaque) PageGetSpecialPointer((entry)->page))->flags & F_LEAF) #define GistPageIsLeaf(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags & F_LEAF)
#define GIST_LEAF(entry) (GistPageIsLeaf((entry)->page))
#define GistPageSetLeaf(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags |= F_LEAF)
#define GistPageSetNonLeaf(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags &= ~F_LEAF)
#define GistPageIsDeleted(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags & F_DELETED)
#define GistPageSetDeleted(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags |= F_DELETED)
#define GistPageSetNonDeleted(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags &= ~F_DELETED)
#define GistTuplesDeleted(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags & F_TUPLES_DELETED)
#define GistMarkTuplesDeleted(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags |= F_TUPLES_DELETED)
#define GistClearTuplesDeleted(page) (((GISTPageOpaque) PageGetSpecialPointer(page))->flags &= ~F_TUPLES_DELETED)
/* /*
* Vector of GISTENTRY structs; user-defined methods union and pick * Vector of GISTENTRY structs; user-defined methods union and pick
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.3 2005/06/14 11:45:14 teodor Exp $ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.4 2005/06/20 10:29:36 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -94,7 +94,6 @@ typedef struct { ...@@ -94,7 +94,6 @@ typedef struct {
int ituplen; /* length of itup */ int ituplen; /* length of itup */
GISTInsertStack *stack; GISTInsertStack *stack;
bool needInsertComplete; bool needInsertComplete;
bool xlog_mode;
/* pointer to heap tuple */ /* pointer to heap tuple */
ItemPointerData key; ItemPointerData key;
...@@ -142,19 +141,20 @@ typedef struct gistxlogEntryUpdate { ...@@ -142,19 +141,20 @@ typedef struct gistxlogEntryUpdate {
RelFileNode node; RelFileNode node;
BlockNumber blkno; BlockNumber blkno;
/* if todeleteoffnum!=InvalidOffsetNumber then delete it. */ uint16 ntodelete;
OffsetNumber todeleteoffnum;
uint16 pathlen; uint16 pathlen;
bool isemptypage;
/* /*
* It used to identify compliteness of insert. * It used to identify completeness of insert.
* Sets to leaf itup * Sets to leaf itup
*/ */
ItemPointerData key; ItemPointerData key;
/* follow: /* follow:
* 1. path to root (BlockNumber) * 1. path to root (BlockNumber)
* 2. tuples to insert * 2. todelete OffsetNumbers
* 3. tuples to insert
*/ */
} gistxlogEntryUpdate; } gistxlogEntryUpdate;
...@@ -163,18 +163,19 @@ typedef struct gistxlogEntryUpdate { ...@@ -163,18 +163,19 @@ typedef struct gistxlogEntryUpdate {
typedef struct gistxlogPageSplit { typedef struct gistxlogPageSplit {
RelFileNode node; RelFileNode node;
BlockNumber origblkno; /*splitted page*/ BlockNumber origblkno; /*splitted page*/
OffsetNumber todeleteoffnum; uint16 ntodelete;
uint16 pathlen; uint16 pathlen;
int npage; uint16 npage;
int nitup; uint16 nitup;
/* see comments on gistxlogEntryUpdate */ /* see comments on gistxlogEntryUpdate */
ItemPointerData key; ItemPointerData key;
/* follow: /* follow:
* 1. path to root (BlockNumber) * 1. path to root (BlockNumber)
* 2. tuples to insert * 2. todelete OffsetNumbers
* 3. gistxlogPage and array of OffsetNumber per page * 3. tuples to insert
* 4. gistxlogPage and array of OffsetNumber per page
*/ */
} gistxlogPageSplit; } gistxlogPageSplit;
...@@ -188,32 +189,65 @@ typedef struct gistxlogPage { ...@@ -188,32 +189,65 @@ typedef struct gistxlogPage {
typedef struct gistxlogInsertComplete { typedef struct gistxlogInsertComplete {
RelFileNode node; RelFileNode node;
ItemPointerData key; /* follows ItemPointerData key to clean */
} gistxlogInsertComplete; } gistxlogInsertComplete;
#define XLOG_GIST_CREATE_INDEX 0x50 #define XLOG_GIST_CREATE_INDEX 0x50
/*
* mark tuples on inner pages during recovery
*/
#define TUPLE_IS_VALID 0xffff
#define TUPLE_IS_INVALID 0xfffe
#define GistTupleIsInvalid(itup) ( ItemPointerGetOffsetNumber( &((itup)->t_tid) ) == TUPLE_IS_INVALID )
#define GistTupleSetValid(itup) ItemPointerSetOffsetNumber( &((itup)->t_tid), TUPLE_IS_VALID )
#define GistTupleSetInvalid(itup) ItemPointerSetOffsetNumber( &((itup)->t_tid), TUPLE_IS_INVALID )
/* gist.c */ /* gist.c */
extern Datum gistbuild(PG_FUNCTION_ARGS); extern Datum gistbuild(PG_FUNCTION_ARGS);
extern Datum gistinsert(PG_FUNCTION_ARGS); extern Datum gistinsert(PG_FUNCTION_ARGS);
extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
extern MemoryContext createTempGistContext(void); extern MemoryContext createTempGistContext(void);
extern void initGISTstate(GISTSTATE *giststate, Relation index); extern void initGISTstate(GISTSTATE *giststate, Relation index);
extern void freeGISTstate(GISTSTATE *giststate); extern void freeGISTstate(GISTSTATE *giststate);
extern void gistnewroot(Relation r, IndexTuple *itup, int len, ItemPointer key, bool xlog_mode); extern void gistnewroot(Relation r, IndexTuple *itup, int len, ItemPointer key);
extern void gistmakedeal(GISTInsertState *state, GISTSTATE *giststate); extern void gistmakedeal(GISTInsertState *state, GISTSTATE *giststate);
typedef struct SplitedPageLayout {
gistxlogPage block;
OffsetNumber *list;
Buffer buffer; /* to write after all proceed */
struct SplitedPageLayout *next;
} SplitedPageLayout;
IndexTuple * gistSplit(Relation r, Buffer buffer, IndexTuple *itup,
int *len, SplitedPageLayout **dist, GISTSTATE *giststate);
/* gistxlog.c */ /* gistxlog.c */
extern void gist_redo(XLogRecPtr lsn, XLogRecord *record); extern void gist_redo(XLogRecPtr lsn, XLogRecord *record);
extern void gist_desc(char *buf, uint8 xl_info, char *rec); extern void gist_desc(char *buf, uint8 xl_info, char *rec);
extern void gist_xlog_startup(void); extern void gist_xlog_startup(void);
extern void gist_xlog_cleanup(void); extern void gist_xlog_cleanup(void);
extern IndexTuple gist_form_invalid_tuple(BlockNumber blkno);
extern XLogRecData* formUpdateRdata(RelFileNode node, BlockNumber blkno,
OffsetNumber *todelete, int ntodelete, bool emptypage,
IndexTuple *itup, int ituplen, ItemPointer key,
BlockNumber *path, int pathlen);
extern XLogRecData* formSplitRdata(RelFileNode node, BlockNumber blkno,
OffsetNumber *todelete, int ntodelete,
IndexTuple *itup, int ituplen, ItemPointer key,
BlockNumber *path, int pathlen, SplitedPageLayout *dist );
extern XLogRecPtr gistxlogInsertCompletion(RelFileNode node, ItemPointerData *keys, int len);
/* gistget.c */ /* gistget.c */
extern Datum gistgettuple(PG_FUNCTION_ARGS); extern Datum gistgettuple(PG_FUNCTION_ARGS);
extern Datum gistgetmulti(PG_FUNCTION_ARGS); extern Datum gistgetmulti(PG_FUNCTION_ARGS);
/* gistutil.c */ /* gistutil.c */
extern Buffer gistReadBuffer(Relation r, BlockNumber blkno);
extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup, extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup,
int len, OffsetNumber off); int len, OffsetNumber off);
extern bool gistnospace(Page page, IndexTuple *itvec, int len); extern bool gistnospace(Page page, IndexTuple *itvec, int len);
...@@ -230,7 +264,7 @@ extern IndexTuple gistgetadjusted(Relation r, ...@@ -230,7 +264,7 @@ extern IndexTuple gistgetadjusted(Relation r,
extern int gistfindgroup(GISTSTATE *giststate, extern int gistfindgroup(GISTSTATE *giststate,
GISTENTRY *valvec, GIST_SPLITVEC *spl); GISTENTRY *valvec, GIST_SPLITVEC *spl);
extern void gistadjsubkey(Relation r, extern void gistadjsubkey(Relation r,
IndexTuple *itup, int *len, IndexTuple *itup, int len,
GIST_SPLITVEC *v, GIST_SPLITVEC *v,
GISTSTATE *giststate); GISTSTATE *giststate);
extern IndexTuple gistFormTuple(GISTSTATE *giststate, extern IndexTuple gistFormTuple(GISTSTATE *giststate,
...@@ -247,10 +281,16 @@ extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, ...@@ -247,10 +281,16 @@ extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r,
IndexTuple tuple, Page p, OffsetNumber o, IndexTuple tuple, Page p, OffsetNumber o,
GISTENTRY *attdata, bool *isnull); GISTENTRY *attdata, bool *isnull);
extern void gistunionsubkey(Relation r, GISTSTATE *giststate, extern void gistunionsubkey(Relation r, GISTSTATE *giststate,
IndexTuple *itvec, GIST_SPLITVEC *spl); IndexTuple *itvec, GIST_SPLITVEC *spl, bool isall);
extern void GISTInitBuffer(Buffer b, uint32 f); extern void GISTInitBuffer(Buffer b, uint32 f);
extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
Datum k, Relation r, Page pg, OffsetNumber o, Datum k, Relation r, Page pg, OffsetNumber o,
int b, bool l, bool isNull); int b, bool l, bool isNull);
void gistUserPicksplit(Relation r, GistEntryVector *entryvec, GIST_SPLITVEC *v,
IndexTuple *itup, int len, GISTSTATE *giststate);
/* gistvacuum.c */
extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
extern Datum gistvacuumcleanup(PG_FUNCTION_ARGS);
#endif /* GIST_PRIVATE_H */ #endif /* GIST_PRIVATE_H */
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.278 2005/06/18 19:33:42 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.279 2005/06/20 10:29:37 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200506181 #define CATALOG_VERSION_NO 200506201
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.34 2005/06/13 23:14:49 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.35 2005/06/20 10:29:37 teodor Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -112,7 +112,7 @@ DESCR("b-tree index access method"); ...@@ -112,7 +112,7 @@ DESCR("b-tree index access method");
DATA(insert OID = 405 ( hash 1 1 0 f f f f t hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate )); DATA(insert OID = 405 ( hash 1 1 0 f f f f t hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
DESCR("hash index access method"); DESCR("hash index access method");
#define HASH_AM_OID 405 #define HASH_AM_OID 405
DATA(insert OID = 783 ( gist 100 7 0 f t f f f gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete - gistcostestimate )); DATA(insert OID = 783 ( gist 100 7 0 f t f f f gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate ));
DESCR("GiST index access method"); DESCR("GiST index access method");
#define GIST_AM_OID 783 #define GIST_AM_OID 783
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.368 2005/06/17 22:32:48 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.369 2005/06/20 10:29:37 teodor Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -1092,6 +1092,7 @@ DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 228 ...@@ -1092,6 +1092,7 @@ DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 228
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ gistbulkdelete - _null_ )); DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ gistbulkdelete - _null_ ));
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 2561 ( gistvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ gistvacuumcleanup - _null_ ));
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistcostestimate - _null_ )); DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistcostestimate - _null_ ));
DESCR("gist(internal)"); DESCR("gist(internal)");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment