2002-07-31 00:40:34 +08:00
|
|
|
#ifndef __LTREE_H__
|
|
|
|
#define __LTREE_H__
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "utils/elog.h"
|
|
|
|
#include "utils/palloc.h"
|
|
|
|
#include "utils/builtins.h"
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
uint8 len;
|
|
|
|
char name[1];
|
|
|
|
} ltree_level;
|
|
|
|
|
|
|
|
#define LEVEL_HDRSIZE (sizeof(uint8))
|
2002-08-04 13:02:50 +08:00
|
|
|
#define LEVEL_NEXT(x) ( (ltree_level*)( ((char*)(x)) + MAXALIGN(((ltree_level*)(x))->len + LEVEL_HDRSIZE) ) )
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int32 len;
|
|
|
|
uint16 numlevel;
|
|
|
|
char data[1];
|
|
|
|
} ltree;
|
|
|
|
|
2002-08-04 13:02:50 +08:00
|
|
|
#define LTREE_HDRSIZE MAXALIGN( sizeof(int32) + sizeof(uint16) )
|
|
|
|
#define LTREE_FIRST(x) ( (ltree_level*)( ((char*)(x))+LTREE_HDRSIZE ) )
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* lquery */
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int4 val;
|
|
|
|
uint8 len;
|
|
|
|
uint8 flag;
|
|
|
|
char name[1];
|
|
|
|
} lquery_variant;
|
|
|
|
|
2002-08-04 13:02:50 +08:00
|
|
|
#define LVAR_HDRSIZE MAXALIGN(sizeof(uint8)*2 + sizeof(int4))
|
|
|
|
#define LVAR_NEXT(x) ( (lquery_variant*)( ((char*)(x)) + MAXALIGN(((lquery_variant*)(x))->len) + LVAR_HDRSIZE ) )
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
#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;
|
|
|
|
|
2002-08-04 13:02:50 +08:00
|
|
|
#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 ) )
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
#define LQL_NOT 0x10
|
|
|
|
#ifdef LOWER_NODE
|
|
|
|
#define FLG_CANLOOKSIGN(x) ( ( (x) & ( LQL_NOT | LVAR_ANYEND | LVAR_SUBLEXEM ) ) == 0 )
|
|
|
|
#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 )
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int32 len;
|
|
|
|
uint16 numlevel;
|
|
|
|
uint16 firstgood;
|
|
|
|
uint16 flag;
|
|
|
|
char data[1];
|
|
|
|
} lquery;
|
|
|
|
|
2002-08-04 13:02:50 +08:00
|
|
|
#define LQUERY_HDRSIZE MAXALIGN( sizeof(int32) + 3*sizeof(uint16) )
|
|
|
|
#define LQUERY_FIRST(x) ( (lquery_level*)( ((char*)(x))+LQUERY_HDRSIZE ) )
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
#define LQUERY_HASNOT 0x01
|
|
|
|
|
|
|
|
#ifndef max
|
|
|
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
#endif
|
|
|
|
#ifndef min
|
|
|
|
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
|
|
|
#endif
|
|
|
|
#ifndef abs
|
|
|
|
#define abs(a) ((a) < (0) ? -(a) : (a))
|
|
|
|
#endif
|
2002-08-11 04:45:48 +08:00
|
|
|
#define ISALNUM(x) ( isalnum((unsigned int)(x)) || (x) == '_' )
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
/* full text query */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* item in polish notation with back link
|
|
|
|
* to left operand
|
|
|
|
*/
|
|
|
|
typedef struct ITEM
|
|
|
|
{
|
|
|
|
int2 type;
|
|
|
|
int2 left;
|
|
|
|
int4 val;
|
|
|
|
uint8 flag;
|
|
|
|
/* user-friendly value */
|
|
|
|
uint8 length;
|
|
|
|
uint16 distance;
|
|
|
|
} ITEM;
|
|
|
|
|
|
|
|
/*
|
|
|
|
*Storage:
|
|
|
|
* (len)(size)(array of ITEM)(array of operand in user-friendly form)
|
|
|
|
*/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int4 len;
|
|
|
|
int4 size;
|
|
|
|
char data[1];
|
|
|
|
} ltxtquery;
|
|
|
|
|
2002-08-04 13:02:50 +08:00
|
|
|
#define HDRSIZEQT MAXALIGN( 2*sizeof(int4) )
|
2002-07-31 00:40:34 +08:00
|
|
|
#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 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
|
|
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* Concatenation functions */
|
|
|
|
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);
|
|
|
|
|
2002-08-11 04:46:24 +08:00
|
|
|
bool ltree_execute(ITEM * curitem, void *checkval,
|
2002-07-31 00:40:34 +08:00
|
|
|
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 );
|
2002-08-04 13:02:50 +08:00
|
|
|
ltree* lca_inner(ltree** a, int len);
|
2002-07-31 00:40:34 +08:00
|
|
|
|
|
|
|
#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))))
|
|
|
|
|
|
|
|
/* GiST support for ltree */
|
|
|
|
|
|
|
|
#define BITBYTE 8
|
|
|
|
#define SIGLENINT 8
|
|
|
|
#define SIGLEN ( sizeof(int4)*SIGLENINT )
|
|
|
|
#define SIGLENBIT (SIGLEN*BITBYTE)
|
|
|
|
typedef unsigned char BITVEC[SIGLEN];
|
|
|
|
typedef unsigned char *BITVECP;
|
|
|
|
|
|
|
|
#define LOOPBYTE(a) \
|
|
|
|
for(i=0;i<SIGLEN;i++) {\
|
|
|
|
a;\
|
|
|
|
}
|
|
|
|
#define LOOPBIT(a) \
|
|
|
|
for(i=0;i<SIGLENBIT;i++) {\
|
|
|
|
a;\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
|
|
|
|
#define GETBITBYTE(x,i) ( ((unsigned char)(x)) >> i & 0x01 )
|
|
|
|
#define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) )
|
|
|
|
#define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITBYTE ) )
|
|
|
|
#define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITBYTE )) & 0x01 )
|
|
|
|
|
|
|
|
#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)
|
|
|
|
#define HASH(sign, val) SETBIT((sign), HASHVAL(val))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* type of index key for ltree. Tree are combined B-Tree and R-Tree
|
|
|
|
* Storage:
|
|
|
|
* Leaf pages
|
|
|
|
* (len)(flag)(ltree)
|
|
|
|
* Non-Leaf
|
|
|
|
* (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;
|
|
|
|
|
|
|
|
#define LTG_ONENODE 0x01
|
|
|
|
#define LTG_ALLTRUE 0x02
|
|
|
|
#define LTG_NORIGHT 0x04
|
|
|
|
|
2002-08-04 13:02:50 +08:00
|
|
|
#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 ) )
|
2002-07-31 00:40:34 +08:00
|
|
|
#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 )
|
2002-08-04 13:02:50 +08:00
|
|
|
#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) )
|
2002-07-31 00:40:34 +08:00
|
|
|
#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) )
|
|
|
|
|
|
|
|
|
|
|
|
/* GiST support for ltree[] */
|
|
|
|
|
|
|
|
#define ASIGLENINT (2*SIGLENINT)
|
|
|
|
#define ASIGLEN (sizeof(int4)*ASIGLENINT)
|
|
|
|
#define ASIGLENBIT (ASIGLEN*BITBYTE)
|
|
|
|
typedef unsigned char ABITVEC[ASIGLEN];
|
|
|
|
|
|
|
|
#define ALOOPBYTE(a) \
|
|
|
|
for(i=0;i<ASIGLEN;i++) {\
|
|
|
|
a;\
|
|
|
|
}
|
|
|
|
#define ALOOPBIT(a) \
|
|
|
|
for(i=0;i<ASIGLENBIT;i++) {\
|
|
|
|
a;\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define AHASHVAL(val) (((unsigned int)(val)) % ASIGLENBIT)
|
|
|
|
#define AHASH(sign, val) SETBIT((sign), AHASHVAL(val))
|
|
|
|
|
|
|
|
/* type of key is the same to ltree_gist */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|