/* contrib/ltree/ltree.h */ #ifndef __LTREE_H__ #define __LTREE_H__ #include "fmgr.h" #include "tsearch/ts_locale.h" #include "utils/memutils.h" typedef struct { uint16 len; char name[1]; } ltree_level; #define LEVEL_HDRSIZE (offsetof(ltree_level, name)) #define LEVEL_NEXT(x) ((ltree_level*)(((char*)(x)) + MAXALIGN(((ltree_level*)(x))->len + LEVEL_HDRSIZE))) typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ uint16 numlevel; char data[1]; } ltree; #define LTREE_HDRSIZE MAXALIGN(offsetof(ltree, data)) #define LTREE_FIRST(x) ((ltree_level*)(((char*)(x)) + LTREE_HDRSIZE)) /* lquery */ typedef struct { int4 val; uint16 len; uint8 flag; char name[1]; } lquery_variant; #define LVAR_HDRSIZE MAXALIGN(offsetof(lquery_variant, name)) #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_SUBLEXEME 0x04 typedef struct { uint16 totallen; uint16 flag; uint16 numvar; uint16 low; uint16 high; char variants[1]; } lquery_level; #define LQL_HDRSIZE MAXALIGN(offsetof(lquery_level, variants)) #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 #ifdef LOWER_NODE #define FLG_CANLOOKSIGN(x) (((x) & (LQL_NOT | LVAR_ANYEND | LVAR_SUBLEXEME)) == 0) #else #define FLG_CANLOOKSIGN(x) (((x) & (LQL_NOT | LVAR_ANYEND | LVAR_SUBLEXEME | LVAR_INCASE)) == 0) #endif #define LQL_CANLOOKSIGN(x) FLG_CANLOOKSIGN(((lquery_level*)(x))->flag) typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ uint16 numlevel; uint16 firstgood; uint16 flag; char data[1]; } lquery; #define LQUERY_HDRSIZE MAXALIGN(offsetof(lquery, data)) #define LQUERY_FIRST(x) ((lquery_level*)(((char*)(x)) + LQUERY_HDRSIZE)) #define LQUERY_HASNOT 0x01 #define ISALNUM(x) (t_isalpha(x) || t_isdigit(x) || (pg_mblen(x) == 1 && t_iseq((x), '_'))) /* 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 { int32 vl_len_; /* varlena header (do not touch directly!) */ int4 size; char data[1]; } ltxtquery; #define HDRSIZEQT MAXALIGN(VARHDRSZ + sizeof(int4)) #define COMPUTESIZE(size, lenofoperand) (HDRSIZEQT + (size) * sizeof(ITEM) + (lenofoperand)) #define LTXTQUERY_TOO_BIG(size, lenofoperand) ((size) > (MaxAllocSize - HDRSIZEQT - (lenofoperand)) / sizeof(ITEM)) #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 */ extern "C" Datum ltree_isparent(PG_FUNCTION_ARGS); extern "C" Datum ltree_risparent(PG_FUNCTION_ARGS); extern "C" Datum ltq_regex(PG_FUNCTION_ARGS); extern "C" Datum ltq_rregex(PG_FUNCTION_ARGS); extern "C" Datum lt_q_regex(PG_FUNCTION_ARGS); extern "C" Datum lt_q_rregex(PG_FUNCTION_ARGS); extern "C" Datum ltxtq_exec(PG_FUNCTION_ARGS); extern "C" Datum ltxtq_rexec(PG_FUNCTION_ARGS); extern "C" Datum _ltq_regex(PG_FUNCTION_ARGS); extern "C" Datum _ltq_rregex(PG_FUNCTION_ARGS); extern "C" Datum _lt_q_regex(PG_FUNCTION_ARGS); extern "C" Datum _lt_q_rregex(PG_FUNCTION_ARGS); extern "C" Datum _ltxtq_exec(PG_FUNCTION_ARGS); extern "C" Datum _ltxtq_rexec(PG_FUNCTION_ARGS); extern "C" Datum _ltree_isparent(PG_FUNCTION_ARGS); extern "C" Datum _ltree_risparent(PG_FUNCTION_ARGS); /* Concatenation functions */ extern "C" Datum ltree_addltree(PG_FUNCTION_ARGS); extern "C" Datum ltree_addtext(PG_FUNCTION_ARGS); extern "C" Datum ltree_textadd(PG_FUNCTION_ARGS); /* Util function */ extern "C" Datum ltree_in(PG_FUNCTION_ARGS); bool ltree_execute(ITEM* curitem, void* checkval, 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_strncasecmp(const char* a, const char* b, size_t s); #define PG_GETARG_LTREE(x) ((ltree*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x)))) #define PG_GETARG_LTREE_COPY(x) ((ltree*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x)))) #define PG_GETARG_LQUERY(x) ((lquery*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x)))) #define PG_GETARG_LQUERY_COPY(x) ((lquery*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x)))) #define PG_GETARG_LTXTQUERY(x) ((ltxtquery*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x)))) #define PG_GETARG_LTXTQUERY_COPY(x) ((ltxtquery*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x)))) /* GiST support for ltree */ #define BITBYTE 8 #define SIGLENINT 2 #define SIGLEN (sizeof(int4) * SIGLENINT) #define SIGLENBIT (SIGLEN * BITBYTE) typedef unsigned char BITVEC[SIGLEN]; typedef unsigned char* BITVECP; #define LOOPBYTE for (i = 0; i < SIGLEN; i++) #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 { int32 vl_len_; /* varlena header (do not touch directly!) */ uint32 flag; char data[1]; } ltree_gist; #define LTG_ONENODE 0x01 #define LTG_ALLTRUE 0x02 #define LTG_NORIGHT 0x04 #define LTG_HDRSIZE MAXALIGN(VARHDRSZ + 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)) + VARSIZE(LTG_LNODE(x)))) #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 (7) #define ASIGLEN (sizeof(int4) * ASIGLENINT) #define ASIGLENBIT (ASIGLEN * BITBYTE) typedef unsigned char ABITVEC[ASIGLEN]; #define ALOOPBYTE for (i = 0; i < ASIGLEN; i++) #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