📄 tsgistidx.c
字号:
/*------------------------------------------------------------------------- * * tsgistidx.c * GiST support functions for tsvector_ops * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/adt/tsgistidx.c,v 1.7 2008/01/01 19:45:52 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/gist.h"#include "access/tuptoaster.h"#include "tsearch/ts_type.h"#include "tsearch/ts_utils.h"#include "utils/pg_crc.h"#define SIGLENINT 31 /* >121 => key will toast, so it will not work * !!! */#define SIGLEN ( sizeof(int4) * SIGLENINT )#define SIGLENBIT (SIGLEN * BITS_PER_BYTE)typedef char BITVEC[SIGLEN];typedef char *BITVECP;#define LOOPBYTE \ for(i=0;i<SIGLEN;i++)#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITS_PER_BYTE ) ) )#define GETBITBYTE(x,i) ( ((char)(x)) >> (i) & 0x01 )#define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITS_PER_BYTE ) )#define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITS_PER_BYTE ) )#define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITS_PER_BYTE )) & 0x01 )#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)#define HASH(sign, val) SETBIT((sign), HASHVAL(val))#define GETENTRY(vec,pos) ((SignTSVector *) DatumGetPointer((vec)->vector[(pos)].key))/* * type of GiST index key */typedef struct{ int32 vl_len_; /* varlena header (do not touch directly!) */ int4 flag; char data[1];} SignTSVector;#define ARRKEY 0x01#define SIGNKEY 0x02#define ALLISTRUE 0x04#define ISARRKEY(x) ( ((SignTSVector*)(x))->flag & ARRKEY )#define ISSIGNKEY(x) ( ((SignTSVector*)(x))->flag & SIGNKEY )#define ISALLTRUE(x) ( ((SignTSVector*)(x))->flag & ALLISTRUE )#define GTHDRSIZE ( VARHDRSZ + sizeof(int4) )#define CALCGTSIZE(flag, len) ( GTHDRSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(int4)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) )#define GETSIGN(x) ( (BITVECP)( (char*)(x)+GTHDRSIZE ) )#define GETARR(x) ( (int4*)( (char*)(x)+GTHDRSIZE ) )#define ARRNELEM(x) ( ( VARSIZE(x) - GTHDRSIZE )/sizeof(int4) )/* Number of one-bits in an unsigned byte */static const uint8 number_of_ones[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};static int4 sizebitvec(BITVECP sign);Datumgtsvectorin(PG_FUNCTION_ARGS){ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("gtsvector_in not implemented"))); PG_RETURN_DATUM(0);}#define SINGOUTSTR "%d true bits, %d false bits"#define ARROUTSTR "%d unique words"#define EXTRALEN ( 2*13 )static int outbuf_maxlen = 0;Datumgtsvectorout(PG_FUNCTION_ARGS){ SignTSVector *key = (SignTSVector *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_POINTER(0))); char *outbuf; if (outbuf_maxlen == 0) outbuf_maxlen = 2 * EXTRALEN + Max(strlen(SINGOUTSTR), strlen(ARROUTSTR)) + 1; outbuf = palloc(outbuf_maxlen); if (ISARRKEY(key)) sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key)); else { int cnttrue = (ISALLTRUE(key)) ? SIGLENBIT : sizebitvec(GETSIGN(key)); sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT - cnttrue); } PG_FREE_IF_COPY(key, 0); PG_RETURN_POINTER(outbuf);}static intcompareint(const void *va, const void *vb){ int4 a = *((int4 *) va); int4 b = *((int4 *) vb); if (a == b) return 0; return (a > b) ? 1 : -1;}/* * Removes duplicates from an array of int4. 'l' is * size of the input array. Returns the new size of the array. */static intuniqueint(int4 *a, int4 l){ int4 *ptr, *res; if (l <= 1) return l; ptr = res = a; qsort((void *) a, l, sizeof(int4), compareint); while (ptr - a < l) if (*ptr != *res) *(++res) = *ptr++; else ptr++; return res + 1 - a;}static voidmakesign(BITVECP sign, SignTSVector *a){ int4 k, len = ARRNELEM(a); int4 *ptr = GETARR(a); MemSet((void *) sign, 0, sizeof(BITVEC)); for (k = 0; k < len; k++) HASH(sign, ptr[k]);}Datumgtsvector_compress(PG_FUNCTION_ARGS){ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval = entry; if (entry->leafkey) { /* tsvector */ SignTSVector *res; TSVector val = DatumGetTSVector(entry->key); int4 len; int4 *arr; WordEntry *ptr = ARRPTR(val); char *words = STRPTR(val); len = CALCGTSIZE(ARRKEY, val->size); res = (SignTSVector *) palloc(len); SET_VARSIZE(res, len); res->flag = ARRKEY; arr = GETARR(res); len = val->size; while (len--) { pg_crc32 c; INIT_CRC32(c); COMP_CRC32(c, words + ptr->pos, ptr->len); FIN_CRC32(c); *arr = *(int4 *) &c; arr++; ptr++; } len = uniqueint(GETARR(res), val->size); if (len != val->size) { /* * there is a collision of hash-function; len is always less than * val->size */ len = CALCGTSIZE(ARRKEY, len); res = (SignTSVector *) repalloc((void *) res, len); SET_VARSIZE(res, len); } /* make signature, if array is too long */ if (VARSIZE(res) > TOAST_INDEX_TARGET) { SignTSVector *ressign; len = CALCGTSIZE(SIGNKEY, 0); ressign = (SignTSVector *) palloc(len); SET_VARSIZE(ressign, len); ressign->flag = SIGNKEY; makesign(GETSIGN(ressign), res); res = ressign; } retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); } else if (ISSIGNKEY(DatumGetPointer(entry->key)) && !ISALLTRUE(DatumGetPointer(entry->key))) { int4 i, len; SignTSVector *res; BITVECP sign = GETSIGN(DatumGetPointer(entry->key)); LOOPBYTE { if ((sign[i] & 0xff) != 0xff) PG_RETURN_POINTER(retval); } len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0); res = (SignTSVector *) palloc(len); SET_VARSIZE(res, len); res->flag = SIGNKEY | ALLISTRUE; retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); } PG_RETURN_POINTER(retval);}Datumgtsvector_decompress(PG_FUNCTION_ARGS){ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); SignTSVector *key = (SignTSVector *) DatumGetPointer(PG_DETOAST_DATUM(entry->key)); if (key != (SignTSVector *) DatumGetPointer(entry->key)) { GISTENTRY *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(key), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry);}typedef struct{ int4 *arrb; int4 *arre;} CHKVAL;/* * is there value 'val' in array or not ? */static boolcheckcondition_arr(void *checkval, QueryOperand *val){ int4 *StopLow = ((CHKVAL *) checkval)->arrb; int4 *StopHigh = ((CHKVAL *) checkval)->arre; int4 *StopMiddle; /* Loop invariant: StopLow <= val < StopHigh */ while (StopLow < StopHigh) { StopMiddle = StopLow + (StopHigh - StopLow) / 2; if (*StopMiddle == val->valcrc) return (true); else if (*StopMiddle < val->valcrc) StopLow = StopMiddle + 1; else StopHigh = StopMiddle; } return (false);}static boolcheckcondition_bit(void *checkval, QueryOperand *val){ return GETBIT(checkval, HASHVAL(val->valcrc));}Datumgtsvector_consistent(PG_FUNCTION_ARGS){ TSQuery query = PG_GETARG_TSQUERY(1); SignTSVector *key = (SignTSVector *) DatumGetPointer( ((GISTENTRY *) PG_GETARG_POINTER(0))->key ); if (!query->size) PG_RETURN_BOOL(false); if (ISSIGNKEY(key)) { if (ISALLTRUE(key)) PG_RETURN_BOOL(true); PG_RETURN_BOOL(TS_execute( GETQUERY(query), (void *) GETSIGN(key), false, checkcondition_bit )); } else { /* only leaf pages */ CHKVAL chkval; chkval.arrb = GETARR(key); chkval.arre = chkval.arrb + ARRNELEM(key); PG_RETURN_BOOL(TS_execute( GETQUERY(query), (void *) &chkval, true, checkcondition_arr )); }}static int4unionkey(BITVECP sbase, SignTSVector *add){ int4 i; if (ISSIGNKEY(add)) { BITVECP sadd = GETSIGN(add); if (ISALLTRUE(add)) return 1; LOOPBYTE sbase[i] |= sadd[i]; } else { int4 *ptr = GETARR(add); for (i = 0; i < ARRNELEM(add); i++) HASH(sbase, ptr[i]); } return 0;}Datumgtsvector_union(PG_FUNCTION_ARGS){ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); int *size = (int *) PG_GETARG_POINTER(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -