openGauss-server/contrib/ltree/ltxtquery_op.cpp

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)));
}