88 lines
2.5 KiB
C++
88 lines
2.5 KiB
C++
/*
|
|
* txtquery operations with ltree
|
|
* Teodor Sigaev <teodor@stack.net>
|
|
* contrib/ltree/ltxtquery_op.c
|
|
*/
|
|
#include "postgres.h"
|
|
#include "knl/knl_variable.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "ltree.h"
|
|
|
|
PG_FUNCTION_INFO_V1(ltxtq_exec);
|
|
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))
|
|
{
|
|
if (curitem->type == VAL)
|
|
return (*chkcond)(checkval, curitem);
|
|
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))
|
|
return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
|
|
else
|
|
return false;
|
|
} else { /* |-operator */
|
|
if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
|
|
return true;
|
|
else
|
|
return ltree_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) ? ltree_strncasecmp : strncmp;
|
|
while (tlen > 0) {
|
|
if (val->flag & LVAR_SUBLEXEME) {
|
|
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 = false;
|
|
|
|
chkval.node = val;
|
|
chkval.operand = GETOPERAND(query);
|
|
|
|
result = ltree_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)));
|
|
}
|