/* * txtquery operations with ltree * Teodor Sigaev */ #include "ltree.h" #include PG_FUNCTION_INFO_V1(ltxtq_exec); PG_FUNCTION_INFO_V1(ltxtq_rexec); /* * check for boolean condition */ bool 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) '!') { return (calcnot) ? ((execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true) : true; } else if (curitem->val == (int4) '&') { if (execute(curitem + curitem->left, checkval, calcnot, chkcond)) return execute(curitem + 1, checkval, calcnot, chkcond); else return false; } else { /* |-operator */ if (execute(curitem + curitem->left, checkval, calcnot, chkcond)) return true; else return execute(curitem + 1, checkval, calcnot, chkcond); } return false; } 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); 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 ) return true; tlen--; level = LEVEL_NEXT(level); } return false; } Datum ltxtq_exec(PG_FUNCTION_ARGS) { ltree *val = PG_GETARG_LTREE(0); ltxtquery *query = PG_GETARG_LTXTQUERY(1); CHKVAL chkval; bool result; chkval.node = val; chkval.operand = GETOPERAND(query); result = execute( GETQUERY(query), &chkval, true, checkcondition_str ); PG_FREE_IF_COPY(val, 0); PG_FREE_IF_COPY(query, 1); PG_RETURN_BOOL(result); } Datum ltxtq_rexec(PG_FUNCTION_ARGS) { PG_RETURN_DATUM( DirectFunctionCall2( ltxtq_exec, PG_GETARG_DATUM(1), PG_GETARG_DATUM(0) ) ); }