Commit 1f7ef548 authored by Teodor Sigaev's avatar Teodor Sigaev

Changes

* new split algorithm (as proposed in http://archives.postgresql.org/pgsql-hackers/2006-06/msg00254.php)
  * possible call pickSplit() for second and below columns
  * add spl_(l|r)datum_exists to GIST_SPLITVEC -
    pickSplit should check its values to use already defined
    spl_(l|r)datum for splitting. pickSplit should set
    spl_(l|r)datum_exists to 'false' (if they was 'true') to
    signal to caller about using spl_(l|r)datum.
  * support for old pickSplit(): not very optimal
    but correct split
* remove 'bytes' field from GISTENTRY: in any case size of
  value is defined by it's type.
* split GIST_SPLITVEC to two structures: one for using in picksplit
  and second - for internal use.
* some code refactoring
* support of subsplit to rtree opclasses

TODO: add support of subsplit to contrib modules
parent a1dc5c60
...@@ -100,7 +100,7 @@ gbt_inet_compress(PG_FUNCTION_ARGS) ...@@ -100,7 +100,7 @@ gbt_inet_compress(PG_FUNCTION_ARGS)
r->upper = r->lower; r->upper = r->lower;
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(inetKEY), FALSE); entry->offset, FALSE);
} }
else else
retval = entry; retval = entry;
......
...@@ -129,7 +129,7 @@ gbt_intv_compress(PG_FUNCTION_ARGS) ...@@ -129,7 +129,7 @@ gbt_intv_compress(PG_FUNCTION_ARGS)
} }
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, 2 * INTERVALSIZE, FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
...@@ -153,7 +153,7 @@ gbt_intv_decompress(PG_FUNCTION_ARGS) ...@@ -153,7 +153,7 @@ gbt_intv_decompress(PG_FUNCTION_ARGS)
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(intvKEY), FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
......
...@@ -115,7 +115,7 @@ gbt_bpchar_compress(PG_FUNCTION_ARGS) ...@@ -115,7 +115,7 @@ gbt_bpchar_compress(PG_FUNCTION_ARGS)
gistentryinit(trim, d, gistentryinit(trim, d,
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, VARSIZE(DatumGetPointer(d)), TRUE); entry->offset, TRUE);
retval = gbt_var_compress(&trim, &tinfo); retval = gbt_var_compress(&trim, &tinfo);
} }
else else
......
...@@ -137,7 +137,7 @@ gbt_timetz_compress(PG_FUNCTION_ARGS) ...@@ -137,7 +137,7 @@ gbt_timetz_compress(PG_FUNCTION_ARGS)
r->lower = r->upper = tmp; r->lower = r->upper = tmp;
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(timeKEY), FALSE); entry->offset, FALSE);
} }
else else
retval = entry; retval = entry;
......
...@@ -159,7 +159,7 @@ gbt_tstz_compress(PG_FUNCTION_ARGS) ...@@ -159,7 +159,7 @@ gbt_tstz_compress(PG_FUNCTION_ARGS)
r->lower = r->upper = gmt; r->lower = r->upper = gmt;
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(tsKEY), FALSE); entry->offset, FALSE);
} }
else else
retval = entry; retval = entry;
......
...@@ -46,7 +46,7 @@ gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo * tinfo ...@@ -46,7 +46,7 @@ gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo * tinfo
memcpy((void *) &r[tinfo->size], leaf, tinfo->size); memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
entry->offset, (2 * tinfo->size), FALSE); entry->offset, FALSE);
} }
else else
retval = entry; retval = entry;
......
...@@ -19,7 +19,7 @@ gbt_var_decompress(PG_FUNCTION_ARGS) ...@@ -19,7 +19,7 @@ gbt_var_decompress(PG_FUNCTION_ARGS)
gistentryinit(*retval, PointerGetDatum(key), gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, VARSIZE(key), FALSE); entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
...@@ -292,7 +292,7 @@ gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo * tinfo) ...@@ -292,7 +292,7 @@ gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo * tinfo)
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, VARSIZE(r), TRUE); entry->offset, TRUE);
} }
else else
retval = entry; retval = entry;
......
/****************************************************************************** /******************************************************************************
$PostgreSQL: pgsql/contrib/cube/cube.c,v 1.25 2006/05/30 22:12:12 tgl Exp $ $PostgreSQL: pgsql/contrib/cube/cube.c,v 1.26 2006/06/28 11:59:59 teodor Exp $
This file contains routines that can be bound to a Postgres backend and This file contains routines that can be bound to a Postgres backend and
called by the backend in the process of processing queries. The calling called by the backend in the process of processing queries. The calling
...@@ -300,8 +300,8 @@ g_cube_picksplit(GistEntryVector *entryvec, ...@@ -300,8 +300,8 @@ g_cube_picksplit(GistEntryVector *entryvec,
double size_l, double size_l,
size_r; size_r;
int nbytes; int nbytes;
OffsetNumber seed_1 = 0, OffsetNumber seed_1 = 1,
seed_2 = 0; seed_2 = 2;
OffsetNumber *left, OffsetNumber *left,
*right; *right;
OffsetNumber maxoff; OffsetNumber maxoff;
......
...@@ -154,7 +154,7 @@ g_int_compress(PG_FUNCTION_ARGS) ...@@ -154,7 +154,7 @@ g_int_compress(PG_FUNCTION_ARGS)
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE); entry->rel, entry->page, entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
...@@ -201,7 +201,7 @@ g_int_compress(PG_FUNCTION_ARGS) ...@@ -201,7 +201,7 @@ g_int_compress(PG_FUNCTION_ARGS)
r = resize_intArrayType(r, len); r = resize_intArrayType(r, len);
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE); entry->rel, entry->page, entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
else else
...@@ -238,7 +238,7 @@ g_int_decompress(PG_FUNCTION_ARGS) ...@@ -238,7 +238,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
{ {
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(in), gistentryinit(*retval, PointerGetDatum(in),
entry->rel, entry->page, entry->offset, VARSIZE(in), FALSE); entry->rel, entry->page, entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
...@@ -260,7 +260,7 @@ g_int_decompress(PG_FUNCTION_ARGS) ...@@ -260,7 +260,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
pfree(in); pfree(in);
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE); entry->rel, entry->page, entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
......
...@@ -172,7 +172,7 @@ g_intbig_compress(PG_FUNCTION_ARGS) ...@@ -172,7 +172,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res), gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, res->len, FALSE); entry->offset, FALSE);
if (in != (ArrayType *) PG_DETOAST_DATUM(entry->key)) if (in != (ArrayType *) PG_DETOAST_DATUM(entry->key))
pfree(in); pfree(in);
...@@ -198,7 +198,7 @@ g_intbig_compress(PG_FUNCTION_ARGS) ...@@ -198,7 +198,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res), gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, res->len, FALSE); entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
......
...@@ -108,7 +108,7 @@ _ltree_compress(PG_FUNCTION_ARGS) ...@@ -108,7 +108,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key), gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, key->len, FALSE); entry->offset, FALSE);
} }
else if (!LTG_ISALLTRUE(entry->key)) else if (!LTG_ISALLTRUE(entry->key))
{ {
...@@ -130,7 +130,7 @@ _ltree_compress(PG_FUNCTION_ARGS) ...@@ -130,7 +130,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key), gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, key->len, FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
......
/* /*
* GiST support for ltree * GiST support for ltree
* Teodor Sigaev <teodor@stack.net> * Teodor Sigaev <teodor@stack.net>
* $PostgreSQL: pgsql/contrib/ltree/ltree_gist.c,v 1.14 2006/03/11 04:38:29 momjian Exp $ * $PostgreSQL: pgsql/contrib/ltree/ltree_gist.c,v 1.15 2006/06/28 11:59:59 teodor Exp $
*/ */
#include "ltree.h" #include "ltree.h"
...@@ -81,7 +81,7 @@ ltree_compress(PG_FUNCTION_ARGS) ...@@ -81,7 +81,7 @@ ltree_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key), gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, key->len, FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
...@@ -98,7 +98,7 @@ ltree_decompress(PG_FUNCTION_ARGS) ...@@ -98,7 +98,7 @@ ltree_decompress(PG_FUNCTION_ARGS)
gistentryinit(*retval, PointerGetDatum(key), gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, key->len, FALSE); entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
PG_RETURN_POINTER(entry); PG_RETURN_POINTER(entry);
......
...@@ -103,7 +103,7 @@ gtrgm_compress(PG_FUNCTION_ARGS) ...@@ -103,7 +103,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res), gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, res->len, FALSE); entry->offset, FALSE);
} }
else if (ISSIGNKEY(DatumGetPointer(entry->key)) && else if (ISSIGNKEY(DatumGetPointer(entry->key)) &&
!ISALLTRUE(DatumGetPointer(entry->key))) !ISALLTRUE(DatumGetPointer(entry->key)))
...@@ -126,7 +126,7 @@ gtrgm_compress(PG_FUNCTION_ARGS) ...@@ -126,7 +126,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res), gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, res->len, FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
......
...@@ -316,8 +316,8 @@ gseg_picksplit(GistEntryVector *entryvec, ...@@ -316,8 +316,8 @@ gseg_picksplit(GistEntryVector *entryvec,
float size_l, float size_l,
size_r; size_r;
int nbytes; int nbytes;
OffsetNumber seed_1 = 0, OffsetNumber seed_1 = 1,
seed_2 = 0; seed_2 = 2;
OffsetNumber *left, OffsetNumber *left,
*right; *right;
OffsetNumber maxoff; OffsetNumber maxoff;
......
/* $PostgreSQL: pgsql/contrib/tsearch2/gistidx.c,v 1.13 2006/03/11 04:38:30 momjian Exp $ */ /* $PostgreSQL: pgsql/contrib/tsearch2/gistidx.c,v 1.14 2006/06/28 12:00:06 teodor Exp $ */
#include "postgres.h" #include "postgres.h"
...@@ -202,7 +202,7 @@ gtsvector_compress(PG_FUNCTION_ARGS) ...@@ -202,7 +202,7 @@ gtsvector_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res), gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, res->len, FALSE); entry->offset, FALSE);
} }
else if (ISSIGNKEY(DatumGetPointer(entry->key)) && else if (ISSIGNKEY(DatumGetPointer(entry->key)) &&
!ISALLTRUE(DatumGetPointer(entry->key))) !ISALLTRUE(DatumGetPointer(entry->key)))
...@@ -225,7 +225,7 @@ gtsvector_compress(PG_FUNCTION_ARGS) ...@@ -225,7 +225,7 @@ gtsvector_compress(PG_FUNCTION_ARGS)
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res), gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, res->len, FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
...@@ -242,7 +242,7 @@ gtsvector_decompress(PG_FUNCTION_ARGS) ...@@ -242,7 +242,7 @@ gtsvector_decompress(PG_FUNCTION_ARGS)
gistentryinit(*retval, PointerGetDatum(key), gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, key->len, FALSE); entry->offset, FALSE);
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
} }
......
...@@ -164,7 +164,7 @@ gtsq_compress(PG_FUNCTION_ARGS) ...@@ -164,7 +164,7 @@ gtsq_compress(PG_FUNCTION_ARGS)
gistentryinit(*retval, PointerGetDatum(sign), gistentryinit(*retval, PointerGetDatum(sign),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(TPQTGist), FALSE); entry->offset, FALSE);
} }
PG_RETURN_POINTER(retval); PG_RETURN_POINTER(retval);
......
...@@ -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.15 2005/07/01 19:19:02 tgl Exp $ # $PostgreSQL: pgsql/src/backend/access/gist/Makefile,v 1.16 2006/06/28 12:00:13 teodor Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -13,7 +13,7 @@ top_builddir = ../../../.. ...@@ -13,7 +13,7 @@ top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = gist.o gistutil.o gistxlog.o gistvacuum.o gistget.o gistscan.o \ OBJS = gist.o gistutil.o gistxlog.o gistvacuum.o gistget.o gistscan.o \
gistproc.o gistproc.o gistsplit.o
all: SUBSYS.o all: SUBSYS.o
......
...@@ -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/gist.c,v 1.138 2006/05/29 12:50:06 teodor Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.139 2006/06/28 12:00:14 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -187,7 +187,7 @@ gistbuildCallback(Relation index, ...@@ -187,7 +187,7 @@ gistbuildCallback(Relation index,
/* form an index tuple and point it at the heap tuple */ /* form an index tuple and point it at the heap tuple */
itup = gistFormTuple(&buildstate->giststate, index, itup = gistFormTuple(&buildstate->giststate, index,
values, NULL /* size is currently bogus */, isnull); values, isnull, true /* size is currently bogus */);
itup->t_tid = htup->t_self; itup->t_tid = htup->t_self;
/* /*
...@@ -233,7 +233,7 @@ gistinsert(PG_FUNCTION_ARGS) ...@@ -233,7 +233,7 @@ gistinsert(PG_FUNCTION_ARGS)
initGISTstate(&giststate, r); initGISTstate(&giststate, r);
itup = gistFormTuple(&giststate, r, itup = gistFormTuple(&giststate, r,
values, NULL /* size is currently bogus */, isnull); values, isnull, true /* size is currently bogus */);
itup->t_tid = *ht_ctid; itup->t_tid = *ht_ctid;
gistdoinsert(r, itup, &giststate); gistdoinsert(r, itup, &giststate);
...@@ -899,150 +899,6 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) ...@@ -899,150 +899,6 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate)
gistxlogInsertCompletion(state->r->rd_node, &(state->key), 1); gistxlogInsertCompletion(state->r->rd_node, &(state->key), 1);
} }
/*
* simple split page
*/
static void
gistSplitHalf(GIST_SPLITVEC *v, int len) {
int i;
v->spl_nright = v->spl_nleft = 0;
v->spl_left = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
v->spl_right= (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
for(i = 1; i <= len; i++)
if ( i<len/2 )
v->spl_right[ v->spl_nright++ ] = i;
else
v->spl_left[ v->spl_nleft++ ] = i;
}
/*
* if it was invalid tuple then we need special processing.
* We move all invalid tuples on right page.
*
* if there is no place on left page, gistSplit will be called one more
* time for left page.
*
* Normally, we never exec this code, but after crash replay it's possible
* to get 'invalid' tuples (probability is low enough)
*/
static void
gistSplitByInvalid(GISTSTATE *giststate, GIST_SPLITVEC *v, IndexTuple *itup, int len) {
int i;
static OffsetNumber offInvTuples[ MaxOffsetNumber ];
int nOffInvTuples = 0;
for (i = 1; i <= len; i++)
if ( GistTupleIsInvalid(itup[i - 1]) )
offInvTuples[ nOffInvTuples++ ] = i;
if ( nOffInvTuples == len ) {
/* corner case, all tuples are invalid */
v->spl_rightvalid= v->spl_leftvalid = false;
gistSplitHalf( v, len );
} else {
GistSplitVec gsvp;
v->spl_right = offInvTuples;
v->spl_nright = nOffInvTuples;
v->spl_rightvalid = false;
v->spl_left = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
v->spl_nleft = 0;
for(i = 1; i <= len; i++)
if ( !GistTupleIsInvalid(itup[i - 1]) )
v->spl_left[ v->spl_nleft++ ] = i;
v->spl_leftvalid = true;
gsvp.idgrp = NULL;
gsvp.attrsize = v->spl_lattrsize;
gsvp.attr = v->spl_lattr;
gsvp.len = v->spl_nleft;
gsvp.entries = v->spl_left;
gsvp.isnull = v->spl_lisnull;
gistunionsubkeyvec(giststate, itup, &gsvp, 0);
}
}
/*
* trys to split page by attno key, in a case of null
* values move its to separate page.
*/
static void
gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len, GISTSTATE *giststate,
GIST_SPLITVEC *v, GistEntryVector *entryvec, int attno) {
int i;
static OffsetNumber offNullTuples[ MaxOffsetNumber ];
int nOffNullTuples = 0;
for (i = 1; i <= len; i++) {
Datum datum;
bool IsNull;
if (!GistPageIsLeaf(page) && GistTupleIsInvalid(itup[i - 1])) {
gistSplitByInvalid(giststate, v, itup, len);
return;
}
datum = index_getattr(itup[i - 1], attno+1, giststate->tupdesc, &IsNull);
gistdentryinit(giststate, attno, &(entryvec->vector[i]),
datum, r, page, i,
ATTSIZE(datum, giststate->tupdesc, attno+1, IsNull),
FALSE, IsNull);
if ( IsNull )
offNullTuples[ nOffNullTuples++ ] = i;
}
v->spl_leftvalid = v->spl_rightvalid = true;
if ( nOffNullTuples == len ) {
/*
* Corner case: All keys in attno column are null, we should try to
* by keys in next column. It all keys in all columns
* are NULL just split page half by half
*/
v->spl_risnull[attno] = v->spl_lisnull[attno] = TRUE;
if ( attno+1 == r->rd_att->natts )
gistSplitHalf( v, len );
else
gistSplitByKey(r, page, itup, len, giststate, v, entryvec, attno+1);
} else if ( nOffNullTuples > 0 ) {
int j=0;
/*
* We don't want to mix NULLs and not-NULLs keys
* on one page, so move nulls to right page
*/
v->spl_right = offNullTuples;
v->spl_nright = nOffNullTuples;
v->spl_risnull[attno] = TRUE;
v->spl_left = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
v->spl_nleft = 0;
for(i = 1; i <= len; i++)
if ( j<v->spl_nright && offNullTuples[j] == i )
j++;
else
v->spl_left[ v->spl_nleft++ ] = i;
v->spl_idgrp = NULL;
gistunionsubkey(giststate, itup, v, 0);
} else {
/*
* all keys are not-null
*/
if ( gistUserPicksplit(r, entryvec, attno, v, itup, len, giststate) && attno+1 != r->rd_att->natts )
/*
* Splitting on attno column is not optimized: unions of left and right
* page are the same, we will try to split page by
* following columns
*/
gistSplitByKey(r, page, itup, len, giststate, v, entryvec, attno+1);
}
}
/* /*
* gistSplit -- split a page in the tree and fill struct * gistSplit -- split a page in the tree and fill struct
* used for XLOG and real writes buffers. Function is recursive, ie * used for XLOG and real writes buffers. Function is recursive, ie
...@@ -1057,7 +913,7 @@ gistSplit(Relation r, ...@@ -1057,7 +913,7 @@ gistSplit(Relation r,
{ {
IndexTuple *lvectup, IndexTuple *lvectup,
*rvectup; *rvectup;
GIST_SPLITVEC v; GistSplitVector v;
GistEntryVector *entryvec; GistEntryVector *entryvec;
int i; int i;
SplitedPageLayout *res = NULL; SplitedPageLayout *res = NULL;
...@@ -1066,6 +922,8 @@ gistSplit(Relation r, ...@@ -1066,6 +922,8 @@ gistSplit(Relation r,
entryvec = palloc(GEVHDRSZ + (len + 1) * sizeof(GISTENTRY)); entryvec = palloc(GEVHDRSZ + (len + 1) * sizeof(GISTENTRY));
entryvec->n = len + 1; entryvec->n = len + 1;
memset( v.spl_lisnull, TRUE, sizeof(bool) * giststate->tupdesc->natts );
memset( v.spl_risnull, TRUE, sizeof(bool) * giststate->tupdesc->natts );
gistSplitByKey(r, page, itup, len, giststate, gistSplitByKey(r, page, itup, len, giststate,
&v, entryvec, 0); &v, entryvec, 0);
...@@ -1073,31 +931,31 @@ gistSplit(Relation r, ...@@ -1073,31 +931,31 @@ gistSplit(Relation r,
lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1)); lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1));
rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1)); rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1));
for (i = 0; i < v.spl_nleft; i++) for (i = 0; i < v.splitVector.spl_nleft; i++)
lvectup[i] = itup[v.spl_left[i] - 1]; lvectup[i] = itup[v.splitVector.spl_left[i] - 1];
for (i = 0; i < v.spl_nright; i++) for (i = 0; i < v.splitVector.spl_nright; i++)
rvectup[i] = itup[v.spl_right[i] - 1]; rvectup[i] = itup[v.splitVector.spl_right[i] - 1];
/* finalyze splitting (may need another split) */ /* finalyze splitting (may need another split) */
if (!gistfitpage(rvectup, v.spl_nright)) if (!gistfitpage(rvectup, v.splitVector.spl_nright))
{ {
res = gistSplit(r, page, rvectup, v.spl_nright, giststate); res = gistSplit(r, page, rvectup, v.splitVector.spl_nright, giststate);
} }
else else
{ {
ROTATEDIST(res); ROTATEDIST(res);
res->block.num = v.spl_nright; res->block.num = v.splitVector.spl_nright;
res->list = gistfillitupvec(rvectup, v.spl_nright, &( res->lenlist ) ); res->list = gistfillitupvec(rvectup, v.splitVector.spl_nright, &( res->lenlist ) );
res->itup = (v.spl_rightvalid) ? gistFormTuple(giststate, r, v.spl_rattr, v.spl_rattrsize, v.spl_risnull) res->itup = (v.spl_rightvalid) ? gistFormTuple(giststate, r, v.spl_rattr, v.spl_risnull, false)
: gist_form_invalid_tuple(GIST_ROOT_BLKNO); : gist_form_invalid_tuple(GIST_ROOT_BLKNO);
} }
if (!gistfitpage(lvectup, v.spl_nleft)) if (!gistfitpage(lvectup, v.splitVector.spl_nleft))
{ {
SplitedPageLayout *resptr, *subres; SplitedPageLayout *resptr, *subres;
resptr = subres = gistSplit(r, page, lvectup, v.spl_nleft, giststate); resptr = subres = gistSplit(r, page, lvectup, v.splitVector.spl_nleft, giststate);
/* install on list's tail */ /* install on list's tail */
while( resptr->next ) while( resptr->next )
...@@ -1109,9 +967,9 @@ gistSplit(Relation r, ...@@ -1109,9 +967,9 @@ gistSplit(Relation r,
else else
{ {
ROTATEDIST(res); ROTATEDIST(res);
res->block.num = v.spl_nleft; res->block.num = v.splitVector.spl_nleft;
res->list = gistfillitupvec(lvectup, v.spl_nleft, &( res->lenlist ) ); res->list = gistfillitupvec(lvectup, v.splitVector.spl_nleft, &( res->lenlist ) );
res->itup = (v.spl_leftvalid) ? gistFormTuple(giststate, r, v.spl_lattr, v.spl_lattrsize, v.spl_lisnull) res->itup = (v.spl_leftvalid) ? gistFormTuple(giststate, r, v.spl_lattr, v.spl_lisnull, false)
: gist_form_invalid_tuple(GIST_ROOT_BLKNO); : gist_form_invalid_tuple(GIST_ROOT_BLKNO);
} }
......
...@@ -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.57 2006/05/24 11:01:39 teodor Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.58 2006/06/28 12:00:14 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -391,7 +391,6 @@ gistindex_keytest(IndexTuple tuple, ...@@ -391,7 +391,6 @@ gistindex_keytest(IndexTuple tuple,
gistdentryinit(giststate, key->sk_attno - 1, &de, gistdentryinit(giststate, key->sk_attno - 1, &de,
datum, r, p, offset, datum, r, p, offset,
IndexTupleSize(tuple) - sizeof(IndexTupleData),
FALSE, isNull); FALSE, isNull);
/* /*
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,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/gistproc.c,v 1.5 2006/03/05 15:58:20 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.6 2006/06/28 12:00:14 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -112,6 +112,17 @@ gist_box_consistent(PG_FUNCTION_ARGS) ...@@ -112,6 +112,17 @@ gist_box_consistent(PG_FUNCTION_ARGS)
strategy)); strategy));
} }
static void
adjustBox( BOX *b, BOX *addon ) {
if (b->high.x < addon->high.x)
b->high.x = addon->high.x;
if (b->low.x > addon->low.x)
b->low.x = addon->low.x;
if (b->high.y < addon->high.y)
b->high.y = addon->high.y;
if (b->low.y > addon->low.y)
b->low.y = addon->low.y;
}
/* /*
* The GiST Union method for boxes * The GiST Union method for boxes
...@@ -136,14 +147,7 @@ gist_box_union(PG_FUNCTION_ARGS) ...@@ -136,14 +147,7 @@ gist_box_union(PG_FUNCTION_ARGS)
for (i = 1; i < numranges; i++) for (i = 1; i < numranges; i++)
{ {
cur = DatumGetBoxP(entryvec->vector[i].key); cur = DatumGetBoxP(entryvec->vector[i].key);
if (pageunion->high.x < cur->high.x) adjustBox( pageunion, cur );
pageunion->high.x = cur->high.x;
if (pageunion->low.x > cur->low.x)
pageunion->low.x = cur->low.x;
if (pageunion->high.y < cur->high.y)
pageunion->high.y = cur->high.y;
if (pageunion->low.y > cur->low.y)
pageunion->low.y = cur->low.y;
} }
*sizep = sizeof(BOX); *sizep = sizeof(BOX);
...@@ -206,6 +210,74 @@ compare_KB(const void *a, const void *b) ...@@ -206,6 +210,74 @@ compare_KB(const void *a, const void *b)
return (sa > sb) ? 1 : -1; return (sa > sb) ? 1 : -1;
} }
static void
chooseLR( GIST_SPLITVEC *v,
OffsetNumber *list1, int nlist1, BOX *union1,
OffsetNumber *list2, int nlist2, BOX *union2 )
{
bool firstToLeft = true;
if ( v->spl_ldatum_exists || v->spl_rdatum_exists ) {
if ( v->spl_ldatum_exists && v->spl_rdatum_exists ) {
BOX LRl = *union1, LRr = *union2;
BOX RLl = *union2, RLr = *union1;
double sizeLR, sizeRL;
adjustBox( &LRl, DatumGetBoxP( v->spl_ldatum ) );
adjustBox( &LRr, DatumGetBoxP( v->spl_rdatum ) );
adjustBox( &RLl, DatumGetBoxP( v->spl_ldatum ) );
adjustBox( &RLr, DatumGetBoxP( v->spl_rdatum ) );
sizeLR = size_box( DirectFunctionCall2(rt_box_inter, BoxPGetDatum(&LRl), BoxPGetDatum(&LRr)) );
sizeRL = size_box( DirectFunctionCall2(rt_box_inter, BoxPGetDatum(&RLl), BoxPGetDatum(&RLr)) );
if ( sizeLR > sizeRL )
firstToLeft = false;
} else {
float p1, p2;
GISTENTRY oldUnion, addon;
gistentryinit(oldUnion, ( v->spl_ldatum_exists ) ? v->spl_ldatum : v->spl_rdatum,
NULL, NULL, InvalidOffsetNumber, FALSE);
gistentryinit(addon, BoxPGetDatum(union1), NULL, NULL, InvalidOffsetNumber, FALSE);
DirectFunctionCall3(gist_box_penalty, PointerGetDatum(&oldUnion), PointerGetDatum(&union1), PointerGetDatum(&p1));
gistentryinit(addon, BoxPGetDatum(union2), NULL, NULL, InvalidOffsetNumber, FALSE);
DirectFunctionCall3(gist_box_penalty, PointerGetDatum(&oldUnion), PointerGetDatum(&union2), PointerGetDatum(&p2));
if ( (v->spl_ldatum_exists && p1 > p2) || (v->spl_rdatum_exists && p1 < p2) )
firstToLeft = false;
}
}
if ( firstToLeft ) {
v->spl_left = list1;
v->spl_right = list2;
v->spl_nleft = nlist1;
v->spl_nright = nlist2;
if ( v->spl_ldatum_exists )
adjustBox(union1, DatumGetBoxP( v->spl_ldatum ) );
v->spl_ldatum = BoxPGetDatum(union1);
if ( v->spl_rdatum_exists )
adjustBox(union2, DatumGetBoxP( v->spl_rdatum ) );
v->spl_rdatum = BoxPGetDatum(union2);
} else {
v->spl_left = list2;
v->spl_right = list1;
v->spl_nleft = nlist2;
v->spl_nright = nlist1;
if ( v->spl_ldatum_exists )
adjustBox(union2, DatumGetBoxP( v->spl_ldatum ) );
v->spl_ldatum = BoxPGetDatum(union2);
if ( v->spl_rdatum_exists )
adjustBox(union1, DatumGetBoxP( v->spl_rdatum ) );
v->spl_rdatum = BoxPGetDatum(union1);
}
v->spl_ldatum_exists = v->spl_rdatum_exists = false;
}
/* /*
* The GiST PickSplit method * The GiST PickSplit method
* *
...@@ -255,14 +327,7 @@ gist_box_picksplit(PG_FUNCTION_ARGS) ...@@ -255,14 +327,7 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
)) ))
allisequal = false; allisequal = false;
if (pageunion.high.x < cur->high.x) adjustBox( &pageunion, cur );
pageunion.high.x = cur->high.x;
if (pageunion.low.x > cur->low.x)
pageunion.low.x = cur->low.x;
if (pageunion.high.y < cur->high.y)
pageunion.high.y = cur->high.y;
if (pageunion.low.y > cur->low.y)
pageunion.low.y = cur->low.y;
} }
nbytes = (maxoff + 2) * sizeof(OffsetNumber); nbytes = (maxoff + 2) * sizeof(OffsetNumber);
...@@ -294,9 +359,17 @@ gist_box_picksplit(PG_FUNCTION_ARGS) ...@@ -294,9 +359,17 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
v->spl_nright++; v->spl_nright++;
} }
} }
if ( v->spl_ldatum_exists )
adjustBox( unionL, DatumGetBoxP( v->spl_ldatum ) );
v->spl_ldatum = BoxPGetDatum(unionL); v->spl_ldatum = BoxPGetDatum(unionL);
if ( v->spl_rdatum_exists )
adjustBox( unionR, DatumGetBoxP( v->spl_rdatum ) );
v->spl_rdatum = BoxPGetDatum(unionR); v->spl_rdatum = BoxPGetDatum(unionR);
v->spl_ldatum_exists = v->spl_rdatum_exists = false;
PG_RETURN_POINTER(v); PG_RETURN_POINTER(v);
} }
} }
...@@ -399,23 +472,13 @@ gist_box_picksplit(PG_FUNCTION_ARGS) ...@@ -399,23 +472,13 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
} }
if (direction == 'x') if (direction == 'x')
{ chooseLR( v,
v->spl_left = listL; listL, posL, unionL,
v->spl_right = listR; listR, posR, unionR );
v->spl_nleft = posL;
v->spl_nright = posR;
v->spl_ldatum = BoxPGetDatum(unionL);
v->spl_rdatum = BoxPGetDatum(unionR);
}
else else
{ chooseLR( v,
v->spl_left = listB; listB, posB, unionB,
v->spl_right = listT; listT, posT, unionT );
v->spl_nleft = posB;
v->spl_nright = posT;
v->spl_ldatum = BoxPGetDatum(unionB);
v->spl_rdatum = BoxPGetDatum(unionT);
}
PG_RETURN_POINTER(v); PG_RETURN_POINTER(v);
} }
...@@ -629,14 +692,14 @@ gist_poly_compress(PG_FUNCTION_ARGS) ...@@ -629,14 +692,14 @@ gist_poly_compress(PG_FUNCTION_ARGS)
memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX)); memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX));
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(BOX), FALSE); entry->offset, FALSE);
} }
else else
{ {
gistentryinit(*retval, (Datum) 0, gistentryinit(*retval, (Datum) 0,
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, 0, FALSE); entry->offset, FALSE);
} }
} }
else else
...@@ -700,14 +763,14 @@ gist_circle_compress(PG_FUNCTION_ARGS) ...@@ -700,14 +763,14 @@ gist_circle_compress(PG_FUNCTION_ARGS)
r->low.y = in->center.y - in->radius; r->low.y = in->center.y - in->radius;
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(BOX), FALSE); entry->offset, FALSE);
} }
else else
{ {
gistentryinit(*retval, (Datum) 0, gistentryinit(*retval, (Datum) 0,
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, 0, FALSE); entry->offset, FALSE);
} }
} }
else else
......
This diff is collapsed.
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, 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.53 2006/06/25 01:02:12 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/gist.h,v 1.54 2006/06/28 12:00:14 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -75,37 +75,29 @@ typedef GISTPageOpaqueData *GISTPageOpaque; ...@@ -75,37 +75,29 @@ typedef GISTPageOpaqueData *GISTPageOpaque;
/* /*
* This is the Split Vector to be returned by the PickSplit method. * This is the Split Vector to be returned by the PickSplit method.
* PickSplit should check spl_(r|l)datum_exists. If it is 'true',
* that corresponding spl_(r|l)datum already defined and
* PickSplit should use that value. PickSplit should always set
* spl_(r|l)datum_exists to false: GiST will check value to
* control supportng this feature by PickSplit...
*/ */
typedef struct GIST_SPLITVEC typedef struct GIST_SPLITVEC
{ {
OffsetNumber *spl_left; /* array of entries that go left */ OffsetNumber *spl_left; /* array of entries that go left */
int spl_nleft; /* size of this array */ int spl_nleft; /* size of this array */
Datum spl_ldatum; /* Union of keys in spl_left */ Datum spl_ldatum; /* Union of keys in spl_left */
Datum spl_lattr[INDEX_MAX_KEYS]; /* Union of subkeys in bool spl_ldatum_exists; /* true, if spl_ldatum already exists. */
* spl_left */
int spl_lattrsize[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 */
Datum spl_rdatum; /* Union of keys in spl_right */ Datum spl_rdatum; /* Union of keys in spl_right */
Datum spl_rattr[INDEX_MAX_KEYS]; /* Union of subkeys in bool spl_rdatum_exists; /* true, if spl_rdatum already exists. */
* spl_right */
int spl_rattrsize[INDEX_MAX_KEYS];
bool spl_risnull[INDEX_MAX_KEYS];
bool spl_rightvalid;
int *spl_idgrp;
int *spl_ngrp; /* number in each group */
char *spl_grpflag; /* flags of each group */
} GIST_SPLITVEC; } GIST_SPLITVEC;
/* /*
* An entry on a GiST node. Contains the key, as well as its own * An entry on a GiST node. Contains the key, as well as its own
* location (rel,page,offset) which can supply the matching pointer. * location (rel,page,offset) which can supply the matching pointer.
* The size of the key is in bytes, and leafkey is a flag to tell us * leafkey is a flag to tell us if the entry is in a leaf node.
* if the entry is in a leaf node.
*/ */
typedef struct GISTENTRY typedef struct GISTENTRY
{ {
...@@ -113,7 +105,6 @@ typedef struct GISTENTRY ...@@ -113,7 +105,6 @@ typedef struct GISTENTRY
Relation rel; Relation rel;
Page page; Page page;
OffsetNumber offset; OffsetNumber offset;
int bytes;
bool leafkey; bool leafkey;
} GISTENTRY; } GISTENTRY;
...@@ -147,8 +138,8 @@ typedef struct ...@@ -147,8 +138,8 @@ typedef struct
/* /*
* macro to initialize a GISTENTRY * macro to initialize a GISTENTRY
*/ */
#define gistentryinit(e, k, r, pg, o, b, l) \ #define gistentryinit(e, k, r, pg, o, l) \
do { (e).key = (k); (e).rel = (r); (e).page = (pg); \ do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
(e).offset = (o); (e).bytes = (b); (e).leafkey = (l); } while (0) (e).offset = (o); (e).leafkey = (l); } while (0)
#endif /* GIST_H */ #endif /* GIST_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, 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.17 2006/05/29 12:50:06 teodor Exp $ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.18 2006/06/28 12:00:14 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -180,6 +180,21 @@ typedef struct GISTInsertStack ...@@ -180,6 +180,21 @@ typedef struct GISTInsertStack
struct GISTInsertStack *next; struct GISTInsertStack *next;
} GISTInsertStack; } GISTInsertStack;
typedef struct GistSplitVector {
GIST_SPLITVEC splitVector; /* to/from PickSplit method */
Datum spl_lattr[INDEX_MAX_KEYS]; /* Union of subkeys in spl_left */
bool spl_lisnull[INDEX_MAX_KEYS];
bool spl_leftvalid;
Datum spl_rattr[INDEX_MAX_KEYS]; /* Union of subkeys in spl_right */
bool spl_risnull[INDEX_MAX_KEYS];
bool spl_rightvalid;
bool *spl_equiv; /* equivalent tuples which can be freely
* distributed between left and right pages */
} GistSplitVector;
#define XLogRecPtrIsInvalid( r ) ( (r).xlogid == 0 && (r).xrecoff == 0 ) #define XLogRecPtrIsInvalid( r ) ( (r).xlogid == 0 && (r).xrecoff == 0 )
typedef struct typedef struct
...@@ -206,12 +221,6 @@ typedef struct ...@@ -206,12 +221,6 @@ typedef struct
/* root page of a gist index */ /* root page of a gist index */
#define GIST_ROOT_BLKNO 0 #define GIST_ROOT_BLKNO 0
#define ATTSIZE(datum, tupdesc, i, isnull) \
( \
(isnull) ? 0 : \
att_addlength(0, (tupdesc)->attrs[(i)-1]->attlen, (datum)) \
)
/* /*
* mark tuples on inner pages during recovery * mark tuples on inner pages during recovery
*/ */
...@@ -281,7 +290,7 @@ extern IndexTuple gistgetadjusted(Relation r, ...@@ -281,7 +290,7 @@ extern IndexTuple gistgetadjusted(Relation r,
IndexTuple addtup, IndexTuple addtup,
GISTSTATE *giststate); GISTSTATE *giststate);
extern IndexTuple gistFormTuple(GISTSTATE *giststate, extern IndexTuple gistFormTuple(GISTSTATE *giststate,
Relation r, Datum *attdata, int *datumsize, bool *isnull); Relation r, Datum *attdata, bool *isnull, bool newValues);
extern OffsetNumber gistchoose(Relation r, Page p, extern OffsetNumber gistchoose(Relation r, Page p,
IndexTuple it, IndexTuple it,
...@@ -289,34 +298,34 @@ extern OffsetNumber gistchoose(Relation r, Page p, ...@@ -289,34 +298,34 @@ extern OffsetNumber gistchoose(Relation r, Page p,
extern void gistcentryinit(GISTSTATE *giststate, int nkey, extern void gistcentryinit(GISTSTATE *giststate, int nkey,
GISTENTRY *e, Datum k, GISTENTRY *e, Datum k,
Relation r, Page pg, Relation r, Page pg,
OffsetNumber o, int b, bool l, bool isNull); OffsetNumber o, bool l, bool isNull);
extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r,
IndexTuple tuple, Page p, OffsetNumber o,
GISTENTRY *attdata, bool *isnull);
typedef struct {
int *attrsize;
Datum *attr;
int len;
OffsetNumber *entries;
bool *isnull;
int *idgrp;
} GistSplitVec;
extern void gistunionsubkeyvec(GISTSTATE *giststate,
IndexTuple *itvec, GistSplitVec *gsvp, int startkey);
extern void gistunionsubkey(GISTSTATE *giststate, IndexTuple *itvec,
GIST_SPLITVEC *spl, int attno);
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); bool l, bool isNull);
bool gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GIST_SPLITVEC *v,
IndexTuple *itup, int len, GISTSTATE *giststate); extern float gistpenalty(GISTSTATE *giststate, int attno,
GISTENTRY *key1, bool isNull1,
GISTENTRY *key2, bool isNull2);
extern bool gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startkey,
Datum *attr, bool *isnull );
extern bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b);
extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,
OffsetNumber o, GISTENTRY *attdata, bool *isnull);
extern void gistMakeUnionKey( GISTSTATE *giststate, int attno,
GISTENTRY *entry1, bool isnull1,
GISTENTRY *entry2, bool isnull2,
Datum *dst, bool *dstisnull );
/* gistvacuum.c */ /* gistvacuum.c */
extern Datum gistbulkdelete(PG_FUNCTION_ARGS); extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
extern Datum gistvacuumcleanup(PG_FUNCTION_ARGS); extern Datum gistvacuumcleanup(PG_FUNCTION_ARGS);
/* gistsplit.c */
extern void gistSplitByKey(Relation r, Page page, IndexTuple *itup,
int len, GISTSTATE *giststate,
GistSplitVector *v, GistEntryVector *entryvec,
int attno);
#endif /* GIST_PRIVATE_H */ #endif /* GIST_PRIVATE_H */
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