2002-07-30 18:40:34 +02:00
|
|
|
/*
|
2002-09-04 22:31:48 +02:00
|
|
|
* txtquery operations with ltree
|
2002-07-30 18:40:34 +02:00
|
|
|
* Teodor Sigaev <teodor@stack.net>
|
2010-09-20 22:08:53 +02:00
|
|
|
* contrib/ltree/ltxtquery_op.c
|
2002-07-30 18:40:34 +02:00
|
|
|
*/
|
2008-05-12 02:00:54 +02:00
|
|
|
#include "postgres.h"
|
2002-07-30 18:40:34 +02:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
2008-05-12 02:00:54 +02:00
|
|
|
#include "ltree.h"
|
2015-10-05 16:06:30 +02:00
|
|
|
#include "miscadmin.h"
|
2008-05-12 02:00:54 +02:00
|
|
|
|
2002-07-30 18:40:34 +02:00
|
|
|
PG_FUNCTION_INFO_V1(ltxtq_exec);
|
|
|
|
PG_FUNCTION_INFO_V1(ltxtq_rexec);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check for boolean condition
|
|
|
|
*/
|
2002-09-04 22:31:48 +02:00
|
|
|
bool
|
2009-06-11 16:49:15 +02:00
|
|
|
ltree_execute(ITEM *curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM *val))
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
2015-10-05 16:06:30 +02:00
|
|
|
/* since this function recurses, it could be driven to stack overflow */
|
|
|
|
check_stack_depth();
|
|
|
|
|
2002-07-30 18:40:34 +02:00
|
|
|
if (curitem->type == VAL)
|
|
|
|
return (*chkcond) (checkval, curitem);
|
2012-06-25 00:51:46 +02:00
|
|
|
else if (curitem->val == (int32) '!')
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
2002-07-30 18:40:34 +02:00
|
|
|
return (calcnot) ?
|
2002-08-10 22:46:24 +02:00
|
|
|
((ltree_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
|
2002-07-30 18:40:34 +02:00
|
|
|
: true;
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
2012-06-25 00:51:46 +02:00
|
|
|
else if (curitem->val == (int32) '&')
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
|
|
|
if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
|
2002-08-10 22:46:24 +02:00
|
|
|
return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
|
2002-07-30 18:40:34 +02:00
|
|
|
else
|
|
|
|
return false;
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* |-operator */
|
2002-08-10 22:46:24 +02:00
|
|
|
if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
|
2002-07-30 18:40:34 +02:00
|
|
|
return true;
|
|
|
|
else
|
2002-08-10 22:46:24 +02:00
|
|
|
return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
|
2002-07-30 18:40:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
ltree *node;
|
|
|
|
char *operand;
|
2007-11-15 23:25:18 +01:00
|
|
|
} CHKVAL;
|
2002-07-30 18:40:34 +02:00
|
|
|
|
|
|
|
static bool
|
2009-06-11 16:49:15 +02:00
|
|
|
checkcondition_str(void *checkval, ITEM *val)
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
|
|
|
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);
|
2002-07-30 18:40:34 +02:00
|
|
|
|
2008-06-30 20:30:48 +02:00
|
|
|
cmpptr = (val->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
|
2002-09-04 22:31:48 +02:00
|
|
|
while (tlen > 0)
|
|
|
|
{
|
2006-03-01 07:30:32 +01:00
|
|
|
if (val->flag & LVAR_SUBLEXEME)
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
|
|
|
if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
|
2002-07-30 18:40:34 +02:00
|
|
|
return true;
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
|
|
|
else if (
|
|
|
|
(
|
|
|
|
val->length == level->len ||
|
|
|
|
(level->len > val->length && (val->flag & LVAR_ANYEND))
|
|
|
|
) &&
|
|
|
|
(*cmpptr) (op, level->name, val->length) == 0)
|
2002-07-30 18:40:34 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
tlen--;
|
2002-09-04 22:31:48 +02:00
|
|
|
level = LEVEL_NEXT(level);
|
2002-07-30 18:40:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
2002-09-04 22:31:48 +02:00
|
|
|
ltxtq_exec(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ltree *val = PG_GETARG_LTREE(0);
|
2002-07-30 18:40:34 +02:00
|
|
|
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
|
2002-09-04 22:31:48 +02:00
|
|
|
CHKVAL chkval;
|
|
|
|
bool result;
|
2002-07-30 18:40:34 +02:00
|
|
|
|
|
|
|
chkval.node = val;
|
|
|
|
chkval.operand = GETOPERAND(query);
|
|
|
|
|
2002-08-10 22:46:24 +02:00
|
|
|
result = ltree_execute(
|
2002-09-04 22:31:48 +02:00
|
|
|
GETQUERY(query),
|
|
|
|
&chkval,
|
|
|
|
true,
|
|
|
|
checkcondition_str
|
|
|
|
);
|
2002-07-30 18:40:34 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(val, 0);
|
|
|
|
PG_FREE_IF_COPY(query, 1);
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
2002-09-04 22:31:48 +02:00
|
|
|
ltxtq_rexec(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
PG_RETURN_DATUM(DirectFunctionCall2(ltxtq_exec,
|
|
|
|
PG_GETARG_DATUM(1),
|
|
|
|
PG_GETARG_DATUM(0)
|
|
|
|
));
|
2002-07-30 18:40:34 +02:00
|
|
|
}
|