1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-24 06:01:07 +03:00

pgindent run.

This commit is contained in:
Bruce Momjian
2002-09-04 20:31:48 +00:00
parent c91ceec21d
commit e50f52a074
446 changed files with 14942 additions and 13363 deletions

View File

@@ -1,5 +1,5 @@
/*
* GiST support for ltree[]
* GiST support for ltree[]
* Teodor Sigaev <teodor@stack.net>
*/
@@ -11,22 +11,27 @@
#include "crc32.h"
PG_FUNCTION_INFO_V1( _ltree_compress );
Datum _ltree_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( _ltree_same );
Datum _ltree_same(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( _ltree_union );
Datum _ltree_union(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( _ltree_penalty );
Datum _ltree_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( _ltree_picksplit );
Datum _ltree_picksplit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( _ltree_consistent );
Datum _ltree_consistent(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_compress);
Datum _ltree_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_same);
Datum _ltree_same(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_union);
Datum _ltree_union(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_penalty);
Datum _ltree_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_picksplit);
Datum _ltree_picksplit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_consistent);
Datum _ltree_consistent(PG_FUNCTION_ARGS);
#define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer(((GISTENTRY *) VARDATA(vec))[(pos)].key))
#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
#define SUMBIT(val) ( \
#define SUMBIT(val) ( \
GETBITBYTE(val,0) + \
GETBITBYTE(val,1) + \
GETBITBYTE(val,2) + \
@@ -34,235 +39,280 @@ Datum _ltree_consistent(PG_FUNCTION_ARGS);
GETBITBYTE(val,4) + \
GETBITBYTE(val,5) + \
GETBITBYTE(val,6) + \
GETBITBYTE(val,7) \
GETBITBYTE(val,7) \
)
#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
static void
hashing(BITVECP sign, ltree *t) {
int tlen = t->numlevel;
hashing(BITVECP sign, ltree * t)
{
int tlen = t->numlevel;
ltree_level *cur = LTREE_FIRST(t);
int hash;
int hash;
while(tlen > 0) {
hash = ltree_crc32_sz( cur->name, cur->len );
AHASH( sign, hash );
while (tlen > 0)
{
hash = ltree_crc32_sz(cur->name, cur->len);
AHASH(sign, hash);
cur = LEVEL_NEXT(cur);
tlen--;
}
}
Datum
_ltree_compress(PG_FUNCTION_ARGS) {
GISTENTRY *entry = (GISTENTRY *)PG_GETARG_POINTER(0);
Datum
_ltree_compress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval = entry;
if ( entry->leafkey ) { /* ltree */
ltree_gist *key;
ArrayType *val = DatumGetArrayTypeP(entry->key);
int4 len = LTG_HDRSIZE + ASIGLEN;
int num=ArrayGetNItems( ARR_NDIM(val), ARR_DIMS(val) );
ltree *item = (ltree*)ARR_DATA_PTR(val);
if (entry->leafkey)
{ /* ltree */
ltree_gist *key;
ArrayType *val = DatumGetArrayTypeP(entry->key);
int4 len = LTG_HDRSIZE + ASIGLEN;
int num = ArrayGetNItems(ARR_NDIM(val), ARR_DIMS(val));
ltree *item = (ltree *) ARR_DATA_PTR(val);
if ( ARR_NDIM(val) != 1 )
elog(ERROR,"Dimension of array != 1");
if (ARR_NDIM(val) != 1)
elog(ERROR, "Dimension of array != 1");
key = (ltree_gist*)palloc( len );
key = (ltree_gist *) palloc(len);
key->len = len;
key->flag = 0;
MemSet( LTG_SIGN(key), 0, sizeof(ASIGLEN) );
while( num>0 ) {
MemSet(LTG_SIGN(key), 0, sizeof(ASIGLEN));
while (num > 0)
{
hashing(LTG_SIGN(key), item);
num--;
item = NEXTVAL(item);
}
if ( PointerGetDatum(val) != entry->key )
if (PointerGetDatum(val) != entry->key)
pfree(val);
retval = (GISTENTRY*)palloc( sizeof(GISTENTRY) );
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page,
entry->offset, key->len, FALSE);
} else {
int4 i,len;
ltree_gist *key;
entry->rel, entry->page,
entry->offset, key->len, FALSE);
}
else
{
int4 i,
len;
ltree_gist *key;
BITVECP sign = LTG_SIGN(DatumGetPointer( entry->key ) );
BITVECP sign = LTG_SIGN(DatumGetPointer(entry->key));
ALOOPBYTE(
if ( sign[i] != 0xff )
PG_RETURN_POINTER(retval);
if (sign[i] != 0xff)
PG_RETURN_POINTER(retval);
);
len = LTG_HDRSIZE;
key = (ltree_gist*)palloc( len );
len = LTG_HDRSIZE;
key = (ltree_gist *) palloc(len);
key->len = len;
key->flag = LTG_ALLTRUE;
retval = (GISTENTRY*)palloc( sizeof(GISTENTRY) );
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page,
entry->offset, key->len, FALSE);
entry->rel, entry->page,
entry->offset, key->len, FALSE);
}
PG_RETURN_POINTER(retval);
}
Datum
_ltree_same(PG_FUNCTION_ARGS) {
ltree_gist* a=(ltree_gist*)PG_GETARG_POINTER(0);
ltree_gist* b=(ltree_gist*)PG_GETARG_POINTER(1);
bool *result = (bool *)PG_GETARG_POINTER(2);
Datum
_ltree_same(PG_FUNCTION_ARGS)
{
ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
if ( LTG_ISALLTRUE(a) && LTG_ISALLTRUE(b) ) {
if (LTG_ISALLTRUE(a) && LTG_ISALLTRUE(b))
*result = true;
} else if ( LTG_ISALLTRUE(a) ) {
else if (LTG_ISALLTRUE(a))
*result = false;
} else if ( LTG_ISALLTRUE(b) ) {
else if (LTG_ISALLTRUE(b))
*result = false;
} else {
int4 i;
BITVECP sa=LTG_SIGN(a), sb=LTG_SIGN(b);
else
{
int4 i;
BITVECP sa = LTG_SIGN(a),
sb = LTG_SIGN(b);
*result = true;
ALOOPBYTE(
if ( sa[i] != sb[i] ) {
*result = false;
break;
}
if (sa[i] != sb[i])
{
*result = false;
break;
}
);
}
PG_RETURN_POINTER(result);
}
PG_RETURN_POINTER(result);
}
static int4
unionkey( BITVECP sbase, ltree_gist *add ) {
int4 i;
BITVECP sadd = LTG_SIGN( add );
static int4
unionkey(BITVECP sbase, ltree_gist * add)
{
int4 i;
BITVECP sadd = LTG_SIGN(add);
if ( LTG_ISALLTRUE(add) )
if (LTG_ISALLTRUE(add))
return 1;
ALOOPBYTE(
sbase[i] |= sadd[i];
sbase[i] |= sadd[i];
);
return 0;
}
Datum
_ltree_union(PG_FUNCTION_ARGS) {
bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int *size = (int *) PG_GETARG_POINTER(1);
ABITVEC base;
int4 len = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
int4 i;
int4 flag = 0;
ltree_gist *result;
Datum
_ltree_union(PG_FUNCTION_ARGS)
{
bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int *size = (int *) PG_GETARG_POINTER(1);
ABITVEC base;
int4 len = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
int4 i;
int4 flag = 0;
ltree_gist *result;
MemSet( (void*)base, 0, sizeof(ABITVEC) );
for(i=0;i<len;i++) {
if ( unionkey( base, GETENTRY(entryvec, i) ) ) {
MemSet((void *) base, 0, sizeof(ABITVEC));
for (i = 0; i < len; i++)
{
if (unionkey(base, GETENTRY(entryvec, i)))
{
flag = LTG_ALLTRUE;
break;
}
}
len = LTG_HDRSIZE + ( ( flag & LTG_ALLTRUE ) ? 0 : ASIGLEN );
result = (ltree_gist*)palloc( len );
len = LTG_HDRSIZE + ((flag & LTG_ALLTRUE) ? 0 : ASIGLEN);
result = (ltree_gist *) palloc(len);
*size = result->len = len;
result->flag = flag;
if ( ! LTG_ISALLTRUE(result) )
memcpy((void*)LTG_SIGN(result), (void*)base, sizeof( ABITVEC ) );
if (!LTG_ISALLTRUE(result))
memcpy((void *) LTG_SIGN(result), (void *) base, sizeof(ABITVEC));
PG_RETURN_POINTER(result);
PG_RETURN_POINTER(result);
}
static int4
sizebitvec( BITVECP sign ) {
int4 size=0, i;
sizebitvec(BITVECP sign)
{
int4 size = 0,
i;
ALOOPBYTE(
size += SUMBIT(*(char*)sign);
sign = (BITVECP) ( ((char*)sign) + 1 );
size += SUMBIT(*(char *) sign);
sign = (BITVECP) (((char *) sign) + 1);
);
return size;
}
Datum
_ltree_penalty(PG_FUNCTION_ARGS) {
ltree_gist *origval = (ltree_gist*)DatumGetPointer( ( (GISTENTRY *)PG_GETARG_POINTER(0) )->key );
ltree_gist *newval = (ltree_gist*)DatumGetPointer( ( (GISTENTRY *)PG_GETARG_POINTER(1) )->key );
float *penalty = (float *) PG_GETARG_POINTER(2);
BITVECP orig = LTG_SIGN(origval);
Datum
_ltree_penalty(PG_FUNCTION_ARGS)
{
ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
float *penalty = (float *) PG_GETARG_POINTER(2);
BITVECP orig = LTG_SIGN(origval);
if ( LTG_ISALLTRUE(origval) ) {
if (LTG_ISALLTRUE(origval))
{
*penalty = 0.0;
PG_RETURN_POINTER( penalty );
PG_RETURN_POINTER(penalty);
}
if ( LTG_ISALLTRUE(newval) ) {
*penalty = (float) (ASIGLENBIT - sizebitvec( orig ) );
} else {
if (LTG_ISALLTRUE(newval))
*penalty = (float) (ASIGLENBIT - sizebitvec(orig));
else
{
unsigned char valtmp;
BITVECP nval = LTG_SIGN(newval);
int4 i, unionsize=0;
BITVECP nval = LTG_SIGN(newval);
int4 i,
unionsize = 0;
ALOOPBYTE(
valtmp = nval[i] | orig[i];
unionsize += SUMBIT(valtmp) - SUMBIT(orig[i]);
valtmp = nval[i] | orig[i];
unionsize += SUMBIT(valtmp) - SUMBIT(orig[i]);
);
*penalty = (float)unionsize;
*penalty = (float) unionsize;
}
PG_RETURN_POINTER( penalty );
PG_RETURN_POINTER(penalty);
}
typedef struct {
OffsetNumber pos;
int4 cost;
typedef struct
{
OffsetNumber pos;
int4 cost;
} SPLITCOST;
static int
comparecost( const void *a, const void *b ) {
return ((SPLITCOST*)a)->cost - ((SPLITCOST*)b)->cost;
comparecost(const void *a, const void *b)
{
return ((SPLITCOST *) a)->cost - ((SPLITCOST *) b)->cost;
}
Datum
_ltree_picksplit(PG_FUNCTION_ARGS) {
bytea *entryvec = (bytea*) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC*) PG_GETARG_POINTER(1);
OffsetNumber k,j;
ltree_gist *datum_l, *datum_r;
ABITVEC union_l, union_r;
bool firsttime = true;
int4 size_alpha,size_beta,sizeu,sizei;
int4 size_waste, waste = 0.0;
int4 size_l, size_r;
int4 nbytes;
OffsetNumber seed_1=0, seed_2=0;
OffsetNumber *left, *right;
Datum
_ltree_picksplit(PG_FUNCTION_ARGS)
{
bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
OffsetNumber k,
j;
ltree_gist *datum_l,
*datum_r;
ABITVEC union_l,
union_r;
bool firsttime = true;
int4 size_alpha,
size_beta,
sizeu,
sizei;
int4 size_waste,
waste = 0.0;
int4 size_l,
size_r;
int4 nbytes;
OffsetNumber seed_1 = 0,
seed_2 = 0;
OffsetNumber *left,
*right;
OffsetNumber maxoff;
BITVECP ptra, ptrb, ptrc;
int i;
unsigned char valtmp;
SPLITCOST *costvector;
ltree_gist *_k, *_j;
BITVECP ptra,
ptrb,
ptrc;
int i;
unsigned char valtmp;
SPLITCOST *costvector;
ltree_gist *_k,
*_j;
maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 2;
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
v->spl_left = (OffsetNumber *) palloc(nbytes);
v->spl_right = (OffsetNumber *) palloc(nbytes);
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k)) {
_k = GETENTRY(entryvec,k);
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j)) {
_j = GETENTRY(entryvec,j);
if ( LTG_ISALLTRUE(_k) || LTG_ISALLTRUE(_j) ) {
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
{
_k = GETENTRY(entryvec, k);
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
{
_j = GETENTRY(entryvec, j);
if (LTG_ISALLTRUE(_k) || LTG_ISALLTRUE(_j))
{
sizeu = ASIGLENBIT;
if ( LTG_ISALLTRUE(_k) && LTG_ISALLTRUE(_j) )
if (LTG_ISALLTRUE(_k) && LTG_ISALLTRUE(_j))
sizei = ASIGLENBIT;
else
sizei = ( LTG_ISALLTRUE(_k) ) ?
sizebitvec( LTG_SIGN(_j) ) : sizebitvec( LTG_SIGN(_k) );
} else {
sizei = (LTG_ISALLTRUE(_k)) ?
sizebitvec(LTG_SIGN(_j)) : sizebitvec(LTG_SIGN(_k));
}
else
{
sizeu = sizei = 0;
ptra = LTG_SIGN(_j);
ptrb = LTG_SIGN(_k);
@@ -278,20 +328,21 @@ _ltree_picksplit(PG_FUNCTION_ARGS) {
} while(0)
ALOOPBYTE(
COUNT(0);
COUNT(1);
COUNT(2);
COUNT(3);
COUNT(4);
COUNT(5);
COUNT(6);
COUNT(7);
ptra = (BITVECP) ( ((char*)ptra) + 1 );
ptrb = (BITVECP) ( ((char*)ptrb) + 1 );
COUNT(0);
COUNT(1);
COUNT(2);
COUNT(3);
COUNT(4);
COUNT(5);
COUNT(6);
COUNT(7);
ptra = (BITVECP) (((char *) ptra) + 1);
ptrb = (BITVECP) (((char *) ptrb) + 1);
);
}
size_waste = sizeu - sizei;
if (size_waste > waste || firsttime) {
if (size_waste > waste || firsttime)
{
waste = size_waste;
seed_1 = k;
seed_2 = j;
@@ -305,129 +356,166 @@ _ltree_picksplit(PG_FUNCTION_ARGS) {
right = v->spl_right;
v->spl_nright = 0;
if ( seed_1 == 0 || seed_2 == 0 ) {
if (seed_1 == 0 || seed_2 == 0)
{
seed_1 = 1;
seed_2 = 2;
}
/* form initial .. */
if ( LTG_ISALLTRUE(GETENTRY(entryvec,seed_1)) ) {
datum_l = (ltree_gist*)palloc( LTG_HDRSIZE );
datum_l->len = LTG_HDRSIZE; datum_l->flag = LTG_ALLTRUE;
if (LTG_ISALLTRUE(GETENTRY(entryvec, seed_1)))
{
datum_l = (ltree_gist *) palloc(LTG_HDRSIZE);
datum_l->len = LTG_HDRSIZE;
datum_l->flag = LTG_ALLTRUE;
size_l = ASIGLENBIT;
} else {
datum_l = (ltree_gist*)palloc( LTG_HDRSIZE + ASIGLEN );
datum_l->len = LTG_HDRSIZE + ASIGLEN; datum_l->flag = 0;
memcpy((void*)LTG_SIGN(datum_l), (void*)LTG_SIGN(GETENTRY(entryvec,seed_1)), sizeof(ABITVEC));
size_l = sizebitvec( LTG_SIGN(datum_l) );
}
if ( LTG_ISALLTRUE(GETENTRY(entryvec,seed_2)) ) {
datum_r = (ltree_gist*)palloc( LTG_HDRSIZE );
datum_r->len = LTG_HDRSIZE; datum_r->flag = LTG_ALLTRUE;
else
{
datum_l = (ltree_gist *) palloc(LTG_HDRSIZE + ASIGLEN);
datum_l->len = LTG_HDRSIZE + ASIGLEN;
datum_l->flag = 0;
memcpy((void *) LTG_SIGN(datum_l), (void *) LTG_SIGN(GETENTRY(entryvec, seed_1)), sizeof(ABITVEC));
size_l = sizebitvec(LTG_SIGN(datum_l));
}
if (LTG_ISALLTRUE(GETENTRY(entryvec, seed_2)))
{
datum_r = (ltree_gist *) palloc(LTG_HDRSIZE);
datum_r->len = LTG_HDRSIZE;
datum_r->flag = LTG_ALLTRUE;
size_r = ASIGLENBIT;
} else {
datum_r = (ltree_gist*)palloc( LTG_HDRSIZE + ASIGLEN );
datum_r->len = LTG_HDRSIZE + ASIGLEN; datum_r->flag = 0;
memcpy((void*)LTG_SIGN(datum_r), (void*)LTG_SIGN(GETENTRY(entryvec,seed_2)), sizeof(ABITVEC));
size_r = sizebitvec( LTG_SIGN(datum_r) );
}
else
{
datum_r = (ltree_gist *) palloc(LTG_HDRSIZE + ASIGLEN);
datum_r->len = LTG_HDRSIZE + ASIGLEN;
datum_r->flag = 0;
memcpy((void *) LTG_SIGN(datum_r), (void *) LTG_SIGN(GETENTRY(entryvec, seed_2)), sizeof(ABITVEC));
size_r = sizebitvec(LTG_SIGN(datum_r));
}
maxoff = OffsetNumberNext(maxoff);
/* sort before ... */
costvector=(SPLITCOST*)palloc( sizeof(SPLITCOST)*maxoff );
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j)) {
costvector[j-1].pos = j;
_j = GETENTRY(entryvec,j);
if ( LTG_ISALLTRUE(_j) ) {
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
{
costvector[j - 1].pos = j;
_j = GETENTRY(entryvec, j);
if (LTG_ISALLTRUE(_j))
{
size_alpha = ASIGLENBIT - size_l;
size_beta = ASIGLENBIT - size_r;
} else {
ptra = LTG_SIGN( datum_l );
ptrb = LTG_SIGN( datum_r );
ptrc = LTG_SIGN( _j );
size_beta = ASIGLENBIT - size_r;
}
else
{
ptra = LTG_SIGN(datum_l);
ptrb = LTG_SIGN(datum_r);
ptrc = LTG_SIGN(_j);
size_beta = size_alpha = 0;
if ( LTG_ISALLTRUE(datum_l) ) {
if ( !LTG_ISALLTRUE(datum_r) ) {
if (LTG_ISALLTRUE(datum_l))
{
if (!LTG_ISALLTRUE(datum_r))
{
ALOOPBIT(
if ( GETBIT(ptrc,i) && ! GETBIT(ptrb,i) )
size_beta++;
if (GETBIT(ptrc, i) && !GETBIT(ptrb, i))
size_beta++;
);
}
} else if ( LTG_ISALLTRUE(datum_r) ) {
if ( !LTG_ISALLTRUE(datum_l) ) {
}
else if (LTG_ISALLTRUE(datum_r))
{
if (!LTG_ISALLTRUE(datum_l))
{
ALOOPBIT(
if ( GETBIT(ptrc,i) && ! GETBIT(ptra,i) )
size_alpha++;
if (GETBIT(ptrc, i) && !GETBIT(ptra, i))
size_alpha++;
);
}
} else {
}
else
{
ALOOPBIT(
if ( GETBIT(ptrc,i) && ! GETBIT(ptra,i) )
size_alpha++;
if ( GETBIT(ptrc,i) && ! GETBIT(ptrb,i) )
size_beta++;
if (GETBIT(ptrc, i) && !GETBIT(ptra, i))
size_alpha++;
if (GETBIT(ptrc, i) && !GETBIT(ptrb, i))
size_beta++;
);
}
}
costvector[j-1].cost = abs( size_alpha - size_beta );
costvector[j - 1].cost = abs(size_alpha - size_beta);
}
qsort( (void*)costvector, maxoff, sizeof(SPLITCOST), comparecost );
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
for (k = 0; k < maxoff; k++) {
for (k = 0; k < maxoff; k++)
{
j = costvector[k].pos;
_j = GETENTRY(entryvec,j);
if ( j == seed_1 ) {
_j = GETENTRY(entryvec, j);
if (j == seed_1)
{
*left++ = j;
v->spl_nleft++;
continue;
} else if ( j == seed_2 ) {
}
else if (j == seed_2)
{
*right++ = j;
v->spl_nright++;
continue;
}
if ( LTG_ISALLTRUE(datum_l) || LTG_ISALLTRUE(_j) ) {
if (LTG_ISALLTRUE(datum_l) || LTG_ISALLTRUE(_j))
size_alpha = ASIGLENBIT;
} else {
else
{
ptra = LTG_SIGN(_j);
ptrb = LTG_SIGN(datum_l);
size_alpha = 0;
ALOOPBYTE(
valtmp = union_l[i] = ptra[i] | ptrb[i];
size_alpha += SUMBIT( valtmp );
valtmp = union_l[i] = ptra[i] | ptrb[i];
size_alpha += SUMBIT(valtmp);
);
}
if ( LTG_ISALLTRUE(datum_r) || LTG_ISALLTRUE(_j) ) {
if (LTG_ISALLTRUE(datum_r) || LTG_ISALLTRUE(_j))
size_beta = ASIGLENBIT;
} else {
else
{
ptra = LTG_SIGN(_j);
ptrb = LTG_SIGN(datum_r);
size_beta = 0;
ALOOPBYTE(
valtmp = union_r[i] = ptra[i] | ptrb[i];
size_beta += SUMBIT( valtmp );
valtmp = union_r[i] = ptra[i] | ptrb[i];
size_beta += SUMBIT(valtmp);
);
}
if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.1)) {
if ( ! LTG_ISALLTRUE( datum_l ) ) {
if ( size_alpha == ASIGLENBIT ) {
if ( size_alpha != size_l )
MemSet( (void*)LTG_SIGN(datum_l),0xff, sizeof(ABITVEC));
} else
memcpy( (void*)LTG_SIGN(datum_l), (void*)union_l, sizeof(ABITVEC) );
if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
{
if (!LTG_ISALLTRUE(datum_l))
{
if (size_alpha == ASIGLENBIT)
{
if (size_alpha != size_l)
MemSet((void *) LTG_SIGN(datum_l), 0xff, sizeof(ABITVEC));
}
else
memcpy((void *) LTG_SIGN(datum_l), (void *) union_l, sizeof(ABITVEC));
}
size_l = size_alpha;
*left++ = j;
v->spl_nleft++;
} else {
if ( ! LTG_ISALLTRUE( datum_r ) ) {
if ( size_beta == ASIGLENBIT ) {
if ( size_beta != size_r )
MemSet( (void*)LTG_SIGN(datum_r),0xff, sizeof(ABITVEC));
} else
memcpy( (void*)LTG_SIGN(datum_r), (void*)union_r, sizeof(ABITVEC) );
}
else
{
if (!LTG_ISALLTRUE(datum_r))
{
if (size_beta == ASIGLENBIT)
{
if (size_beta != size_r)
MemSet((void *) LTG_SIGN(datum_r), 0xff, sizeof(ABITVEC));
}
else
memcpy((void *) LTG_SIGN(datum_r), (void *) union_r, sizeof(ABITVEC));
}
size_r = size_beta;
*right++ = j;
@@ -441,23 +529,25 @@ _ltree_picksplit(PG_FUNCTION_ARGS) {
v->spl_ldatum = PointerGetDatum(datum_l);
v->spl_rdatum = PointerGetDatum(datum_r);
PG_RETURN_POINTER( v );
PG_RETURN_POINTER(v);
}
static bool
gist_te(ltree_gist *key, ltree* query) {
ltree_level *curq = LTREE_FIRST(query);
BITVECP sign = LTG_SIGN(key);
int qlen = query->numlevel;
gist_te(ltree_gist * key, ltree * query)
{
ltree_level *curq = LTREE_FIRST(query);
BITVECP sign = LTG_SIGN(key);
int qlen = query->numlevel;
unsigned int hv;
if ( LTG_ISALLTRUE(key) )
if (LTG_ISALLTRUE(key))
return true;
while( qlen>0 ) {
hv = ltree_crc32_sz(curq->name,curq->len);
if ( ! GETBIT( sign, AHASHVAL(hv) ) )
return false;
while (qlen > 0)
{
hv = ltree_crc32_sz(curq->name, curq->len);
if (!GETBIT(sign, AHASHVAL(hv)))
return false;
curq = LEVEL_NEXT(curq);
qlen--;
}
@@ -466,48 +556,56 @@ gist_te(ltree_gist *key, ltree* query) {
}
static bool
checkcondition_bit(void *checkval, ITEM* val ) {
return ( FLG_CANLOOKSIGN(val->flag) ) ? GETBIT( checkval, AHASHVAL( val->val ) ) : true;
checkcondition_bit(void *checkval, ITEM * val)
{
return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(checkval, AHASHVAL(val->val)) : true;
}
static bool
gist_qtxt(ltree_gist *key, ltxtquery* query) {
if ( LTG_ISALLTRUE(key) )
gist_qtxt(ltree_gist * key, ltxtquery * query)
{
if (LTG_ISALLTRUE(key))
return true;
return ltree_execute(
GETQUERY(query),
(void*)LTG_SIGN(key), false,
checkcondition_bit
);
GETQUERY(query),
(void *) LTG_SIGN(key), false,
checkcondition_bit
);
}
static bool
gist_qe(ltree_gist *key, lquery* query) {
lquery_level *curq = LQUERY_FIRST(query);
BITVECP sign = LTG_SIGN(key);
int qlen = query->numlevel;
if ( LTG_ISALLTRUE(key) )
gist_qe(ltree_gist * key, lquery * query)
{
lquery_level *curq = LQUERY_FIRST(query);
BITVECP sign = LTG_SIGN(key);
int qlen = query->numlevel;
if (LTG_ISALLTRUE(key))
return true;
while( qlen>0 ) {
if ( curq->numvar && LQL_CANLOOKSIGN(curq) ) {
bool isexist=false;
int vlen = curq->numvar;
while (qlen > 0)
{
if (curq->numvar && LQL_CANLOOKSIGN(curq))
{
bool isexist = false;
int vlen = curq->numvar;
lquery_variant *curv = LQL_FIRST(curq);
while( vlen>0 ) {
if ( GETBIT( sign, AHASHVAL( curv->val ) ) ) {
isexist=true;
while (vlen > 0)
{
if (GETBIT(sign, AHASHVAL(curv->val)))
{
isexist = true;
break;
}
curv = LVAR_NEXT(curv);
vlen--;
}
if ( !isexist )
if (!isexist)
return false;
}
curq = LQL_NEXT(curq);
qlen--;
}
@@ -516,34 +614,35 @@ gist_qe(ltree_gist *key, lquery* query) {
}
Datum
_ltree_consistent(PG_FUNCTION_ARGS) {
GISTENTRY *entry = (GISTENTRY*)PG_GETARG_POINTER(0);
char *query = (char*)DatumGetPointer( PG_DETOAST_DATUM(PG_GETARG_DATUM(1)) );
ltree_gist *key = (ltree_gist*)DatumGetPointer( entry->key );
Datum
_ltree_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
char *query = (char *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
bool res = false;
bool res = false;
#ifndef assert_enabled
#ifndef assert_enabled
#define assert_enabled 0
#endif
switch( strategy ) {
switch (strategy)
{
case 10:
case 11:
res = gist_te(key, (ltree*)query);
res = gist_te(key, (ltree *) query);
break;
case 12:
case 13:
res = gist_qe(key, (lquery*)query);
break;
res = gist_qe(key, (lquery *) query);
break;
case 14:
case 15:
res = gist_qtxt(key, (ltxtquery*)query);
break;
res = gist_qtxt(key, (ltxtquery *) query);
break;
default:
elog(ERROR,"Unknown StrategyNumber: %d", strategy);
elog(ERROR, "Unknown StrategyNumber: %d", strategy);
}
PG_RETURN_BOOL(res);
}

View File

@@ -1,5 +1,5 @@
/*
* op function for ltree[]
* op function for ltree[]
* Teodor Sigaev <teodor@stack.net>
*/
@@ -16,223 +16,253 @@ PG_FUNCTION_INFO_V1(_ltq_rregex);
PG_FUNCTION_INFO_V1(_ltxtq_exec);
PG_FUNCTION_INFO_V1(_ltxtq_rexec);
Datum _ltree_r_isparent(PG_FUNCTION_ARGS);
Datum _ltree_r_risparent(PG_FUNCTION_ARGS);
Datum _ltree_r_isparent(PG_FUNCTION_ARGS);
Datum _ltree_r_risparent(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
PG_FUNCTION_INFO_V1(_ltq_extract_regex);
PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
Datum _ltree_extract_isparent(PG_FUNCTION_ARGS);
Datum _ltree_extract_risparent(PG_FUNCTION_ARGS);
Datum _ltq_extract_regex(PG_FUNCTION_ARGS);
Datum _ltxtq_extract_exec(PG_FUNCTION_ARGS);
Datum _ltree_extract_isparent(PG_FUNCTION_ARGS);
Datum _ltree_extract_risparent(PG_FUNCTION_ARGS);
Datum _ltq_extract_regex(PG_FUNCTION_ARGS);
Datum _ltxtq_extract_exec(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(_lca);
Datum _lca(PG_FUNCTION_ARGS);
Datum _lca(PG_FUNCTION_ARGS);
typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
typedef Datum (*PGCALL2)(PG_FUNCTION_ARGS);
#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
static bool
array_iterator( ArrayType *la, PGCALL2 callback, void* param, ltree ** found) {
int num=ArrayGetNItems( ARR_NDIM(la), ARR_DIMS(la));
ltree *item = (ltree*)ARR_DATA_PTR(la);
array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree ** found)
{
int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
ltree *item = (ltree *) ARR_DATA_PTR(la);
if ( ARR_NDIM(la) !=1 )
elog(ERROR,"Dimension of array != 1");
if (ARR_NDIM(la) != 1)
elog(ERROR, "Dimension of array != 1");
if ( found )
*found=NULL;
while( num>0 ) {
if ( DatumGetBool( DirectFunctionCall2( callback,
PointerGetDatum(item), PointerGetDatum(param) ) ) ) {
if (found)
*found = NULL;
while (num > 0)
{
if (DatumGetBool(DirectFunctionCall2(callback,
PointerGetDatum(item), PointerGetDatum(param))))
{
if ( found )
if (found)
*found = item;
return true;
}
num--;
item = NEXTVAL(item);
item = NEXTVAL(item);
}
return false;
}
Datum
_ltree_isparent(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
bool res = array_iterator( la, ltree_isparent, (void*)query, NULL );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
_ltree_isparent(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
bool res = array_iterator(la, ltree_isparent, (void *) query, NULL);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(res);
}
Datum
_ltree_r_isparent(PG_FUNCTION_ARGS) {
PG_RETURN_DATUM( DirectFunctionCall2( _ltree_isparent,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
) );
_ltree_r_isparent(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
));
}
Datum
_ltree_risparent(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
bool res = array_iterator( la, ltree_risparent, (void*)query, NULL );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
_ltree_risparent(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
bool res = array_iterator(la, ltree_risparent, (void *) query, NULL);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(res);
}
Datum
_ltree_r_risparent(PG_FUNCTION_ARGS) {
PG_RETURN_DATUM( DirectFunctionCall2( _ltree_risparent,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
) );
_ltree_r_risparent(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
));
}
Datum
_ltq_regex(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
lquery *query = PG_GETARG_LQUERY(1);
bool res = array_iterator( la, ltq_regex, (void*)query, NULL );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
_ltq_regex(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
lquery *query = PG_GETARG_LQUERY(1);
bool res = array_iterator(la, ltq_regex, (void *) query, NULL);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(res);
}
Datum
_ltq_rregex(PG_FUNCTION_ARGS) {
PG_RETURN_DATUM( DirectFunctionCall2( _ltq_regex,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
) );
_ltq_rregex(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
));
}
Datum
_ltxtq_exec(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
bool res = array_iterator( la, ltxtq_exec, (void*)query, NULL );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
Datum
_ltxtq_exec(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
bool res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(res);
}
Datum
_ltxtq_rexec(PG_FUNCTION_ARGS) {
PG_RETURN_DATUM( DirectFunctionCall2( _ltxtq_exec,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
) );
_ltxtq_rexec(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
));
}
Datum
_ltree_extract_isparent(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
ltree *found,*item;
Datum
_ltree_extract_isparent(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
ltree *found,
*item;
if ( !array_iterator( la, ltree_isparent, (void*)query, &found ) ) {
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
if (!array_iterator(la, ltree_isparent, (void *) query, &found))
{
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_NULL();
}
item = (ltree*)palloc( found->len );
memcpy( item, found, found->len );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_POINTER(item);
}
item = (ltree *) palloc(found->len);
memcpy(item, found, found->len);
Datum
_ltree_extract_risparent(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
ltree *found,*item;
if ( !array_iterator( la, ltree_risparent, (void*)query, &found ) ) {
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_NULL();
}
item = (ltree*)palloc( found->len );
memcpy( item, found, found->len );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_POINTER(item);
}
Datum
_ltq_extract_regex(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
lquery *query = PG_GETARG_LQUERY(1);
ltree *found,*item;
if ( !array_iterator( la, ltq_regex, (void*)query, &found ) ) {
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_NULL();
}
item = (ltree*)palloc( found->len );
memcpy( item, found, found->len );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_POINTER(item);
}
Datum
_ltxtq_extract_exec(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
ltree *found,*item;
if ( !array_iterator( la, ltxtq_exec, (void*)query, &found ) ) {
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_NULL();
}
item = (ltree*)palloc( found->len );
memcpy( item, found, found->len );
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(query,1);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_POINTER(item);
}
Datum
_lca(PG_FUNCTION_ARGS) {
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
int num=ArrayGetNItems( ARR_NDIM(la), ARR_DIMS(la));
ltree *item = (ltree*)ARR_DATA_PTR(la);
ltree **a,*res;
_ltree_extract_risparent(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltree *query = PG_GETARG_LTREE(1);
ltree *found,
*item;
a=(ltree**)palloc( sizeof(ltree*) * num );
while( num>0 ) {
if (!array_iterator(la, ltree_risparent, (void *) query, &found))
{
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_NULL();
}
item = (ltree *) palloc(found->len);
memcpy(item, found, found->len);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_POINTER(item);
}
Datum
_ltq_extract_regex(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
lquery *query = PG_GETARG_LQUERY(1);
ltree *found,
*item;
if (!array_iterator(la, ltq_regex, (void *) query, &found))
{
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_NULL();
}
item = (ltree *) palloc(found->len);
memcpy(item, found, found->len);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_POINTER(item);
}
Datum
_ltxtq_extract_exec(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
ltree *found,
*item;
if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
{
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_NULL();
}
item = (ltree *) palloc(found->len);
memcpy(item, found, found->len);
PG_FREE_IF_COPY(la, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_POINTER(item);
}
Datum
_lca(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
ltree *item = (ltree *) ARR_DATA_PTR(la);
ltree **a,
*res;
a = (ltree **) palloc(sizeof(ltree *) * num);
while (num > 0)
{
num--;
a[num] = item;
item = NEXTVAL(item);
}
res = lca_inner(a, ArrayGetNItems( ARR_NDIM(la), ARR_DIMS(la)));
res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
pfree(a);
PG_FREE_IF_COPY(la,0);
PG_FREE_IF_COPY(la, 0);
if ( res )
PG_RETURN_POINTER(res);
else
PG_RETURN_NULL();
if (res)
PG_RETURN_POINTER(res);
else
PG_RETURN_NULL();
}

View File

@@ -105,6 +105,6 @@ ltree_crc32_sz(char *buf, int size)
len = 0;
nr = size;
for (len += nr, p = buf; nr--; ++p)
_CRC32_(crc, TOLOWER((unsigned int)*p));
_CRC32_(crc, TOLOWER((unsigned int) *p));
return ~crc;
}

View File

@@ -1,5 +1,5 @@
/*
* op function for ltree and lquery
* op function for ltree and lquery
* Teodor Sigaev <teodor@stack.net>
*/
@@ -9,27 +9,29 @@
PG_FUNCTION_INFO_V1(ltq_regex);
PG_FUNCTION_INFO_V1(ltq_rregex);
typedef struct {
lquery_level *q;
int nq;
ltree_level *t;
int nt;
int posq;
int post;
} FieldNot;
typedef struct
{
lquery_level *q;
int nq;
ltree_level *t;
int nt;
int posq;
int post;
} FieldNot;
static char *
getlexem(char *start, char *end, int *len) {
char *ptr;
while( start<end && *start == '_' )
getlexem(char *start, char *end, int *len)
{
char *ptr;
while (start < end && *start == '_')
start++;
ptr = start;
if ( ptr == end )
if (ptr == end)
return NULL;
while( ptr < end && *ptr != '_')
while (ptr < end && *ptr != '_')
ptr++;
*len = ptr - start;
@@ -37,31 +39,36 @@ getlexem(char *start, char *end, int *len) {
}
bool
compare_subnode( ltree_level *t, char *qn, int len, int (*cmpptr)(const char *,const char *,size_t), bool anyend ) {
char *endt = t->name + t->len;
char *endq = qn + len;
char *tn;
int lent,lenq;
bool isok;
compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend)
{
char *endt = t->name + t->len;
char *endq = qn + len;
char *tn;
int lent,
lenq;
bool isok;
while( (qn=getlexem(qn,endq,&lenq)) != NULL ) {
tn=t->name;
while ((qn = getlexem(qn, endq, &lenq)) != NULL)
{
tn = t->name;
isok = false;
while( (tn=getlexem(tn,endt,&lent)) != NULL ) {
if (
while ((tn = getlexem(tn, endt, &lent)) != NULL)
{
if (
(
lent == lenq ||
( lent > lenq && anyend )
) &&
(*cmpptr)(qn,tn,lenq) == 0 ) {
isok = true;
lent == lenq ||
(lent > lenq && anyend)
) &&
(*cmpptr) (qn, tn, lenq) == 0)
{
isok = true;
break;
}
tn += lent;
}
if ( !isok )
if (!isok)
return false;
qn += lenq;
}
@@ -70,27 +77,32 @@ compare_subnode( ltree_level *t, char *qn, int len, int (*cmpptr)(const char *,c
}
static bool
checkLevel( lquery_level *curq, ltree_level *curt ) {
int (*cmpptr)(const char *,const char *,size_t);
checkLevel(lquery_level * curq, ltree_level * curt)
{
int (*cmpptr) (const char *, const char *, size_t);
lquery_variant *curvar = LQL_FIRST(curq);
int i;
for(i=0;i<curq->numvar;i++) {
cmpptr = ( curvar->flag & LVAR_INCASE ) ? strncasecmp : strncmp;
int i;
if ( curvar->flag & LVAR_SUBLEXEM ) {
if ( compare_subnode(curt, curvar->name, curvar->len, cmpptr, (curvar->flag & LVAR_ANYEND) ) )
for (i = 0; i < curq->numvar; i++)
{
cmpptr = (curvar->flag & LVAR_INCASE) ? strncasecmp : strncmp;
if (curvar->flag & LVAR_SUBLEXEM)
{
if (compare_subnode(curt, curvar->name, curvar->len, cmpptr, (curvar->flag & LVAR_ANYEND)))
return true;
} else if (
(
curvar->len == curt->len ||
( curt->len > curvar->len && (curvar->flag & LVAR_ANYEND) )
) &&
(*cmpptr)( curvar->name, curt->name, curvar->len) == 0 ) {
}
else if (
(
curvar->len == curt->len ||
(curt->len > curvar->len && (curvar->flag & LVAR_ANYEND))
) &&
(*cmpptr) (curvar->name, curt->name, curvar->len) == 0)
{
return true;
}
curvar = LVAR_NEXT(curvar);
curvar = LVAR_NEXT(curvar);
}
return false;
}
@@ -102,78 +114,97 @@ printFieldNot(FieldNot *fn ) {
elog(NOTICE,"posQ:%d lenQ:%d posT:%d lenT:%d", fn->posq,fn->nq,fn->post,fn->nt);
fn++;
}
}
}
*/
static bool
checkCond( lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_numlevel, FieldNot *ptr ) {
uint32 low_pos=0,high_pos=0,cur_tpos=0;
int tlen = tree_numlevel, qlen = query_numlevel;
int isok;
lquery_level *prevq=NULL;
ltree_level *prevt=NULL;
checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_numlevel, FieldNot * ptr)
{
uint32 low_pos = 0,
high_pos = 0,
cur_tpos = 0;
int tlen = tree_numlevel,
qlen = query_numlevel;
int isok;
lquery_level *prevq = NULL;
ltree_level *prevt = NULL;
while( tlen >0 && qlen>0 ) {
if ( curq->numvar ) {
while (tlen > 0 && qlen > 0)
{
if (curq->numvar)
{
prevt = curt;
while ( cur_tpos < low_pos ) {
while (cur_tpos < low_pos)
{
curt = LEVEL_NEXT(curt);
tlen--;
cur_tpos++;
if ( tlen==0 )
if (tlen == 0)
return false;
if ( ptr && ptr->q )
if (ptr && ptr->q)
ptr->nt++;
}
if ( ptr && curq->flag & LQL_NOT ) {
if ( !(prevq && prevq->numvar == 0) )
if (ptr && curq->flag & LQL_NOT)
{
if (!(prevq && prevq->numvar == 0))
prevq = curq;
if ( ptr->q == NULL ) {
if (ptr->q == NULL)
{
ptr->t = prevt;
ptr->q = prevq;
ptr->nt=1;
ptr->nq=1 + ( (prevq==curq) ? 0 : 1 );
ptr->posq = query_numlevel - qlen - ( (prevq==curq) ? 0 : 1 );
ptr->nt = 1;
ptr->nq = 1 + ((prevq == curq) ? 0 : 1);
ptr->posq = query_numlevel - qlen - ((prevq == curq) ? 0 : 1);
ptr->post = cur_tpos;
} else {
}
else
{
ptr->nt++;
ptr->nq++;
}
if ( qlen == 1 && ptr->q->numvar==0 )
ptr->nt = tree_numlevel - ptr->post;
if (qlen == 1 && ptr->q->numvar == 0)
ptr->nt = tree_numlevel - ptr->post;
curt = LEVEL_NEXT(curt);
tlen--;
cur_tpos++;
if ( high_pos < cur_tpos )
if (high_pos < cur_tpos)
high_pos++;
} else {
}
else
{
isok = false;
while( cur_tpos <= high_pos && tlen > 0 && !isok) {
while (cur_tpos <= high_pos && tlen > 0 && !isok)
{
isok = checkLevel(curq, curt);
curt = LEVEL_NEXT(curt);
tlen--;
cur_tpos++;
if ( !isok && ptr )
if (!isok && ptr)
ptr->nt++;
}
if ( !isok )
if (!isok)
return false;
if (ptr && ptr->q) {
if ( checkCond(ptr->q,ptr->nq,ptr->t,ptr->nt,NULL) )
if (ptr && ptr->q)
{
if (checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL))
return false;
ptr->q = NULL;
}
low_pos=cur_tpos; high_pos=cur_tpos;
low_pos = cur_tpos;
high_pos = cur_tpos;
}
} else {
}
else
{
low_pos = cur_tpos + curq->low;
high_pos = cur_tpos + curq->high;
if ( ptr && ptr->q ) {
if (ptr && ptr->q)
{
ptr->nq++;
if ( qlen==1 )
if (qlen == 1)
ptr->nt = tree_numlevel - ptr->post;
}
}
@@ -181,16 +212,20 @@ checkCond( lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_n
prevq = curq;
curq = LQL_NEXT(curq);
qlen--;
}
}
if ( low_pos > tree_numlevel || tree_numlevel > high_pos )
if (low_pos > tree_numlevel || tree_numlevel > high_pos)
return false;
while( qlen>0 ) {
if ( curq->numvar ) {
if ( ! (curq->flag & LQL_NOT) )
while (qlen > 0)
{
if (curq->numvar)
{
if (!(curq->flag & LQL_NOT))
return false;
} else {
}
else
{
low_pos = cur_tpos + curq->low;
high_pos = cur_tpos + curq->high;
}
@@ -199,42 +234,47 @@ checkCond( lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_n
qlen--;
}
if ( low_pos > tree_numlevel || tree_numlevel > high_pos )
if (low_pos > tree_numlevel || tree_numlevel > high_pos)
return false;
if ( ptr && ptr->q && checkCond(ptr->q,ptr->nq,ptr->t,ptr->nt,NULL) )
if (ptr && ptr->q && checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL))
return false;
return true;
}
Datum
ltq_regex(PG_FUNCTION_ARGS) {
ltree *tree = PG_GETARG_LTREE(0);
lquery *query = PG_GETARG_LQUERY(1);
bool res= false;
ltq_regex(PG_FUNCTION_ARGS)
{
ltree *tree = PG_GETARG_LTREE(0);
lquery *query = PG_GETARG_LQUERY(1);
bool res = false;
if ( query->flag & LQUERY_HASNOT ) {
if (query->flag & LQUERY_HASNOT)
{
FieldNot fn;
fn.q=NULL;
fn.q = NULL;
res = checkCond( LQUERY_FIRST(query), query->numlevel,
LTREE_FIRST(tree), tree->numlevel, &fn );
} else {
res = checkCond( LQUERY_FIRST(query), query->numlevel,
LTREE_FIRST(tree), tree->numlevel, NULL );
res = checkCond(LQUERY_FIRST(query), query->numlevel,
LTREE_FIRST(tree), tree->numlevel, &fn);
}
else
{
res = checkCond(LQUERY_FIRST(query), query->numlevel,
LTREE_FIRST(tree), tree->numlevel, NULL);
}
PG_FREE_IF_COPY(tree,0);
PG_FREE_IF_COPY(query,1);
PG_RETURN_BOOL(res);
PG_FREE_IF_COPY(tree, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(res);
}
Datum
ltq_rregex(PG_FUNCTION_ARGS) {
PG_RETURN_DATUM( DirectFunctionCall2( ltq_regex,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
) );
Datum
ltq_rregex(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(DirectFunctionCall2(ltq_regex,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
));
}

View File

@@ -6,19 +6,21 @@
#include "utils/palloc.h"
#include "utils/builtins.h"
typedef struct {
uint8 len;
char name[1];
} ltree_level;
typedef struct
{
uint8 len;
char name[1];
} ltree_level;
#define LEVEL_HDRSIZE (sizeof(uint8))
#define LEVEL_HDRSIZE (sizeof(uint8))
#define LEVEL_NEXT(x) ( (ltree_level*)( ((char*)(x)) + MAXALIGN(((ltree_level*)(x))->len + LEVEL_HDRSIZE) ) )
typedef struct {
int32 len;
uint16 numlevel;
char data[1];
} ltree;
typedef struct
{
int32 len;
uint16 numlevel;
char data[1];
} ltree;
#define LTREE_HDRSIZE MAXALIGN( sizeof(int32) + sizeof(uint16) )
#define LTREE_FIRST(x) ( (ltree_level*)( ((char*)(x))+LTREE_HDRSIZE ) )
@@ -26,31 +28,33 @@ typedef struct {
/* lquery */
typedef struct {
int4 val;
uint8 len;
uint8 flag;
char name[1];
} lquery_variant;
typedef struct
{
int4 val;
uint8 len;
uint8 flag;
char name[1];
} lquery_variant;
#define LVAR_HDRSIZE MAXALIGN(sizeof(uint8)*2 + sizeof(int4))
#define LVAR_NEXT(x) ( (lquery_variant*)( ((char*)(x)) + MAXALIGN(((lquery_variant*)(x))->len) + LVAR_HDRSIZE ) )
#define LVAR_ANYEND 0x01
#define LVAR_INCASE 0x02
#define LVAR_ANYEND 0x01
#define LVAR_INCASE 0x02
#define LVAR_SUBLEXEM 0x04
typedef struct {
uint16 totallen;
uint16 flag;
uint16 numvar;
uint16 low;
uint16 high;
char variants[1];
} lquery_level;
typedef struct
{
uint16 totallen;
uint16 flag;
uint16 numvar;
uint16 low;
uint16 high;
char variants[1];
} lquery_level;
#define LQL_HDRSIZE MAXALIGN( sizeof(uint16)*5 )
#define LQL_NEXT(x) ( (lquery_level*)( ((char*)(x)) + MAXALIGN(((lquery_level*)(x))->totallen) ) )
#define LQL_HDRSIZE MAXALIGN( sizeof(uint16)*5 )
#define LQL_NEXT(x) ( (lquery_level*)( ((char*)(x)) + MAXALIGN(((lquery_level*)(x))->totallen) ) )
#define LQL_FIRST(x) ( (lquery_variant*)( ((char*)(x))+LQL_HDRSIZE ) )
#define LQL_NOT 0x10
@@ -59,29 +63,30 @@ typedef struct {
#else
#define FLG_CANLOOKSIGN(x) ( ( (x) & ( LQL_NOT | LVAR_ANYEND | LVAR_SUBLEXEM | LVAR_INCASE ) ) == 0 )
#endif
#define LQL_CANLOOKSIGN(x) FLG_CANLOOKSIGN( ((lquery_level*)(x))->flag )
#define LQL_CANLOOKSIGN(x) FLG_CANLOOKSIGN( ((lquery_level*)(x))->flag )
typedef struct {
int32 len;
uint16 numlevel;
uint16 firstgood;
uint16 flag;
char data[1];
} lquery;
typedef struct
{
int32 len;
uint16 numlevel;
uint16 firstgood;
uint16 flag;
char data[1];
} lquery;
#define LQUERY_HDRSIZE MAXALIGN( sizeof(int32) + 3*sizeof(uint16) )
#define LQUERY_HDRSIZE MAXALIGN( sizeof(int32) + 3*sizeof(uint16) )
#define LQUERY_FIRST(x) ( (lquery_level*)( ((char*)(x))+LQUERY_HDRSIZE ) )
#define LQUERY_HASNOT 0x01
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define min(a,b) ((a) <= (b) ? (a) : (b))
#endif
#ifndef abs
#define abs(a) ((a) < (0) ? -(a) : (a))
#define abs(a) ((a) < (0) ? -(a) : (a))
#endif
#define ISALNUM(x) ( isalnum((unsigned int)(x)) || (x) == '_' )
@@ -93,75 +98,75 @@ typedef struct {
*/
typedef struct ITEM
{
int2 type;
int2 left;
int4 val;
int2 type;
int2 left;
int4 val;
uint8 flag;
/* user-friendly value */
uint8 length;
uint16 distance;
} ITEM;
/* user-friendly value */
uint8 length;
uint16 distance;
} ITEM;
/*
*Storage:
* (len)(size)(array of ITEM)(array of operand in user-friendly form)
* (len)(size)(array of ITEM)(array of operand in user-friendly form)
*/
typedef struct
{
int4 len;
int4 size;
char data[1];
} ltxtquery;
int4 len;
int4 size;
char data[1];
} ltxtquery;
#define HDRSIZEQT MAXALIGN( 2*sizeof(int4) )
#define COMPUTESIZE(size,lenofoperand) ( HDRSIZEQT + size * sizeof(ITEM) + lenofoperand )
#define HDRSIZEQT MAXALIGN( 2*sizeof(int4) )
#define COMPUTESIZE(size,lenofoperand) ( HDRSIZEQT + size * sizeof(ITEM) + lenofoperand )
#define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
#define GETOPERAND(x) ( (char*)GETQUERY(x) + ((ltxtquery*)x)->size * sizeof(ITEM) )
#define GETOPERAND(x) ( (char*)GETQUERY(x) + ((ltxtquery*)x)->size * sizeof(ITEM) )
#define ISOPERATOR(x) ( (x)=='!' || (x)=='&' || (x)=='|' || (x)=='(' || (x)==')' )
#define END 0
#define ERR 1
#define VAL 2
#define OPR 3
#define OPEN 4
#define CLOSE 5
#define VALTRUE 6 /* for stop words */
#define VALFALSE 7
#define END 0
#define ERR 1
#define VAL 2
#define OPR 3
#define OPEN 4
#define CLOSE 5
#define VALTRUE 6 /* for stop words */
#define VALFALSE 7
/* use in array iterator */
Datum ltree_isparent(PG_FUNCTION_ARGS);
Datum ltree_risparent(PG_FUNCTION_ARGS);
Datum ltq_regex(PG_FUNCTION_ARGS);
Datum ltq_rregex(PG_FUNCTION_ARGS);
Datum ltxtq_exec(PG_FUNCTION_ARGS);
Datum ltxtq_rexec(PG_FUNCTION_ARGS);
Datum _ltq_regex(PG_FUNCTION_ARGS);
Datum _ltq_rregex(PG_FUNCTION_ARGS);
Datum _ltxtq_exec(PG_FUNCTION_ARGS);
Datum _ltxtq_rexec(PG_FUNCTION_ARGS);
Datum _ltree_isparent(PG_FUNCTION_ARGS);
Datum _ltree_risparent(PG_FUNCTION_ARGS);
Datum ltree_isparent(PG_FUNCTION_ARGS);
Datum ltree_risparent(PG_FUNCTION_ARGS);
Datum ltq_regex(PG_FUNCTION_ARGS);
Datum ltq_rregex(PG_FUNCTION_ARGS);
Datum ltxtq_exec(PG_FUNCTION_ARGS);
Datum ltxtq_rexec(PG_FUNCTION_ARGS);
Datum _ltq_regex(PG_FUNCTION_ARGS);
Datum _ltq_rregex(PG_FUNCTION_ARGS);
Datum _ltxtq_exec(PG_FUNCTION_ARGS);
Datum _ltxtq_rexec(PG_FUNCTION_ARGS);
Datum _ltree_isparent(PG_FUNCTION_ARGS);
Datum _ltree_risparent(PG_FUNCTION_ARGS);
/* Concatenation functions */
Datum ltree_addltree(PG_FUNCTION_ARGS);
Datum ltree_addtext(PG_FUNCTION_ARGS);
Datum ltree_textadd(PG_FUNCTION_ARGS);
Datum ltree_addltree(PG_FUNCTION_ARGS);
Datum ltree_addtext(PG_FUNCTION_ARGS);
Datum ltree_textadd(PG_FUNCTION_ARGS);
/* Util function */
Datum ltree_in(PG_FUNCTION_ARGS);
Datum ltree_in(PG_FUNCTION_ARGS);
bool ltree_execute(ITEM * curitem, void *checkval,
bool calcnot, bool (*chkcond) (void *checkval, ITEM * val));
bool calcnot, bool (*chkcond) (void *checkval, ITEM * val));
int ltree_compare(const ltree *a, const ltree *b);
bool inner_isparent(const ltree *c, const ltree *p);
bool compare_subnode( ltree_level *t, char *q, int len,
int (*cmpptr)(const char *,const char *,size_t), bool anyend );
ltree* lca_inner(ltree** a, int len);
int ltree_compare(const ltree * a, const ltree * b);
bool inner_isparent(const ltree * c, const ltree * p);
bool compare_subnode(ltree_level * t, char *q, int len,
int (*cmpptr) (const char *, const char *, size_t), bool anyend);
ltree *lca_inner(ltree ** a, int len);
#define PG_GETARG_LTREE(x) ((ltree*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
#define PG_GETARG_LTREE(x) ((ltree*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
#define PG_GETARG_LQUERY(x) ((lquery*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
#define PG_GETARG_LTXTQUERY(x) ((ltxtquery*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
@@ -169,7 +174,7 @@ ltree* lca_inner(ltree** a, int len);
#define BITBYTE 8
#define SIGLENINT 8
#define SIGLEN ( sizeof(int4)*SIGLENINT )
#define SIGLEN ( sizeof(int4)*SIGLENINT )
#define SIGLENBIT (SIGLEN*BITBYTE)
typedef unsigned char BITVEC[SIGLEN];
typedef unsigned char *BITVECP;
@@ -195,43 +200,44 @@ typedef unsigned char *BITVECP;
/*
* type of index key for ltree. Tree are combined B-Tree and R-Tree
* Storage:
* Leaf pages
* Leaf pages
* (len)(flag)(ltree)
* Non-Leaf
* (len)(flag)(sign)(left_ltree)(right_ltree)
* (len)(flag)(sign)(left_ltree)(right_ltree)
* ALLTRUE: (len)(flag)(left_ltree)(right_ltree)
*
*
*/
typedef struct {
int4 len;
uint32 flag;
char data[1];
} ltree_gist;
typedef struct
{
int4 len;
uint32 flag;
char data[1];
} ltree_gist;
#define LTG_ONENODE 0x01
#define LTG_ALLTRUE 0x02
#define LTG_NORIGHT 0x04
#define LTG_ONENODE 0x01
#define LTG_ALLTRUE 0x02
#define LTG_NORIGHT 0x04
#define LTG_HDRSIZE MAXALIGN( sizeof(int4) + sizeof(uint32) )
#define LTG_SIGN(x) ( (BITVECP)( ((char*)(x))+LTG_HDRSIZE ) )
#define LTG_NODE(x) ( (ltree*)( ((char*)(x))+LTG_HDRSIZE ) )
#define LTG_ISONENODE(x) ( ((ltree_gist*)(x))->flag & LTG_ONENODE )
#define LTG_ISALLTRUE(x) ( ((ltree_gist*)(x))->flag & LTG_ALLTRUE )
#define LTG_ISNORIGHT(x) ( ((ltree_gist*)(x))->flag & LTG_NORIGHT )
#define LTG_HDRSIZE MAXALIGN( sizeof(int4) + sizeof(uint32) )
#define LTG_SIGN(x) ( (BITVECP)( ((char*)(x))+LTG_HDRSIZE ) )
#define LTG_NODE(x) ( (ltree*)( ((char*)(x))+LTG_HDRSIZE ) )
#define LTG_ISONENODE(x) ( ((ltree_gist*)(x))->flag & LTG_ONENODE )
#define LTG_ISALLTRUE(x) ( ((ltree_gist*)(x))->flag & LTG_ALLTRUE )
#define LTG_ISNORIGHT(x) ( ((ltree_gist*)(x))->flag & LTG_NORIGHT )
#define LTG_LNODE(x) ( (ltree*)( ( ((char*)(x))+LTG_HDRSIZE ) + ( LTG_ISALLTRUE(x) ? 0 : SIGLEN ) ) )
#define LTG_RENODE(x) ( (ltree*)( ((char*)LTG_LNODE(x)) + LTG_LNODE(x)->len) )
#define LTG_RNODE(x) ( LTG_ISNORIGHT(x) ? LTG_LNODE(x) : LTG_RENODE(x) )
#define LTG_GETLNODE(x) ( LTG_ISONENODE(x) ? LTG_NODE(x) : LTG_LNODE(x) )
#define LTG_GETRNODE(x) ( LTG_ISONENODE(x) ? LTG_NODE(x) : LTG_RNODE(x) )
#define LTG_GETLNODE(x) ( LTG_ISONENODE(x) ? LTG_NODE(x) : LTG_LNODE(x) )
#define LTG_GETRNODE(x) ( LTG_ISONENODE(x) ? LTG_NODE(x) : LTG_RNODE(x) )
/* GiST support for ltree[] */
#define ASIGLENINT (2*SIGLENINT)
#define ASIGLENINT (2*SIGLENINT)
#define ASIGLEN (sizeof(int4)*ASIGLENINT)
#define ASIGLENBIT (ASIGLEN*BITBYTE)
#define ASIGLENBIT (ASIGLEN*BITBYTE)
typedef unsigned char ABITVEC[ASIGLEN];
#define ALOOPBYTE(a) \
@@ -249,4 +255,3 @@ typedef unsigned char ABITVEC[ASIGLEN];
/* type of key is the same to ltree_gist */
#endif

View File

@@ -1,5 +1,5 @@
/*
* GiST support for ltree
* GiST support for ltree
* Teodor Sigaev <teodor@stack.net>
*/
@@ -10,252 +10,297 @@
#include "crc32.h"
PG_FUNCTION_INFO_V1( ltree_gist_in );
Datum ltree_gist_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_gist_out );
Datum ltree_gist_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_gist_in);
Datum ltree_gist_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_gist_out);
Datum ltree_gist_out(PG_FUNCTION_ARGS);
Datum
ltree_gist_in(PG_FUNCTION_ARGS) {
elog(ERROR,"Unimplemented");
ltree_gist_in(PG_FUNCTION_ARGS)
{
elog(ERROR, "Unimplemented");
PG_RETURN_DATUM(0);
}
Datum
ltree_gist_out(PG_FUNCTION_ARGS) {
elog(ERROR,"Unimplemented");
ltree_gist_out(PG_FUNCTION_ARGS)
{
elog(ERROR, "Unimplemented");
PG_RETURN_DATUM(0);
}
PG_FUNCTION_INFO_V1( ltree_compress );
Datum ltree_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_decompress );
Datum ltree_decompress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_same );
Datum ltree_same(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_union );
Datum ltree_union(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_penalty );
Datum ltree_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_picksplit );
Datum ltree_picksplit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1( ltree_consistent );
Datum ltree_consistent(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_compress);
Datum ltree_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_decompress);
Datum ltree_decompress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_same);
Datum ltree_same(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_union);
Datum ltree_union(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_penalty);
Datum ltree_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_picksplit);
Datum ltree_picksplit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_consistent);
Datum ltree_consistent(PG_FUNCTION_ARGS);
#define ISEQ(a,b) ( (a)->numlevel == (b)->numlevel && ltree_compare(a,b)==0 )
#define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer(((GISTENTRY *) VARDATA(vec))[(pos)].key))
Datum
ltree_compress(PG_FUNCTION_ARGS) {
GISTENTRY *entry = (GISTENTRY *)PG_GETARG_POINTER(0);
Datum
ltree_compress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval = entry;
if ( entry->leafkey ) { /* ltree */
ltree_gist *key;
ltree *val = (ltree*)DatumGetPointer(PG_DETOAST_DATUM(entry->key));
int4 len = LTG_HDRSIZE + val->len;
if (entry->leafkey)
{ /* ltree */
ltree_gist *key;
ltree *val = (ltree *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
int4 len = LTG_HDRSIZE + val->len;
key = (ltree_gist*)palloc( len );
key = (ltree_gist *) palloc(len);
key->len = len;
key->flag = LTG_ONENODE;
memcpy( (void*)LTG_NODE(key), (void*)val, val->len);
memcpy((void *) LTG_NODE(key), (void *) val, val->len);
if ( PointerGetDatum(val) != entry->key )
if (PointerGetDatum(val) != entry->key)
pfree(val);
retval = (GISTENTRY*)palloc( sizeof(GISTENTRY) );
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page,
entry->offset, key->len, FALSE);
entry->rel, entry->page,
entry->offset, key->len, FALSE);
}
PG_RETURN_POINTER(retval);
}
Datum
ltree_decompress(PG_FUNCTION_ARGS) {
GISTENTRY *entry = (GISTENTRY *)PG_GETARG_POINTER(0);
ltree_gist *key = (ltree_gist*)DatumGetPointer( PG_DETOAST_DATUM(entry->key) );
Datum
ltree_decompress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
ltree_gist *key = (ltree_gist *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
if (PointerGetDatum(key) != entry->key)
{
GISTENTRY *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
if ( PointerGetDatum(key) != entry->key ) {
GISTENTRY *retval = (GISTENTRY*)palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(key),
entry->rel, entry->page,
entry->offset, key->len, FALSE);
entry->rel, entry->page,
entry->offset, key->len, FALSE);
PG_RETURN_POINTER(retval);
}
PG_RETURN_POINTER(entry);
PG_RETURN_POINTER(entry);
}
Datum
ltree_same(PG_FUNCTION_ARGS) {
ltree_gist* a=(ltree_gist*)PG_GETARG_POINTER(0);
ltree_gist* b=(ltree_gist*)PG_GETARG_POINTER(1);
bool *result = (bool *)PG_GETARG_POINTER(2);
Datum
ltree_same(PG_FUNCTION_ARGS)
{
ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
*result = false;
if ( LTG_ISONENODE(a) != LTG_ISONENODE(b) )
PG_RETURN_POINTER(result);
if ( LTG_ISONENODE(a) ) {
*result = ( ISEQ(LTG_NODE(a), LTG_NODE(b)) ) ? true : false;
} else {
int4 i;
BITVECP sa=LTG_SIGN(a), sb=LTG_SIGN(b);
if ( LTG_ISALLTRUE(a) != LTG_ISALLTRUE(b) )
PG_RETURN_POINTER(result);
if (LTG_ISONENODE(a) != LTG_ISONENODE(b))
PG_RETURN_POINTER(result);
if ( !ISEQ(LTG_LNODE(a), LTG_LNODE(b)) )
PG_RETURN_POINTER(result);
if ( !ISEQ(LTG_RNODE(a), LTG_RNODE(b)) )
if (LTG_ISONENODE(a))
*result = (ISEQ(LTG_NODE(a), LTG_NODE(b))) ? true : false;
else
{
int4 i;
BITVECP sa = LTG_SIGN(a),
sb = LTG_SIGN(b);
if (LTG_ISALLTRUE(a) != LTG_ISALLTRUE(b))
PG_RETURN_POINTER(result);
if (!ISEQ(LTG_LNODE(a), LTG_LNODE(b)))
PG_RETURN_POINTER(result);
if (!ISEQ(LTG_RNODE(a), LTG_RNODE(b)))
PG_RETURN_POINTER(result);
*result = true;
if ( !LTG_ISALLTRUE(a) )
if (!LTG_ISALLTRUE(a))
LOOPBYTE(
if ( sa[i] != sb[i] ) {
*result = false;
break;
}
);
if (sa[i] != sb[i])
{
*result = false;
break;
}
);
}
PG_RETURN_POINTER(result);
PG_RETURN_POINTER(result);
}
static void
hashing(BITVECP sign, ltree *t) {
int tlen = t->numlevel;
hashing(BITVECP sign, ltree * t)
{
int tlen = t->numlevel;
ltree_level *cur = LTREE_FIRST(t);
int hash;
int hash;
while(tlen > 0) {
hash = ltree_crc32_sz( cur->name, cur->len );
HASH( sign, hash );
while (tlen > 0)
{
hash = ltree_crc32_sz(cur->name, cur->len);
HASH(sign, hash);
cur = LEVEL_NEXT(cur);
tlen--;
}
}
Datum
ltree_union(PG_FUNCTION_ARGS) {
bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int *size = (int *) PG_GETARG_POINTER(1);
BITVEC base;
int4 len = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
int4 i,j;
ltree_gist *result,*cur;
ltree *left=NULL, *right=NULL, *curtree;
bool isalltrue = false;
bool isleqr;
Datum
ltree_union(PG_FUNCTION_ARGS)
{
bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int *size = (int *) PG_GETARG_POINTER(1);
BITVEC base;
int4 len = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
int4 i,
j;
ltree_gist *result,
*cur;
ltree *left = NULL,
*right = NULL,
*curtree;
bool isalltrue = false;
bool isleqr;
MemSet( (void*)base, 0, sizeof(BITVEC) );
for(j=0;j<len;j++) {
MemSet((void *) base, 0, sizeof(BITVEC));
for (j = 0; j < len; j++)
{
cur = GETENTRY(entryvec, j);
if ( LTG_ISONENODE(cur) ) {
if (LTG_ISONENODE(cur))
{
curtree = LTG_NODE(cur);
hashing(base,curtree);
if ( !left || ltree_compare( left, curtree ) > 0 )
left = curtree;
if ( !right || ltree_compare( right, curtree ) < 0 )
hashing(base, curtree);
if (!left || ltree_compare(left, curtree) > 0)
left = curtree;
if (!right || ltree_compare(right, curtree) < 0)
right = curtree;
} else {
if ( isalltrue || LTG_ISALLTRUE(cur) )
}
else
{
if (isalltrue || LTG_ISALLTRUE(cur))
isalltrue = true;
else {
BITVECP sc=LTG_SIGN(cur);
else
{
BITVECP sc = LTG_SIGN(cur);
LOOPBYTE(
((unsigned char*)base)[i] |= sc[i];
((unsigned char *) base)[i] |= sc[i];
);
}
curtree = LTG_LNODE(cur);
if ( !left || ltree_compare( left, curtree ) > 0 )
left = curtree;
if (!left || ltree_compare(left, curtree) > 0)
left = curtree;
curtree = LTG_RNODE(cur);
if ( !right || ltree_compare( right, curtree ) < 0 )
if (!right || ltree_compare(right, curtree) < 0)
right = curtree;
}
}
}
if ( isalltrue == false ) {
if (isalltrue == false)
{
isalltrue = true;
LOOPBYTE(
if ( ((unsigned char*)base)[i] != 0xff ) {
isalltrue = false;
break;
}
);
if (((unsigned char *) base)[i] != 0xff)
{
isalltrue = false;
break;
}
);
}
isleqr = ( left==right || ISEQ(left,right) ) ? true : false;
*size = LTG_HDRSIZE + ( (isalltrue) ? 0 : SIGLEN ) + left->len + ( (isleqr) ? 0 : right->len );
isleqr = (left == right || ISEQ(left, right)) ? true : false;
*size = LTG_HDRSIZE + ((isalltrue) ? 0 : SIGLEN) + left->len + ((isleqr) ? 0 : right->len);
result = (ltree_gist*)palloc( *size );
result = (ltree_gist *) palloc(*size);
result->len = *size;
result->flag = 0;
if ( isalltrue )
if (isalltrue)
result->flag |= LTG_ALLTRUE;
else
memcpy( (void*)LTG_SIGN(result), base, SIGLEN );
memcpy((void *) LTG_SIGN(result), base, SIGLEN);
memcpy( (void*)LTG_LNODE(result), (void*)left, left->len );
if ( isleqr )
memcpy((void *) LTG_LNODE(result), (void *) left, left->len);
if (isleqr)
result->flag |= LTG_NORIGHT;
else
memcpy( (void*)LTG_RNODE(result), (void*)right, right->len );
memcpy((void *) LTG_RNODE(result), (void *) right, right->len);
PG_RETURN_POINTER(result);
PG_RETURN_POINTER(result);
}
Datum
ltree_penalty(PG_FUNCTION_ARGS) {
ltree_gist *origval = (ltree_gist*)DatumGetPointer( ( (GISTENTRY *)PG_GETARG_POINTER(0) )->key );
ltree_gist *newval = (ltree_gist*)DatumGetPointer( ( (GISTENTRY *)PG_GETARG_POINTER(1) )->key );
float *penalty = (float *) PG_GETARG_POINTER(2);
int4 cmpr,cmpl;
Datum
ltree_penalty(PG_FUNCTION_ARGS)
{
ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
float *penalty = (float *) PG_GETARG_POINTER(2);
int4 cmpr,
cmpl;
cmpl = ltree_compare( LTG_GETLNODE(origval), LTG_GETLNODE(newval) );
cmpr = ltree_compare( LTG_GETRNODE(newval), LTG_GETRNODE(origval));
cmpl = ltree_compare(LTG_GETLNODE(origval), LTG_GETLNODE(newval));
cmpr = ltree_compare(LTG_GETRNODE(newval), LTG_GETRNODE(origval));
*penalty = max( cmpl, 0 ) + max( cmpr, 0 );
*penalty = max(cmpl, 0) + max(cmpr, 0);
PG_RETURN_POINTER(penalty);
}
/* used for sorting */
typedef struct rix {
int index;
ltree *r;
} RIX;
typedef struct rix
{
int index;
ltree *r;
} RIX;
static int
treekey_cmp(const void *a, const void *b) {
treekey_cmp(const void *a, const void *b)
{
return ltree_compare(
((RIX *) a)->r,
((RIX *) b)->r
((RIX *) a)->r,
((RIX *) b)->r
);
}
Datum
ltree_picksplit(PG_FUNCTION_ARGS) {
bytea *entryvec = (bytea*) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC*) PG_GETARG_POINTER(1);
Datum
ltree_picksplit(PG_FUNCTION_ARGS)
{
bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
OffsetNumber j;
int4 i;
RIX *array;
int4 i;
RIX *array;
OffsetNumber maxoff;
int nbytes;
int size;
ltree *lu_l,*lu_r, *ru_l, *ru_r;
ltree_gist *lu, *ru;
BITVEC ls,rs;
bool lisat=false, risat=false, isleqr;
memset( (void*)ls,0,sizeof(BITVEC) );
memset( (void*)rs,0,sizeof(BITVEC) );
int nbytes;
int size;
ltree *lu_l,
*lu_r,
*ru_l,
*ru_r;
ltree_gist *lu,
*ru;
BITVEC ls,
rs;
bool lisat = false,
risat = false,
isleqr;
memset((void *) ls, 0, sizeof(BITVEC));
memset((void *) rs, 0, sizeof(BITVEC));
maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1;
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
v->spl_left = (OffsetNumber *) palloc(nbytes);
@@ -263,109 +308,124 @@ ltree_picksplit(PG_FUNCTION_ARGS) {
v->spl_nleft = 0;
v->spl_nright = 0;
array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
/* copy the data into RIXes, and sort the RIXes */
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j)) {
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
{
array[j].index = j;
lu = GETENTRY( entryvec, j ); /* use as tmp val */
lu = GETENTRY(entryvec, j); /* use as tmp val */
array[j].r = LTG_GETLNODE(lu);
}
qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
sizeof(RIX), treekey_cmp);
sizeof(RIX), treekey_cmp);
lu_l = lu_r = ru_l = ru_r = NULL;
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j)) {
lu = GETENTRY( entryvec, array[j].index ); /* use as tmp val */
if (j <= (maxoff - FirstOffsetNumber + 1) / 2) {
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
{
lu = GETENTRY(entryvec, array[j].index); /* use as tmp val */
if (j <= (maxoff - FirstOffsetNumber + 1) / 2)
{
v->spl_left[v->spl_nleft] = array[j].index;
v->spl_nleft++;
if ( lu_r==NULL || ltree_compare( LTG_GETRNODE(lu), lu_r ) > 0 )
if (lu_r == NULL || ltree_compare(LTG_GETRNODE(lu), lu_r) > 0)
lu_r = LTG_GETRNODE(lu);
if ( LTG_ISONENODE(lu) )
hashing(ls,LTG_NODE(lu));
else {
if ( lisat || LTG_ISALLTRUE(lu) )
if (LTG_ISONENODE(lu))
hashing(ls, LTG_NODE(lu));
else
{
if (lisat || LTG_ISALLTRUE(lu))
lisat = true;
else {
BITVECP sc=LTG_SIGN(lu);
else
{
BITVECP sc = LTG_SIGN(lu);
LOOPBYTE(
((unsigned char*)ls)[i] |= sc[i];
((unsigned char *) ls)[i] |= sc[i];
);
}
}
} else {
}
else
{
v->spl_right[v->spl_nright] = array[j].index;
v->spl_nright++;
if ( ru_r==NULL || ltree_compare( LTG_GETRNODE(lu), ru_r ) > 0 )
if (ru_r == NULL || ltree_compare(LTG_GETRNODE(lu), ru_r) > 0)
ru_r = LTG_GETRNODE(lu);
if ( LTG_ISONENODE(lu) )
hashing(rs,LTG_NODE(lu));
else {
if ( risat || LTG_ISALLTRUE(lu) )
if (LTG_ISONENODE(lu))
hashing(rs, LTG_NODE(lu));
else
{
if (risat || LTG_ISALLTRUE(lu))
risat = true;
else {
BITVECP sc=LTG_SIGN(lu);
else
{
BITVECP sc = LTG_SIGN(lu);
LOOPBYTE(
((unsigned char*)rs)[i] |= sc[i];
((unsigned char *) rs)[i] |= sc[i];
);
}
}
}
}
if ( lisat == false ) {
if (lisat == false)
{
lisat = true;
LOOPBYTE(
if ( ((unsigned char*)ls)[i] != 0xff ) {
lisat = false;
break;
}
);
if (((unsigned char *) ls)[i] != 0xff)
{
lisat = false;
break;
}
);
}
if ( risat == false ) {
if (risat == false)
{
risat = true;
LOOPBYTE(
if ( ((unsigned char*)rs)[i] != 0xff ) {
risat = false;
break;
}
);
if (((unsigned char *) rs)[i] != 0xff)
{
risat = false;
break;
}
);
}
lu_l = LTG_GETLNODE( GETENTRY( entryvec, array[FirstOffsetNumber].index ) );
isleqr = ( lu_l==lu_r || ISEQ(lu_l,lu_r) ) ? true : false;
size = LTG_HDRSIZE + ( (lisat) ? 0 : SIGLEN ) + lu_l->len + ( (isleqr) ? 0 : lu_r->len );
lu = (ltree_gist*)palloc( size );
lu_l = LTG_GETLNODE(GETENTRY(entryvec, array[FirstOffsetNumber].index));
isleqr = (lu_l == lu_r || ISEQ(lu_l, lu_r)) ? true : false;
size = LTG_HDRSIZE + ((lisat) ? 0 : SIGLEN) + lu_l->len + ((isleqr) ? 0 : lu_r->len);
lu = (ltree_gist *) palloc(size);
lu->len = size;
lu->flag = 0;
if ( lisat )
if (lisat)
lu->flag |= LTG_ALLTRUE;
else
memcpy( (void*)LTG_SIGN(lu), ls, SIGLEN );
memcpy( (void*)LTG_LNODE(lu), (void*)lu_l, lu_l->len );
if ( isleqr )
memcpy((void *) LTG_SIGN(lu), ls, SIGLEN);
memcpy((void *) LTG_LNODE(lu), (void *) lu_l, lu_l->len);
if (isleqr)
lu->flag |= LTG_NORIGHT;
else
memcpy( (void*)LTG_RNODE(lu), (void*)lu_r, lu_r->len );
memcpy((void *) LTG_RNODE(lu), (void *) lu_r, lu_r->len);
ru_l = LTG_GETLNODE( GETENTRY( entryvec, array[ 1 + ((maxoff - FirstOffsetNumber + 1) / 2) ].index ) );
isleqr = ( ru_l==ru_r || ISEQ(ru_l,ru_r) ) ? true : false;
size = LTG_HDRSIZE + ( (risat) ? 0 : SIGLEN ) + ru_l->len + ( (isleqr) ? 0 : ru_r->len );
ru = (ltree_gist*)palloc( size );
ru_l = LTG_GETLNODE(GETENTRY(entryvec, array[1 + ((maxoff - FirstOffsetNumber + 1) / 2)].index));
isleqr = (ru_l == ru_r || ISEQ(ru_l, ru_r)) ? true : false;
size = LTG_HDRSIZE + ((risat) ? 0 : SIGLEN) + ru_l->len + ((isleqr) ? 0 : ru_r->len);
ru = (ltree_gist *) palloc(size);
ru->len = size;
ru->flag = 0;
if ( risat )
if (risat)
ru->flag |= LTG_ALLTRUE;
else
memcpy( (void*)LTG_SIGN(ru), rs, SIGLEN );
memcpy( (void*)LTG_LNODE(ru), (void*)ru_l, ru_l->len );
if ( isleqr )
memcpy((void *) LTG_SIGN(ru), rs, SIGLEN);
memcpy((void *) LTG_LNODE(ru), (void *) ru_l, ru_l->len);
if (isleqr)
ru->flag |= LTG_NORIGHT;
else
memcpy( (void*)LTG_RNODE(ru), (void*)ru_r, ru_r->len );
memcpy((void *) LTG_RNODE(ru), (void *) ru_r, ru_r->len);
pfree(array);
v->spl_ldatum = PointerGetDatum(lu);
@@ -375,13 +435,16 @@ ltree_picksplit(PG_FUNCTION_ARGS) {
}
static bool
gist_isparent(ltree_gist *key, ltree *query) {
int4 numlevel = query->numlevel;
int i;
gist_isparent(ltree_gist * key, ltree * query)
{
int4 numlevel = query->numlevel;
int i;
for(i=query->numlevel;i>=0;i--) {
query->numlevel=i;
if ( ltree_compare(query,LTG_GETLNODE(key)) >=0 && ltree_compare(query,LTG_GETRNODE(key)) <= 0 ) {
for (i = query->numlevel; i >= 0; i--)
{
query->numlevel = i;
if (ltree_compare(query, LTG_GETLNODE(key)) >= 0 && ltree_compare(query, LTG_GETRNODE(key)) <= 0)
{
query->numlevel = numlevel;
return true;
}
@@ -392,23 +455,24 @@ gist_isparent(ltree_gist *key, ltree *query) {
}
static bool
gist_ischild(ltree_gist *key, ltree *query) {
ltree *left = LTG_GETLNODE(key);
ltree *right = LTG_GETRNODE(key);
int4 numlevelL = left->numlevel;
int4 numlevelR = right->numlevel;
bool res = true;
gist_ischild(ltree_gist * key, ltree * query)
{
ltree *left = LTG_GETLNODE(key);
ltree *right = LTG_GETRNODE(key);
int4 numlevelL = left->numlevel;
int4 numlevelR = right->numlevel;
bool res = true;
if ( numlevelL > query->numlevel )
if (numlevelL > query->numlevel)
left->numlevel = query->numlevel;
if ( ltree_compare(query,left) < 0 )
if (ltree_compare(query, left) < 0)
res = false;
if ( numlevelR > query->numlevel )
if (numlevelR > query->numlevel)
right->numlevel = query->numlevel;
if ( res && ltree_compare(query,right) > 0 )
if (res && ltree_compare(query, right) > 0)
res = false;
left->numlevel = numlevelL;
@@ -417,29 +481,35 @@ gist_ischild(ltree_gist *key, ltree *query) {
}
static bool
gist_qe(ltree_gist *key, lquery* query) {
lquery_level *curq = LQUERY_FIRST(query);
BITVECP sign = LTG_SIGN(key);
int qlen = query->numlevel;
gist_qe(ltree_gist * key, lquery * query)
{
lquery_level *curq = LQUERY_FIRST(query);
BITVECP sign = LTG_SIGN(key);
int qlen = query->numlevel;
if ( LTG_ISALLTRUE(key) )
if (LTG_ISALLTRUE(key))
return true;
while( qlen>0 ) {
if ( curq->numvar && LQL_CANLOOKSIGN(curq) ) {
bool isexist=false;
int vlen = curq->numvar;
while (qlen > 0)
{
if (curq->numvar && LQL_CANLOOKSIGN(curq))
{
bool isexist = false;
int vlen = curq->numvar;
lquery_variant *curv = LQL_FIRST(curq);
while( vlen>0 ) {
if ( GETBIT( sign, HASHVAL( curv->val ) ) ) {
isexist=true;
while (vlen > 0)
{
if (GETBIT(sign, HASHVAL(curv->val)))
{
isexist = true;
break;
}
curv = LVAR_NEXT(curv);
vlen--;
}
if ( !isexist )
return false;
if (!isexist)
return false;
}
curq = LQL_NEXT(curq);
@@ -450,22 +520,27 @@ gist_qe(ltree_gist *key, lquery* query) {
}
static int
gist_tqcmp(ltree* t, lquery* q) {
gist_tqcmp(ltree * t, lquery * q)
{
ltree_level *al = LTREE_FIRST(t);
lquery_level *ql = LQUERY_FIRST(q);
lquery_variant *bl;
int an = t->numlevel;
int bn = q->firstgood;
int res = 0;
int an = t->numlevel;
int bn = q->firstgood;
int res = 0;
while( an>0 && bn>0 ) {
while (an > 0 && bn > 0)
{
bl = LQL_FIRST(ql);
if ( (res = strncmp( al->name, bl->name, min(al->len, bl->len))) == 0 ) {
if ( al->len != bl->len )
if ((res = strncmp(al->name, bl->name, min(al->len, bl->len))) == 0)
{
if (al->len != bl->len)
return al->len - bl->len;
} else
}
else
return res;
an--; bn--;
an--;
bn--;
al = LEVEL_NEXT(al);
ql = LQL_NEXT(ql);
}
@@ -474,26 +549,27 @@ gist_tqcmp(ltree* t, lquery* q) {
}
static bool
gist_between(ltree_gist *key, lquery* query) {
ltree *left = LTG_GETLNODE(key);
ltree *right = LTG_GETRNODE(key);
int4 numlevelL = left->numlevel;
int4 numlevelR = right->numlevel;
bool res = true;
gist_between(ltree_gist * key, lquery * query)
{
ltree *left = LTG_GETLNODE(key);
ltree *right = LTG_GETRNODE(key);
int4 numlevelL = left->numlevel;
int4 numlevelR = right->numlevel;
bool res = true;
if ( query->firstgood == 0 )
if (query->firstgood == 0)
return true;
if ( numlevelL > query->firstgood )
if (numlevelL > query->firstgood)
left->numlevel = query->firstgood;
if ( gist_tqcmp(left,query) > 0 )
if (gist_tqcmp(left, query) > 0)
res = false;
if ( numlevelR > query->firstgood )
if (numlevelR > query->firstgood)
right->numlevel = query->firstgood;
if ( res && gist_tqcmp(right,query) < 0 )
if (res && gist_tqcmp(right, query) < 0)
res = false;
left->numlevel = numlevelL;
@@ -502,99 +578,102 @@ gist_between(ltree_gist *key, lquery* query) {
}
static bool
checkcondition_bit(void *checkval, ITEM* val ) {
return ( FLG_CANLOOKSIGN(val->flag) ) ? GETBIT( checkval, HASHVAL( val->val ) ) : true;
checkcondition_bit(void *checkval, ITEM * val)
{
return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(checkval, HASHVAL(val->val)) : true;
}
static bool
gist_qtxt(ltree_gist *key, ltxtquery* query) {
if ( LTG_ISALLTRUE(key) )
gist_qtxt(ltree_gist * key, ltxtquery * query)
{
if (LTG_ISALLTRUE(key))
return true;
return ltree_execute(
GETQUERY(query),
(void*)LTG_SIGN(key), false,
checkcondition_bit
);
GETQUERY(query),
(void *) LTG_SIGN(key), false,
checkcondition_bit
);
}
Datum
ltree_consistent(PG_FUNCTION_ARGS) {
GISTENTRY *entry = (GISTENTRY*)PG_GETARG_POINTER(0);
char *query = (char*)DatumGetPointer( PG_DETOAST_DATUM(PG_GETARG_DATUM(1)) );
ltree_gist *key = (ltree_gist*)DatumGetPointer( entry->key );
Datum
ltree_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
char *query = (char *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
bool res = false;
bool res = false;
#ifndef assert_enabled
#ifndef assert_enabled
#define assert_enabled 0
#endif
switch( strategy ) {
switch (strategy)
{
case BTLessStrategyNumber:
res = ( GIST_LEAF( entry ) ) ?
( ltree_compare((ltree*)query,LTG_NODE(key)) > 0 )
res = (GIST_LEAF(entry)) ?
(ltree_compare((ltree *) query, LTG_NODE(key)) > 0)
:
( ltree_compare((ltree*)query,LTG_GETLNODE(key)) >= 0 );
(ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0);
break;
case BTLessEqualStrategyNumber:
res = ( ltree_compare((ltree*)query,LTG_GETLNODE(key)) >= 0 );
res = (ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0);
break;
case BTEqualStrategyNumber:
if ( GIST_LEAF( entry ) )
res = ( ltree_compare((ltree*)query,LTG_NODE(key)) == 0 );
if (GIST_LEAF(entry))
res = (ltree_compare((ltree *) query, LTG_NODE(key)) == 0);
else
res = (
ltree_compare((ltree*)query,LTG_GETLNODE(key)) >= 0
&&
ltree_compare((ltree*)query,LTG_GETRNODE(key)) <= 0
);
ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0
&&
ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0
);
break;
case BTGreaterEqualStrategyNumber:
res = ( ltree_compare((ltree*)query,LTG_GETRNODE(key)) <= 0 );
res = (ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0);
break;
case BTGreaterStrategyNumber:
res = ( GIST_LEAF( entry ) ) ?
( ltree_compare((ltree*)query,LTG_GETRNODE(key)) < 0 )
res = (GIST_LEAF(entry)) ?
(ltree_compare((ltree *) query, LTG_GETRNODE(key)) < 0)
:
( ltree_compare((ltree*)query,LTG_GETRNODE(key)) <= 0 );
(ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0);
break;
case 10:
res = ( GIST_LEAF( entry ) ) ?
inner_isparent( (ltree*)query, LTG_NODE(key) )
res = (GIST_LEAF(entry)) ?
inner_isparent((ltree *) query, LTG_NODE(key))
:
gist_isparent( key, (ltree*)query);
gist_isparent(key, (ltree *) query);
break;
case 11:
res = ( GIST_LEAF( entry ) ) ?
inner_isparent( LTG_NODE(key), (ltree*)query)
res = (GIST_LEAF(entry)) ?
inner_isparent(LTG_NODE(key), (ltree *) query)
:
gist_ischild( key, (ltree*)query);
gist_ischild(key, (ltree *) query);
break;
case 12:
case 13:
if ( GIST_LEAF( entry ) )
res = DatumGetBool( DirectFunctionCall2( ltq_regex,
PointerGetDatum( LTG_NODE(key) ),
PointerGetDatum( (lquery*)query )
) );
else
res = ( gist_qe(key, (lquery*)query) && gist_between(key, (lquery*)query) );
break;
if (GIST_LEAF(entry))
res = DatumGetBool(DirectFunctionCall2(ltq_regex,
PointerGetDatum(LTG_NODE(key)),
PointerGetDatum((lquery *) query)
));
else
res = (gist_qe(key, (lquery *) query) && gist_between(key, (lquery *) query));
break;
case 14:
case 15:
if ( GIST_LEAF( entry ) )
res = DatumGetBool( DirectFunctionCall2( ltxtq_exec,
PointerGetDatum( LTG_NODE(key) ),
PointerGetDatum( (lquery*)query )
) );
else
res = gist_qtxt(key, (ltxtquery*)query);
break;
if (GIST_LEAF(entry))
res = DatumGetBool(DirectFunctionCall2(ltxtq_exec,
PointerGetDatum(LTG_NODE(key)),
PointerGetDatum((lquery *) query)
));
else
res = gist_qtxt(key, (ltxtquery *) query);
break;
default:
elog(ERROR,"Unknown StrategyNumber: %d", strategy);
elog(ERROR, "Unknown StrategyNumber: %d", strategy);
}
PG_RETURN_BOOL(res);
}

View File

@@ -5,91 +5,110 @@
#include "ltree.h"
#include <ctype.h>
#include "crc32.h"
#include "crc32.h"
PG_FUNCTION_INFO_V1(ltree_in);
Datum ltree_in(PG_FUNCTION_ARGS);
Datum ltree_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltree_out);
Datum ltree_out(PG_FUNCTION_ARGS);
Datum ltree_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(lquery_in);
Datum lquery_in(PG_FUNCTION_ARGS);
Datum lquery_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(lquery_out);
Datum lquery_out(PG_FUNCTION_ARGS);
Datum lquery_out(PG_FUNCTION_ARGS);
#define UNCHAR elog(ERROR,"Syntax error in position %d near '%c'", (int)(ptr-buf), *ptr)
typedef struct {
char* start;
int len;
int flag;
} nodeitem;
typedef struct
{
char *start;
int len;
int flag;
} nodeitem;
#define LTPRS_WAITNAME 0
#define LTPRS_WAITDELIM 1
#define LTPRS_WAITDELIM 1
Datum
ltree_in(PG_FUNCTION_ARGS) {
char *buf = (char *) PG_GETARG_POINTER(0);
char *ptr;
nodeitem *list, *lptr;
int num=0, totallen = 0;
int state = LTPRS_WAITNAME;
ltree *result;
ltree_level *curlevel;
Datum
ltree_in(PG_FUNCTION_ARGS)
{
char *buf = (char *) PG_GETARG_POINTER(0);
char *ptr;
nodeitem *list,
*lptr;
int num = 0,
totallen = 0;
int state = LTPRS_WAITNAME;
ltree *result;
ltree_level *curlevel;
ptr=buf;
while( *ptr ) {
if ( *ptr == '.' )
ptr = buf;
while (*ptr)
{
if (*ptr == '.')
num++;
ptr++;
}
list = lptr = (nodeitem*) palloc( sizeof(nodeitem)*(num+1) );
ptr=buf;
while( *ptr ) {
if ( state == LTPRS_WAITNAME ) {
if ( ISALNUM(*ptr) ) {
list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
ptr = buf;
while (*ptr)
{
if (state == LTPRS_WAITNAME)
{
if (ISALNUM(*ptr))
{
lptr->start = ptr;
state = LTPRS_WAITDELIM;
} else
}
else
UNCHAR;
} else if ( state == LTPRS_WAITDELIM ) {
if ( *ptr == '.' ) {
}
else if (state == LTPRS_WAITDELIM)
{
if (*ptr == '.')
{
lptr->len = ptr - lptr->start;
if ( lptr->len > 255 )
elog(ERROR,"Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int)(lptr->start - buf));
if (lptr->len > 255)
elog(ERROR, "Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int) (lptr->start - buf));
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
lptr++;
state = LTPRS_WAITNAME;
} else if ( !ISALNUM(*ptr) )
}
else if (!ISALNUM(*ptr))
UNCHAR;
} else
elog(ERROR,"Inner error in parser");
}
else
elog(ERROR, "Inner error in parser");
ptr++;
}
if ( state == LTPRS_WAITDELIM ) {
if (state == LTPRS_WAITDELIM)
{
lptr->len = ptr - lptr->start;
if ( lptr->len > 255 )
elog(ERROR,"Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int)(lptr->start - buf));
if (lptr->len > 255)
elog(ERROR, "Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int) (lptr->start - buf));
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
lptr++;
} else if ( ! (state == LTPRS_WAITNAME && lptr == list) )
elog(ERROR,"Unexpected end of line");
}
else if (!(state == LTPRS_WAITNAME && lptr == list))
elog(ERROR, "Unexpected end of line");
result = (ltree*)palloc( LTREE_HDRSIZE + totallen );
result = (ltree *) palloc(LTREE_HDRSIZE + totallen);
result->len = LTREE_HDRSIZE + totallen;
result->numlevel = lptr-list;
result->numlevel = lptr - list;
curlevel = LTREE_FIRST(result);
lptr=list;
while( lptr-list < result->numlevel ) {
lptr = list;
while (lptr - list < result->numlevel)
{
curlevel->len = (uint8) lptr->len;
memcpy( curlevel->name, lptr->start, lptr->len);
curlevel = LEVEL_NEXT(curlevel);
memcpy(curlevel->name, lptr->start, lptr->len);
curlevel = LEVEL_NEXT(curlevel);
lptr++;
}
@@ -97,254 +116,323 @@ ltree_in(PG_FUNCTION_ARGS) {
PG_RETURN_POINTER(result);
}
Datum
ltree_out(PG_FUNCTION_ARGS) {
ltree *in = PG_GETARG_LTREE(0);
char *buf,*ptr;
int i;
ltree_level *curlevel;
ptr = buf = (char*)palloc( in->len );
Datum
ltree_out(PG_FUNCTION_ARGS)
{
ltree *in = PG_GETARG_LTREE(0);
char *buf,
*ptr;
int i;
ltree_level *curlevel;
ptr = buf = (char *) palloc(in->len);
curlevel = LTREE_FIRST(in);
for(i=0;i<in->numlevel;i++) {
if ( i!=0 ) {
for (i = 0; i < in->numlevel; i++)
{
if (i != 0)
{
*ptr = '.';
ptr++;
}
memcpy( ptr, curlevel->name, curlevel->len );
ptr+=curlevel->len;
memcpy(ptr, curlevel->name, curlevel->len);
ptr += curlevel->len;
curlevel = LEVEL_NEXT(curlevel);
}
*ptr='\0';
PG_FREE_IF_COPY(in,0);
*ptr = '\0';
PG_FREE_IF_COPY(in, 0);
PG_RETURN_POINTER(buf);
}
#define LQPRS_WAITLEVEL 0
#define LQPRS_WAITDELIM 1
#define LQPRS_WAITOPEN 2
#define LQPRS_WAITFNUM 3
#define LQPRS_WAITSNUM 4
#define LQPRS_WAITND 5
#define LQPRS_WAITCLOSE 6
#define LQPRS_WAITLEVEL 0
#define LQPRS_WAITDELIM 1
#define LQPRS_WAITOPEN 2
#define LQPRS_WAITFNUM 3
#define LQPRS_WAITSNUM 4
#define LQPRS_WAITND 5
#define LQPRS_WAITCLOSE 6
#define LQPRS_WAITEND 7
#define LQPRS_WAITVAR 8
#define GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) )
#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
#define NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
#define GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) )
#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
#define NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
Datum
lquery_in(PG_FUNCTION_ARGS) {
char *buf = (char *) PG_GETARG_POINTER(0);
char *ptr;
int num=0, totallen = 0, numOR=0;
int state = LQPRS_WAITLEVEL;
lquery *result;
nodeitem *lptr=NULL;
lquery_level *cur,*curqlevel, *tmpql;
lquery_variant *lrptr=NULL;
bool hasnot=false;
bool wasbad=false;
Datum
lquery_in(PG_FUNCTION_ARGS)
{
char *buf = (char *) PG_GETARG_POINTER(0);
char *ptr;
int num = 0,
totallen = 0,
numOR = 0;
int state = LQPRS_WAITLEVEL;
lquery *result;
nodeitem *lptr = NULL;
lquery_level *cur,
*curqlevel,
*tmpql;
lquery_variant *lrptr = NULL;
bool hasnot = false;
bool wasbad = false;
ptr=buf;
while( *ptr ) {
if ( *ptr == '.' )
ptr = buf;
while (*ptr)
{
if (*ptr == '.')
num++;
else if ( *ptr == '|' )
else if (*ptr == '|')
numOR++;
ptr++;
}
num++;
curqlevel = tmpql = (lquery_level*) palloc( ITEMSIZE*num );
memset((void*)tmpql,0, ITEMSIZE*num );
ptr=buf;
while( *ptr ) {
if ( state==LQPRS_WAITLEVEL ) {
if ( ISALNUM(*ptr) ) {
GETVAR(curqlevel) = lptr = (nodeitem*)palloc( sizeof(nodeitem)*(numOR+1) );
memset((void*)GETVAR(curqlevel), 0,sizeof(nodeitem)*(numOR+1) );
curqlevel = tmpql = (lquery_level *) palloc(ITEMSIZE * num);
memset((void *) tmpql, 0, ITEMSIZE * num);
ptr = buf;
while (*ptr)
{
if (state == LQPRS_WAITLEVEL)
{
if (ISALNUM(*ptr))
{
GETVAR(curqlevel) = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (numOR + 1));
memset((void *) GETVAR(curqlevel), 0, sizeof(nodeitem) * (numOR + 1));
lptr->start = ptr;
state = LQPRS_WAITDELIM;
curqlevel->numvar = 1;
} else if ( *ptr == '!' ) {
GETVAR(curqlevel) = lptr = (nodeitem*)palloc( sizeof(nodeitem)*(numOR+1) );
memset((void*)GETVAR(curqlevel), 0,sizeof(nodeitem)*(numOR+1) );
lptr->start = ptr+1;
}
else if (*ptr == '!')
{
GETVAR(curqlevel) = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (numOR + 1));
memset((void *) GETVAR(curqlevel), 0, sizeof(nodeitem) * (numOR + 1));
lptr->start = ptr + 1;
state = LQPRS_WAITDELIM;
curqlevel->numvar = 1;
curqlevel->flag |= LQL_NOT;
hasnot=true;
} else if ( *ptr == '*' ) {
hasnot = true;
}
else if (*ptr == '*')
state = LQPRS_WAITOPEN;
} else
else
UNCHAR;
} else if ( state==LQPRS_WAITVAR ) {
if ( ISALNUM(*ptr) ) {
}
else if (state == LQPRS_WAITVAR)
{
if (ISALNUM(*ptr))
{
lptr++;
lptr->start = ptr;
state = LQPRS_WAITDELIM;
curqlevel->numvar++;
} else
}
else
UNCHAR;
} else if ( state==LQPRS_WAITDELIM ) {
if ( *ptr == '@' ) {
if ( lptr->start == ptr )
}
else if (state == LQPRS_WAITDELIM)
{
if (*ptr == '@')
{
if (lptr->start == ptr)
UNCHAR;
lptr->flag |= LVAR_INCASE;
curqlevel->flag |= LVAR_INCASE;
} else if ( *ptr == '*' ) {
if ( lptr->start == ptr )
}
else if (*ptr == '*')
{
if (lptr->start == ptr)
UNCHAR;
lptr->flag |= LVAR_ANYEND;
curqlevel->flag |= LVAR_ANYEND;
} else if ( *ptr == '%' ) {
if ( lptr->start == ptr )
}
else if (*ptr == '%')
{
if (lptr->start == ptr)
UNCHAR;
lptr->flag |= LVAR_SUBLEXEM;
curqlevel->flag |= LVAR_SUBLEXEM;
} else if ( *ptr == '|' ) {
lptr->len = ptr - lptr->start -
( ( lptr->flag & LVAR_SUBLEXEM ) ? 1 : 0 ) -
( ( lptr->flag & LVAR_INCASE ) ? 1 : 0 ) -
( ( lptr->flag & LVAR_ANYEND ) ? 1 : 0 );
if ( lptr->len > 255 )
elog(ERROR,"Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int)(lptr->start - buf));
}
else if (*ptr == '|')
{
lptr->len = ptr - lptr->start -
((lptr->flag & LVAR_SUBLEXEM) ? 1 : 0) -
((lptr->flag & LVAR_INCASE) ? 1 : 0) -
((lptr->flag & LVAR_ANYEND) ? 1 : 0);
if (lptr->len > 255)
elog(ERROR, "Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int) (lptr->start - buf));
state = LQPRS_WAITVAR;
} else if ( *ptr == '.' ) {
lptr->len = ptr - lptr->start -
( ( lptr->flag & LVAR_SUBLEXEM ) ? 1 : 0 ) -
( ( lptr->flag & LVAR_INCASE ) ? 1 : 0 ) -
( ( lptr->flag & LVAR_ANYEND ) ? 1 : 0 );
if ( lptr->len > 255 )
elog(ERROR,"Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int)(lptr->start - buf));
}
else if (*ptr == '.')
{
lptr->len = ptr - lptr->start -
((lptr->flag & LVAR_SUBLEXEM) ? 1 : 0) -
((lptr->flag & LVAR_INCASE) ? 1 : 0) -
((lptr->flag & LVAR_ANYEND) ? 1 : 0);
if (lptr->len > 255)
elog(ERROR, "Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int) (lptr->start - buf));
state = LQPRS_WAITLEVEL;
curqlevel = NEXTLEV(curqlevel);
} else if ( ISALNUM(*ptr) ) {
if ( lptr->flag )
}
else if (ISALNUM(*ptr))
{
if (lptr->flag)
UNCHAR;
} else
}
else
UNCHAR;
} else if ( state == LQPRS_WAITOPEN ) {
if ( *ptr == '{' ) {
}
else if (state == LQPRS_WAITOPEN)
{
if (*ptr == '{')
state = LQPRS_WAITFNUM;
} else if ( *ptr == '.' ) {
curqlevel->low=0;
curqlevel->high=0xffff;
else if (*ptr == '.')
{
curqlevel->low = 0;
curqlevel->high = 0xffff;
curqlevel = NEXTLEV(curqlevel);
state = LQPRS_WAITLEVEL;
} else
}
else
UNCHAR;
} else if ( state == LQPRS_WAITFNUM ) {
if ( *ptr == ',' ) {
state = LQPRS_WAITSNUM;
} else if ( isdigit((unsigned int)*ptr) ) {
curqlevel->low = atoi( ptr );
}
else if (state == LQPRS_WAITFNUM)
{
if (*ptr == ',')
state = LQPRS_WAITSNUM;
else if (isdigit((unsigned int) *ptr))
{
curqlevel->low = atoi(ptr);
state = LQPRS_WAITND;
} else
UNCHAR;
} else if ( state == LQPRS_WAITSNUM ) {
if ( isdigit((unsigned int)*ptr) ) {
curqlevel->high = atoi( ptr );
state = LQPRS_WAITCLOSE;
} else if ( *ptr == '}' ) {
}
else
UNCHAR;
}
else if (state == LQPRS_WAITSNUM)
{
if (isdigit((unsigned int) *ptr))
{
curqlevel->high = atoi(ptr);
state = LQPRS_WAITCLOSE;
}
else if (*ptr == '}')
{
curqlevel->high = 0xffff;
state = LQPRS_WAITEND;
} else
}
else
UNCHAR;
} else if ( state == LQPRS_WAITCLOSE ) {
if ( *ptr == '}' )
}
else if (state == LQPRS_WAITCLOSE)
{
if (*ptr == '}')
state = LQPRS_WAITEND;
else if ( !isdigit((unsigned int)*ptr) )
else if (!isdigit((unsigned int) *ptr))
UNCHAR;
} else if ( state == LQPRS_WAITND ) {
if ( *ptr == '}' ) {
}
else if (state == LQPRS_WAITND)
{
if (*ptr == '}')
{
curqlevel->high = curqlevel->low;
state = LQPRS_WAITEND;
} else if ( *ptr == ',' )
}
else if (*ptr == ',')
state = LQPRS_WAITSNUM;
else if ( !isdigit((unsigned int)*ptr) )
else if (!isdigit((unsigned int) *ptr))
UNCHAR;
} else if ( state == LQPRS_WAITEND ) {
if ( *ptr == '.' ) {
}
else if (state == LQPRS_WAITEND)
{
if (*ptr == '.')
{
state = LQPRS_WAITLEVEL;
curqlevel = NEXTLEV(curqlevel);
} else
}
else
UNCHAR;
} else
elog(ERROR,"Inner error in parser");
}
else
elog(ERROR, "Inner error in parser");
ptr++;
}
if ( state==LQPRS_WAITDELIM ) {
if ( lptr->start == ptr )
elog(ERROR,"Unexpected end of line");
if (state == LQPRS_WAITDELIM)
{
if (lptr->start == ptr)
elog(ERROR, "Unexpected end of line");
lptr->len = ptr - lptr->start -
( ( lptr->flag & LVAR_SUBLEXEM ) ? 1 : 0 ) -
( ( lptr->flag & LVAR_INCASE ) ? 1 : 0 ) -
( ( lptr->flag & LVAR_ANYEND ) ? 1 : 0 );
if ( lptr->len==0 )
elog(ERROR,"Unexpected end of line");
if ( lptr->len > 255 )
elog(ERROR,"Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int)(lptr->start - buf));
} else if ( state == LQPRS_WAITOPEN ) {
((lptr->flag & LVAR_SUBLEXEM) ? 1 : 0) -
((lptr->flag & LVAR_INCASE) ? 1 : 0) -
((lptr->flag & LVAR_ANYEND) ? 1 : 0);
if (lptr->len == 0)
elog(ERROR, "Unexpected end of line");
if (lptr->len > 255)
elog(ERROR, "Name of level is too long (%d, must be < 256) in position %d",
lptr->len, (int) (lptr->start - buf));
}
else if (state == LQPRS_WAITOPEN)
curqlevel->high = 0xffff;
} else if ( state != LQPRS_WAITEND )
elog(ERROR,"Unexpected end of line");
else if (state != LQPRS_WAITEND)
elog(ERROR, "Unexpected end of line");
curqlevel = tmpql;
totallen = LQUERY_HDRSIZE;
while( (char*)curqlevel-(char*)tmpql < num*ITEMSIZE ) {
totallen += LQL_HDRSIZE;
if ( curqlevel->numvar ) {
totallen = LQUERY_HDRSIZE;
while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
{
totallen += LQL_HDRSIZE;
if (curqlevel->numvar)
{
lptr = GETVAR(curqlevel);
while( lptr-GETVAR(curqlevel) < curqlevel->numvar ) {
while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
{
totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
lptr++;
}
} else if ( curqlevel->low > curqlevel->high )
elog(ERROR,"Low limit(%d) is greater than upper(%d)",curqlevel->low,curqlevel->high );
}
else if (curqlevel->low > curqlevel->high)
elog(ERROR, "Low limit(%d) is greater than upper(%d)", curqlevel->low, curqlevel->high);
curqlevel = NEXTLEV(curqlevel);
}
result = (lquery*)palloc( totallen );
result = (lquery *) palloc(totallen);
result->len = totallen;
result->numlevel = num;
result->firstgood = 0;
result->flag=0;
if ( hasnot )
result->flag = 0;
if (hasnot)
result->flag |= LQUERY_HASNOT;
cur = LQUERY_FIRST(result);
curqlevel = tmpql;
while( (char*)curqlevel-(char*)tmpql < num*ITEMSIZE ) {
memcpy(cur,curqlevel,LQL_HDRSIZE);
cur->totallen=LQL_HDRSIZE;
if ( curqlevel->numvar ) {
while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
{
memcpy(cur, curqlevel, LQL_HDRSIZE);
cur->totallen = LQL_HDRSIZE;
if (curqlevel->numvar)
{
lrptr = LQL_FIRST(cur);
lptr = GETVAR(curqlevel);
while( lptr-GETVAR(curqlevel) < curqlevel->numvar ) {
while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
{
cur->totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
lrptr->len = lptr->len;
lrptr->len = lptr->len;
lrptr->flag = lptr->flag;
lrptr->val = ltree_crc32_sz((uint8 *) lptr->start, lptr->len);
memcpy( lrptr->name, lptr->start, lptr->len);
memcpy(lrptr->name, lptr->start, lptr->len);
lptr++;
lrptr = LVAR_NEXT( lrptr );
lrptr = LVAR_NEXT(lrptr);
}
pfree( GETVAR(curqlevel) );
if ( cur->numvar > 1 || cur->flag != 0 )
wasbad=true;
else if ( wasbad==false )
(result->firstgood)++;
} else
wasbad=true;
pfree(GETVAR(curqlevel));
if (cur->numvar > 1 || cur->flag != 0)
wasbad = true;
else if (wasbad == false)
(result->firstgood)++;
}
else
wasbad = true;
curqlevel = NEXTLEV(curqlevel);
cur = LQL_NEXT(cur);
}
@@ -353,82 +441,104 @@ lquery_in(PG_FUNCTION_ARGS) {
PG_RETURN_POINTER(result);
}
Datum
lquery_out(PG_FUNCTION_ARGS) {
lquery *in = PG_GETARG_LQUERY(0);
char *buf,*ptr;
int i,j,totallen=0;
lquery_level *curqlevel;
lquery_variant *curtlevel;
Datum
lquery_out(PG_FUNCTION_ARGS)
{
lquery *in = PG_GETARG_LQUERY(0);
char *buf,
*ptr;
int i,
j,
totallen = 0;
lquery_level *curqlevel;
lquery_variant *curtlevel;
curqlevel = LQUERY_FIRST(in);
for(i=0;i<in->numlevel;i++) {
if ( curqlevel->numvar )
totallen = (curqlevel->numvar*4) + 1 + curqlevel->totallen;
for (i = 0; i < in->numlevel; i++)
{
if (curqlevel->numvar)
totallen = (curqlevel->numvar * 4) + 1 + curqlevel->totallen;
else
totallen = 2*11 + 4;
totallen = 2 * 11 + 4;
totallen++;
curqlevel = LQL_NEXT(curqlevel);
}
ptr = buf = (char*)palloc( totallen );
ptr = buf = (char *) palloc(totallen);
curqlevel = LQUERY_FIRST(in);
for(i=0;i<in->numlevel;i++) {
if ( i!=0 ) {
for (i = 0; i < in->numlevel; i++)
{
if (i != 0)
{
*ptr = '.';
ptr++;
}
if ( curqlevel->numvar ) {
if ( curqlevel->flag & LQL_NOT ) {
if (curqlevel->numvar)
{
if (curqlevel->flag & LQL_NOT)
{
*ptr = '!';
ptr++;
}
curtlevel = LQL_FIRST(curqlevel);
for(j=0;j<curqlevel->numvar;j++) {
if ( j!=0 ) {
for (j = 0; j < curqlevel->numvar; j++)
{
if (j != 0)
{
*ptr = '|';
ptr++;
}
memcpy( ptr, curtlevel->name, curtlevel->len );
ptr+=curtlevel->len;
if ( (curtlevel->flag & LVAR_SUBLEXEM) ) {
memcpy(ptr, curtlevel->name, curtlevel->len);
ptr += curtlevel->len;
if ((curtlevel->flag & LVAR_SUBLEXEM))
{
*ptr = '%';
ptr++;
}
if ( (curtlevel->flag & LVAR_INCASE) ) {
if ((curtlevel->flag & LVAR_INCASE))
{
*ptr = '@';
ptr++;
}
if ( (curtlevel->flag & LVAR_ANYEND) ) {
if ((curtlevel->flag & LVAR_ANYEND))
{
*ptr = '*';
ptr++;
}
curtlevel = LVAR_NEXT(curtlevel);
}
} else {
if ( curqlevel->low == curqlevel->high ) {
sprintf(ptr,"*{%d}",curqlevel->low);
} else if ( curqlevel->low == 0 ) {
if ( curqlevel->high == 0xffff ) {
*ptr='*';
*(ptr+1)='\0';
} else
sprintf(ptr,"*{,%d}",curqlevel->high);
} else if ( curqlevel->high == 0xffff ) {
sprintf(ptr,"*{%d,}",curqlevel->low);
} else
sprintf(ptr,"*{%d,%d}", curqlevel->low, curqlevel->high);
ptr = strchr(ptr,'\0');
}
else
{
if (curqlevel->low == curqlevel->high)
{
sprintf(ptr, "*{%d}", curqlevel->low);
}
else if (curqlevel->low == 0)
{
if (curqlevel->high == 0xffff)
{
*ptr = '*';
*(ptr + 1) = '\0';
}
else
sprintf(ptr, "*{,%d}", curqlevel->high);
}
else if (curqlevel->high == 0xffff)
{
sprintf(ptr, "*{%d,}", curqlevel->low);
}
else
sprintf(ptr, "*{%d,%d}", curqlevel->low, curqlevel->high);
ptr = strchr(ptr, '\0');
}
curqlevel = LQL_NEXT(curqlevel);
}
*ptr='\0';
PG_FREE_IF_COPY(in,0);
*ptr = '\0';
PG_FREE_IF_COPY(in, 0);
PG_RETURN_POINTER(buf);
}

View File

@@ -1,5 +1,5 @@
/*
* op function for ltree
* op function for ltree
* Teodor Sigaev <teodor@stack.net>
*/
@@ -23,45 +23,50 @@ PG_FUNCTION_INFO_V1(ltree_addltree);
PG_FUNCTION_INFO_V1(ltree_addtext);
PG_FUNCTION_INFO_V1(ltree_textadd);
PG_FUNCTION_INFO_V1(lca);
Datum ltree_cmp(PG_FUNCTION_ARGS);
Datum ltree_lt(PG_FUNCTION_ARGS);
Datum ltree_le(PG_FUNCTION_ARGS);
Datum ltree_eq(PG_FUNCTION_ARGS);
Datum ltree_ne(PG_FUNCTION_ARGS);
Datum ltree_ge(PG_FUNCTION_ARGS);
Datum ltree_gt(PG_FUNCTION_ARGS);
Datum nlevel(PG_FUNCTION_ARGS);
Datum subltree(PG_FUNCTION_ARGS);
Datum subpath(PG_FUNCTION_ARGS);
Datum ltree_addltree(PG_FUNCTION_ARGS);
Datum ltree_addtext(PG_FUNCTION_ARGS);
Datum ltree_textadd(PG_FUNCTION_ARGS);
Datum lca(PG_FUNCTION_ARGS);
Datum ltree_cmp(PG_FUNCTION_ARGS);
Datum ltree_lt(PG_FUNCTION_ARGS);
Datum ltree_le(PG_FUNCTION_ARGS);
Datum ltree_eq(PG_FUNCTION_ARGS);
Datum ltree_ne(PG_FUNCTION_ARGS);
Datum ltree_ge(PG_FUNCTION_ARGS);
Datum ltree_gt(PG_FUNCTION_ARGS);
Datum nlevel(PG_FUNCTION_ARGS);
Datum subltree(PG_FUNCTION_ARGS);
Datum subpath(PG_FUNCTION_ARGS);
Datum ltree_addltree(PG_FUNCTION_ARGS);
Datum ltree_addtext(PG_FUNCTION_ARGS);
Datum ltree_textadd(PG_FUNCTION_ARGS);
Datum lca(PG_FUNCTION_ARGS);
int
ltree_compare(const ltree *a, const ltree *b) {
ltree_compare(const ltree * a, const ltree * b)
{
ltree_level *al = LTREE_FIRST(a);
ltree_level *bl = LTREE_FIRST(b);
int an = a->numlevel;
int bn = b->numlevel;
int res = 0;
int an = a->numlevel;
int bn = b->numlevel;
int res = 0;
while( an>0 && bn>0 ) {
if ( (res = strncmp( al->name, bl->name, min(al->len, bl->len))) == 0 ) {
if ( al->len != bl->len )
return (al->len - bl->len)*10*(an+1);
} else
return res*10*(an+1);
while (an > 0 && bn > 0)
{
if ((res = strncmp(al->name, bl->name, min(al->len, bl->len))) == 0)
{
if (al->len != bl->len)
return (al->len - bl->len) * 10 * (an + 1);
}
else
return res * 10 * (an + 1);
an--; bn--;
al = LEVEL_NEXT(al);
bl = LEVEL_NEXT(bl);
an--;
bn--;
al = LEVEL_NEXT(al);
bl = LEVEL_NEXT(bl);
}
return (a->numlevel - b->numlevel)*10*(an+1);
}
return (a->numlevel - b->numlevel) * 10 * (an + 1);
}
#define RUNCMP \
#define RUNCMP \
ltree *a = PG_GETARG_LTREE(0); \
ltree *b = PG_GETARG_LTREE(1); \
int res = ltree_compare(a,b); \
@@ -69,320 +74,360 @@ PG_FREE_IF_COPY(a,0); \
PG_FREE_IF_COPY(b,1); \
Datum
ltree_cmp(PG_FUNCTION_ARGS) {
ltree_cmp(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_INT32(res);
}
Datum
ltree_lt(PG_FUNCTION_ARGS) {
ltree_lt(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_BOOL( (res<0) ? true : false );
PG_RETURN_BOOL((res < 0) ? true : false);
}
Datum
ltree_le(PG_FUNCTION_ARGS) {
ltree_le(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_BOOL( (res<=0) ? true : false );
PG_RETURN_BOOL((res <= 0) ? true : false);
}
Datum
ltree_eq(PG_FUNCTION_ARGS) {
ltree_eq(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_BOOL( (res==0) ? true : false );
PG_RETURN_BOOL((res == 0) ? true : false);
}
Datum
ltree_ge(PG_FUNCTION_ARGS) {
ltree_ge(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_BOOL( (res>=0) ? true : false );
PG_RETURN_BOOL((res >= 0) ? true : false);
}
Datum
ltree_gt(PG_FUNCTION_ARGS) {
ltree_gt(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_BOOL( (res>0) ? true : false );
PG_RETURN_BOOL((res > 0) ? true : false);
}
Datum
ltree_ne(PG_FUNCTION_ARGS) {
ltree_ne(PG_FUNCTION_ARGS)
{
RUNCMP
PG_RETURN_BOOL( (res!=0) ? true : false );
PG_RETURN_BOOL((res != 0) ? true : false);
}
Datum
nlevel(PG_FUNCTION_ARGS) {
ltree *a = PG_GETARG_LTREE(0);
int res = a->numlevel;
PG_FREE_IF_COPY(a,0);
nlevel(PG_FUNCTION_ARGS)
{
ltree *a = PG_GETARG_LTREE(0);
int res = a->numlevel;
PG_FREE_IF_COPY(a, 0);
PG_RETURN_INT32(res);
}
bool
inner_isparent(const ltree *c, const ltree *p) {
inner_isparent(const ltree * c, const ltree * p)
{
ltree_level *cl = LTREE_FIRST(c);
ltree_level *pl = LTREE_FIRST(p);
int pn = p->numlevel;
int pn = p->numlevel;
if ( pn > c->numlevel )
if (pn > c->numlevel)
return false;
while( pn>0 ) {
if ( cl->len != pl->len )
while (pn > 0)
{
if (cl->len != pl->len)
return false;
if ( strncmp( cl->name, pl->name, cl->len ) )
if (strncmp(cl->name, pl->name, cl->len))
return false;
pn--;
cl = LEVEL_NEXT(cl);
pl = LEVEL_NEXT(pl);
cl = LEVEL_NEXT(cl);
pl = LEVEL_NEXT(pl);
}
return true;
}
Datum
ltree_isparent(PG_FUNCTION_ARGS) {
ltree *c = PG_GETARG_LTREE(1);
ltree *p = PG_GETARG_LTREE(0);
bool res = inner_isparent(c,p);
PG_FREE_IF_COPY(c,1);
PG_FREE_IF_COPY(p,0);
PG_RETURN_BOOL( res );
Datum
ltree_isparent(PG_FUNCTION_ARGS)
{
ltree *c = PG_GETARG_LTREE(1);
ltree *p = PG_GETARG_LTREE(0);
bool res = inner_isparent(c, p);
PG_FREE_IF_COPY(c, 1);
PG_FREE_IF_COPY(p, 0);
PG_RETURN_BOOL(res);
}
Datum
ltree_risparent(PG_FUNCTION_ARGS) {
ltree *c = PG_GETARG_LTREE(0);
ltree *p = PG_GETARG_LTREE(1);
bool res = inner_isparent(c,p);
PG_FREE_IF_COPY(c,0);
PG_FREE_IF_COPY(p,1);
PG_RETURN_BOOL( res );
Datum
ltree_risparent(PG_FUNCTION_ARGS)
{
ltree *c = PG_GETARG_LTREE(0);
ltree *p = PG_GETARG_LTREE(1);
bool res = inner_isparent(c, p);
PG_FREE_IF_COPY(c, 0);
PG_FREE_IF_COPY(p, 1);
PG_RETURN_BOOL(res);
}
static ltree*
inner_subltree(ltree *t, int4 startpos, int4 endpos) {
char *start=NULL,*end=NULL;
static ltree *
inner_subltree(ltree * t, int4 startpos, int4 endpos)
{
char *start = NULL,
*end = NULL;
ltree_level *ptr = LTREE_FIRST(t);
ltree *res;
int i;
ltree *res;
int i;
if ( startpos <0 || endpos <0 || startpos>=t->numlevel || startpos >= endpos )
elog(ERROR,"Wrong positions");
if (startpos < 0 || endpos < 0 || startpos >= t->numlevel || startpos >= endpos)
elog(ERROR, "Wrong positions");
if ( endpos > t->numlevel )
if (endpos > t->numlevel)
endpos = t->numlevel;
for(i=0;i<endpos ;i++) {
if ( i==startpos )
start = (char*)ptr;
if ( i==endpos-1 ) {
end = (char*)LEVEL_NEXT(ptr);
for (i = 0; i < endpos; i++)
{
if (i == startpos)
start = (char *) ptr;
if (i == endpos - 1)
{
end = (char *) LEVEL_NEXT(ptr);
break;
}
ptr = LEVEL_NEXT(ptr);
ptr = LEVEL_NEXT(ptr);
}
res=(ltree*)palloc( LTREE_HDRSIZE + (end-start) );
res->len = LTREE_HDRSIZE + (end-start);
res->numlevel = endpos-startpos;
res = (ltree *) palloc(LTREE_HDRSIZE + (end - start));
res->len = LTREE_HDRSIZE + (end - start);
res->numlevel = endpos - startpos;
memcpy(LTREE_FIRST(res), start, end - start);
memcpy( LTREE_FIRST(res), start, end-start);
return res;
}
Datum
subltree(PG_FUNCTION_ARGS) {
ltree *t = PG_GETARG_LTREE(0);
ltree *res = inner_subltree(t,PG_GETARG_INT32(1),PG_GETARG_INT32(2));
subltree(PG_FUNCTION_ARGS)
{
ltree *t = PG_GETARG_LTREE(0);
ltree *res = inner_subltree(t, PG_GETARG_INT32(1), PG_GETARG_INT32(2));
PG_FREE_IF_COPY(t,0);
PG_FREE_IF_COPY(t, 0);
PG_RETURN_POINTER(res);
}
Datum
subpath(PG_FUNCTION_ARGS) {
ltree *t = PG_GETARG_LTREE(0);
int4 start = PG_GETARG_INT32(1);
int4 len = ( fcinfo->nargs==3 ) ? PG_GETARG_INT32(2) : 0;
int4 end;
ltree *res;
Datum
subpath(PG_FUNCTION_ARGS)
{
ltree *t = PG_GETARG_LTREE(0);
int4 start = PG_GETARG_INT32(1);
int4 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
int4 end;
ltree *res;
end = start+len;
end = start + len;
if ( start < 0 ) {
if (start < 0)
{
start = t->numlevel + start;
end = start+len;
end = start + len;
}
if ( start < 0 ) { /* start > t->numlevel */
if (start < 0)
{ /* start > t->numlevel */
start = t->numlevel + start;
end = start+len;
end = start + len;
}
if ( len < 0 )
if (len < 0)
end = t->numlevel + len;
else if ( len == 0 )
else if (len == 0)
end = 0xffff;
res = inner_subltree(t,start,end);
res = inner_subltree(t, start, end);
PG_FREE_IF_COPY(t,0);
PG_FREE_IF_COPY(t, 0);
PG_RETURN_POINTER(res);
}
static ltree*
ltree_concat( ltree *a, ltree *b) {
ltree *r;
r=(ltree*)palloc( a->len + b->len - LTREE_HDRSIZE);
r->len = a->len + b->len - LTREE_HDRSIZE;
r->numlevel = a->numlevel + b->numlevel;
memcpy( LTREE_FIRST(r), LTREE_FIRST(a), a->len - LTREE_HDRSIZE);
memcpy( ((char*)LTREE_FIRST(r))+ a->len - LTREE_HDRSIZE, LTREE_FIRST(b), b->len -
LTREE_HDRSIZE);
return r;
}
Datum
ltree_addltree(PG_FUNCTION_ARGS) {
ltree *a = PG_GETARG_LTREE(0);
ltree *b = PG_GETARG_LTREE(1);
ltree *r;
static ltree *
ltree_concat(ltree * a, ltree * b)
{
ltree *r;
r = (ltree *) palloc(a->len + b->len - LTREE_HDRSIZE);
r->len = a->len + b->len - LTREE_HDRSIZE;
r->numlevel = a->numlevel + b->numlevel;
memcpy(LTREE_FIRST(r), LTREE_FIRST(a), a->len - LTREE_HDRSIZE);
memcpy(((char *) LTREE_FIRST(r)) + a->len - LTREE_HDRSIZE, LTREE_FIRST(b), b->len -
LTREE_HDRSIZE);
return r;
}
Datum
ltree_addltree(PG_FUNCTION_ARGS)
{
ltree *a = PG_GETARG_LTREE(0);
ltree *b = PG_GETARG_LTREE(1);
ltree *r;
r = ltree_concat(a, b);
PG_FREE_IF_COPY(a,0);
PG_FREE_IF_COPY(b,1);
PG_FREE_IF_COPY(a, 0);
PG_FREE_IF_COPY(b, 1);
PG_RETURN_POINTER(r);
}
Datum
ltree_addtext(PG_FUNCTION_ARGS) {
ltree *a = PG_GETARG_LTREE(0);
text *b = PG_GETARG_TEXT_P(1);
char *s;
ltree *r,*tmp;
ltree_addtext(PG_FUNCTION_ARGS)
{
ltree *a = PG_GETARG_LTREE(0);
text *b = PG_GETARG_TEXT_P(1);
char *s;
ltree *r,
*tmp;
s = (char*)palloc( VARSIZE(b) - VARHDRSZ+1 );
memcpy(s, VARDATA(b), VARSIZE(b) - VARHDRSZ );
s = (char *) palloc(VARSIZE(b) - VARHDRSZ + 1);
memcpy(s, VARDATA(b), VARSIZE(b) - VARHDRSZ);
s[VARSIZE(b) - VARHDRSZ] = '\0';
tmp = (ltree*)DatumGetPointer( DirectFunctionCall1(
ltree_in,
PointerGetDatum(s)
) );
tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(
ltree_in,
PointerGetDatum(s)
));
pfree(s);
r = ltree_concat(a,tmp);
r = ltree_concat(a, tmp);
pfree( tmp );
PG_FREE_IF_COPY(a,0);
PG_FREE_IF_COPY(b,1);
pfree(tmp);
PG_FREE_IF_COPY(a, 0);
PG_FREE_IF_COPY(b, 1);
PG_RETURN_POINTER(r);
}
Datum
ltree_textadd(PG_FUNCTION_ARGS) {
ltree *a = PG_GETARG_LTREE(1);
text *b = PG_GETARG_TEXT_P(0);
char *s;
ltree *r,*tmp;
ltree_textadd(PG_FUNCTION_ARGS)
{
ltree *a = PG_GETARG_LTREE(1);
text *b = PG_GETARG_TEXT_P(0);
char *s;
ltree *r,
*tmp;
s = (char*)palloc( VARSIZE(b) - VARHDRSZ + 1 );
memcpy(s, VARDATA(b), VARSIZE(b) - VARHDRSZ );
s[VARSIZE(b) - VARHDRSZ] = '\0';
tmp = (ltree*)DatumGetPointer( DirectFunctionCall1(
ltree_in,
PointerGetDatum(s)
) );
s = (char *) palloc(VARSIZE(b) - VARHDRSZ + 1);
memcpy(s, VARDATA(b), VARSIZE(b) - VARHDRSZ);
s[VARSIZE(b) - VARHDRSZ] = '\0';
pfree(s);
tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(
ltree_in,
PointerGetDatum(s)
));
r = ltree_concat(tmp,a);
pfree(s);
pfree( tmp );
PG_FREE_IF_COPY(a,1);
PG_FREE_IF_COPY(b,0);
PG_RETURN_POINTER(r);
r = ltree_concat(tmp, a);
pfree(tmp);
PG_FREE_IF_COPY(a, 1);
PG_FREE_IF_COPY(b, 0);
PG_RETURN_POINTER(r);
}
ltree*
lca_inner(ltree** a, int len) {
int tmp,num=( (*a)->numlevel ) ? (*a)->numlevel-1 : 0;
ltree **ptr=a+1;
int i,reslen=LTREE_HDRSIZE;
ltree_level *l1, *l2;
ltree *res;
ltree *
lca_inner(ltree ** a, int len)
{
int tmp,
num = ((*a)->numlevel) ? (*a)->numlevel - 1 : 0;
ltree **ptr = a + 1;
int i,
reslen = LTREE_HDRSIZE;
ltree_level *l1,
*l2;
ltree *res;
if ( (*a)->numlevel == 0 )
if ((*a)->numlevel == 0)
return NULL;
while( ptr-a < len ) {
if ( (*ptr)->numlevel == 0 )
while (ptr - a < len)
{
if ((*ptr)->numlevel == 0)
return NULL;
else if ( (*ptr)->numlevel == 1 )
num=0;
else {
else if ((*ptr)->numlevel == 1)
num = 0;
else
{
l1 = LTREE_FIRST(*a);
l2 = LTREE_FIRST(*ptr);
tmp=num; num=0;
for(i=0;i<min(tmp, (*ptr)->numlevel-1); i++) {
if ( l1->len == l2->len && strncmp(l1->name,l2->name,l1->len) == 0 )
num=i+1;
tmp = num;
num = 0;
for (i = 0; i < min(tmp, (*ptr)->numlevel - 1); i++)
{
if (l1->len == l2->len && strncmp(l1->name, l2->name, l1->len) == 0)
num = i + 1;
else
break;
l1=LEVEL_NEXT(l1);
l2=LEVEL_NEXT(l2);
l1 = LEVEL_NEXT(l1);
l2 = LEVEL_NEXT(l2);
}
}
ptr++;
}
l1 = LTREE_FIRST(*a);
for(i=0;i<num;i++) {
for (i = 0; i < num; i++)
{
reslen += MAXALIGN(l1->len + LEVEL_HDRSIZE);
l1=LEVEL_NEXT(l1);
l1 = LEVEL_NEXT(l1);
}
res=(ltree*)palloc( reslen );
res = (ltree *) palloc(reslen);
res->len = reslen;
res->numlevel = num;
l1 = LTREE_FIRST(*a);
l2 = LTREE_FIRST(res);
for(i=0;i<num;i++) {
memcpy(l2,l1, MAXALIGN(l1->len + LEVEL_HDRSIZE));
l1=LEVEL_NEXT(l1);
l2=LEVEL_NEXT(l2);
}
for (i = 0; i < num; i++)
{
memcpy(l2, l1, MAXALIGN(l1->len + LEVEL_HDRSIZE));
l1 = LEVEL_NEXT(l1);
l2 = LEVEL_NEXT(l2);
}
return res;
}
Datum
lca(PG_FUNCTION_ARGS) {
int i;
ltree **a,*res;
lca(PG_FUNCTION_ARGS)
{
int i;
ltree **a,
*res;
a=(ltree**)palloc( sizeof(ltree*) * fcinfo->nargs );
for(i=0;i<fcinfo->nargs;i++)
a = (ltree **) palloc(sizeof(ltree *) * fcinfo->nargs);
for (i = 0; i < fcinfo->nargs; i++)
a[i] = PG_GETARG_LTREE(i);
res = lca_inner(a, (int) fcinfo->nargs);
for(i=0;i<fcinfo->nargs;i++)
PG_FREE_IF_COPY(a[i],i);
res = lca_inner(a, (int) fcinfo->nargs);
for (i = 0; i < fcinfo->nargs; i++)
PG_FREE_IF_COPY(a[i], i);
pfree(a);
if ( res )
if (res)
PG_RETURN_POINTER(res);
else
PG_RETURN_NULL();
}

View File

@@ -1,5 +1,5 @@
/*
* txtquery io
* txtquery io
* Teodor Sigaev <teodor@stack.net>
*/
@@ -8,44 +8,47 @@
#include "crc32.h"
PG_FUNCTION_INFO_V1(ltxtq_in);
Datum ltxtq_in(PG_FUNCTION_ARGS);
Datum ltxtq_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ltxtq_out);
Datum ltxtq_out(PG_FUNCTION_ARGS);
Datum ltxtq_out(PG_FUNCTION_ARGS);
/* parser's states */
#define WAITOPERAND 1
#define INOPERAND 2
#define WAITOPERATOR 3
#define WAITOPERATOR 3
/*
* node of query tree, also used
* for storing polish notation in parser
*/
typedef struct NODE {
int4 type;
int4 val;
int2 distance;
int2 length;
uint16 flag;
typedef struct NODE
{
int4 type;
int4 val;
int2 distance;
int2 length;
uint16 flag;
struct NODE *next;
} NODE;
} NODE;
typedef struct {
char *buf;
int4 state;
int4 count;
typedef struct
{
char *buf;
int4 state;
int4 count;
/* reverse polish notation in list (for temprorary usage) */
NODE *str;
NODE *str;
/* number in str */
int4 num;
int4 num;
/* user-friendly operand */
int4 lenop;
int4 sumlen;
char *op;
char *curop;
} QPRS_STATE;
int4 lenop;
int4 sumlen;
char *op;
char *curop;
} QPRS_STATE;
/*
* get token from query string
@@ -70,27 +73,31 @@ gettoken_query(QPRS_STATE * state, int4 *val, int4 *lenval, char **strval, uint1
(state->buf)++;
return OPEN;
}
else if ( ISALNUM(*(state->buf)) )
else if (ISALNUM(*(state->buf)))
{
state->state = INOPERAND;
*strval = state->buf;
*lenval = 1;
*flag = 0;
} else if ( !isspace((unsigned int)*(state->buf)) )
elog(ERROR,"Operand syntax error");
}
else if (!isspace((unsigned int) *(state->buf)))
elog(ERROR, "Operand syntax error");
break;
case INOPERAND:
if ( ISALNUM(*(state->buf)) ) {
if ( *flag )
elog(ERROR,"Modificators syntax error");
if (ISALNUM(*(state->buf)))
{
if (*flag)
elog(ERROR, "Modificators syntax error");
(*lenval)++;
} else if ( *(state->buf) == '%' ) {
}
else if (*(state->buf) == '%')
*flag |= LVAR_SUBLEXEM;
} else if ( *(state->buf) == '@' ) {
else if (*(state->buf) == '@')
*flag |= LVAR_INCASE;
} else if ( *(state->buf) == '*' ) {
else if (*(state->buf) == '*')
*flag |= LVAR_ANYEND;
} else {
else
{
state->state = WAITOPERATOR;
return VAL;
}
@@ -129,7 +136,7 @@ gettoken_query(QPRS_STATE * state, int4 *val, int4 *lenval, char **strval, uint1
static void
pushquery(QPRS_STATE * state, int4 type, int4 val, int4 distance, int4 lenval, uint16 flag)
{
NODE *tmp = (NODE *) palloc(sizeof(NODE));
NODE *tmp = (NODE *) palloc(sizeof(NODE));
tmp->type = type;
tmp->val = val;
@@ -159,7 +166,7 @@ pushval_asis(QPRS_STATE * state, int type, char *strval, int lenval, uint16 flag
while (state->curop - state->op + lenval + 1 >= state->lenop)
{
int4 tmp = state->curop - state->op;
int4 tmp = state->curop - state->op;
state->lenop *= 2;
state->op = (char *) repalloc((void *) state->op, state->lenop);
@@ -173,26 +180,27 @@ pushval_asis(QPRS_STATE * state, int type, char *strval, int lenval, uint16 flag
return;
}
#define STACKDEPTH 32
#define STACKDEPTH 32
/*
* make polish notaion of query
*/
static int4
makepol(QPRS_STATE * state)
{
int4 val,
int4 val,
type;
int4 lenval;
char *strval;
int4 stack[STACKDEPTH];
int4 lenstack = 0;
uint16 flag;
int4 lenval;
char *strval;
int4 stack[STACKDEPTH];
int4 lenstack = 0;
uint16 flag;
while ((type = gettoken_query(state, &val, &lenval, &strval,&flag)) != END) {
while ((type = gettoken_query(state, &val, &lenval, &strval, &flag)) != END)
{
switch (type)
{
case VAL:
pushval_asis(state, VAL, strval, lenval,flag);
pushval_asis(state, VAL, strval, lenval, flag);
while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
stack[lenstack - 1] == (int4) '!'))
{
@@ -236,7 +244,8 @@ makepol(QPRS_STATE * state)
}
}
while (lenstack) {
while (lenstack)
{
lenstack--;
pushquery(state, OPR, stack[lenstack], 0, 0, 0);
};
@@ -259,8 +268,8 @@ findoprnd(ITEM * ptr, int4 *pos)
}
else
{
ITEM *curitem = &ptr[*pos];
int4 tmp = *pos;
ITEM *curitem = &ptr[*pos];
int4 tmp = *pos;
(*pos)++;
findoprnd(ptr, pos);
@@ -276,16 +285,16 @@ findoprnd(ITEM * ptr, int4 *pos)
static ltxtquery *
queryin(char *buf)
{
QPRS_STATE state;
int4 i;
QPRS_STATE state;
int4 i;
ltxtquery *query;
int4 commonlen;
ITEM *ptr;
NODE *tmp;
int4 pos = 0;
int4 commonlen;
ITEM *ptr;
NODE *tmp;
int4 pos = 0;
#ifdef BS_DEBUG
char pbuf[16384],
char pbuf[16384],
*cur;
#endif
@@ -351,12 +360,12 @@ ltxtq_in(PG_FUNCTION_ARGS)
*/
typedef struct
{
ITEM *curpol;
char *buf;
char *cur;
char *op;
int4 buflen;
} INFIX;
ITEM *curpol;
char *buf;
char *cur;
char *op;
int4 buflen;
} INFIX;
#define RESIZEBUF(inf,addsize) \
while( ( inf->cur - inf->buf ) + addsize + 1 >= inf->buflen ) \
@@ -376,23 +385,27 @@ infix(INFIX * in, bool first)
{
if (in->curpol->type == VAL)
{
char *op = in->op + in->curpol->distance;
char *op = in->op + in->curpol->distance;
RESIZEBUF(in, in->curpol->length * 2 + 5);
while (*op) {
while (*op)
{
*(in->cur) = *op;
op++;
in->cur++;
}
if ( in->curpol->flag & LVAR_SUBLEXEM ) {
if (in->curpol->flag & LVAR_SUBLEXEM)
{
*(in->cur) = '%';
in->cur++;
}
if ( in->curpol->flag & LVAR_INCASE ) {
if (in->curpol->flag & LVAR_INCASE)
{
*(in->cur) = '@';
in->cur++;
}
if ( in->curpol->flag & LVAR_ANYEND ) {
if (in->curpol->flag & LVAR_ANYEND)
{
*(in->cur) = '*';
in->cur++;
}
@@ -401,7 +414,7 @@ infix(INFIX * in, bool first)
}
else if (in->curpol->val == (int4) '!')
{
bool isopr = false;
bool isopr = false;
RESIZEBUF(in, 1);
*(in->cur) = '!';
@@ -425,8 +438,8 @@ infix(INFIX * in, bool first)
}
else
{
int4 op = in->curpol->val;
INFIX nrm;
int4 op = in->curpol->val;
INFIX nrm;
in->curpol++;
if (op == (int4) '|' && !first)
@@ -467,7 +480,7 @@ Datum
ltxtq_out(PG_FUNCTION_ARGS)
{
ltxtquery *query = PG_GETARG_LTXTQUERY(0);
INFIX nrm;
INFIX nrm;
if (query->size == 0)
elog(ERROR, "Empty");
@@ -481,4 +494,3 @@ ltxtq_out(PG_FUNCTION_ARGS)
PG_FREE_IF_COPY(query, 0);
PG_RETURN_POINTER(nrm.buf);
}

View File

@@ -1,5 +1,5 @@
/*
* txtquery operations with ltree
* txtquery operations with ltree
* Teodor Sigaev <teodor@stack.net>
*/
@@ -12,20 +12,26 @@ PG_FUNCTION_INFO_V1(ltxtq_rexec);
/*
* check for boolean condition
*/
bool
ltree_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM * val)) {
bool
ltree_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM * val))
{
if (curitem->type == VAL)
return (*chkcond) (checkval, curitem);
else if (curitem->val == (int4) '!') {
else if (curitem->val == (int4) '!')
{
return (calcnot) ?
((ltree_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
: true;
} else if (curitem->val == (int4) '&') {
if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
}
else if (curitem->val == (int4) '&')
{
if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
else
return false;
} else { /* |-operator */
}
else
{ /* |-operator */
if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
return true;
else
@@ -34,54 +40,60 @@ ltree_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (voi
return false;
}
typedef struct {
ltree *node;
char *operand;
} CHKVAL;
typedef struct
{
ltree *node;
char *operand;
} CHKVAL;
static bool
checkcondition_str(void* checkval, ITEM * val) {
ltree_level *level = LTREE_FIRST( ((CHKVAL*)checkval)->node );
int tlen = ((CHKVAL*)checkval)->node->numlevel;
char *op = ((CHKVAL*)checkval)->operand + val->distance;
int (*cmpptr)(const char *,const char *,size_t);
checkcondition_str(void *checkval, ITEM * val)
{
ltree_level *level = LTREE_FIRST(((CHKVAL *) checkval)->node);
int tlen = ((CHKVAL *) checkval)->node->numlevel;
char *op = ((CHKVAL *) checkval)->operand + val->distance;
int (*cmpptr) (const char *, const char *, size_t);
cmpptr = ( val->flag & LVAR_INCASE ) ? strncasecmp : strncmp;
while( tlen > 0 ) {
if ( val->flag & LVAR_SUBLEXEM ) {
if ( compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND) ) )
cmpptr = (val->flag & LVAR_INCASE) ? strncasecmp : strncmp;
while (tlen > 0)
{
if (val->flag & LVAR_SUBLEXEM)
{
if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
return true;
} else if (
(
val->length == level->len ||
( level->len > val->length && (val->flag & LVAR_ANYEND) )
) &&
(*cmpptr)( op, level->name, val->length) == 0 )
}
else if (
(
val->length == level->len ||
(level->len > val->length && (val->flag & LVAR_ANYEND))
) &&
(*cmpptr) (op, level->name, val->length) == 0)
return true;
tlen--;
level = LEVEL_NEXT(level);
level = LEVEL_NEXT(level);
}
return false;
}
Datum
ltxtq_exec(PG_FUNCTION_ARGS) {
ltree *val = PG_GETARG_LTREE(0);
ltxtq_exec(PG_FUNCTION_ARGS)
{
ltree *val = PG_GETARG_LTREE(0);
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
CHKVAL chkval;
bool result;
CHKVAL chkval;
bool result;
chkval.node = val;
chkval.operand = GETOPERAND(query);
result = ltree_execute(
GETQUERY(query),
&chkval,
true,
checkcondition_str
);
GETQUERY(query),
&chkval,
true,
checkcondition_str
);
PG_FREE_IF_COPY(val, 0);
PG_FREE_IF_COPY(query, 1);
@@ -89,11 +101,10 @@ ltxtq_exec(PG_FUNCTION_ARGS) {
}
Datum
ltxtq_rexec(PG_FUNCTION_ARGS) {
PG_RETURN_DATUM( DirectFunctionCall2( ltxtq_exec,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
) );
ltxtq_rexec(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(DirectFunctionCall2(ltxtq_exec,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
));
}