Line data Source code
1 : /*
2 : * txtquery operations with ltree
3 : * Teodor Sigaev <teodor@stack.net>
4 : * contrib/ltree/ltxtquery_op.c
5 : */
6 : #include "postgres.h"
7 :
8 : #include <ctype.h>
9 :
10 : #include "ltree.h"
11 : #include "miscadmin.h"
12 :
13 6 : PG_FUNCTION_INFO_V1(ltxtq_exec);
14 4 : PG_FUNCTION_INFO_V1(ltxtq_rexec);
15 :
16 : /*
17 : * check for boolean condition
18 : */
19 : bool
20 51488 : ltree_execute(ITEM *curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM *val))
21 : {
22 : /* since this function recurses, it could be driven to stack overflow */
23 51488 : check_stack_depth();
24 :
25 51488 : if (curitem->type == VAL)
26 29404 : return (*chkcond) (checkval, curitem);
27 22084 : else if (curitem->val == (int32) '!')
28 : {
29 : return calcnot ?
30 6 : ((ltree_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
31 12 : : true;
32 : }
33 22078 : else if (curitem->val == (int32) '&')
34 : {
35 22074 : if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
36 7324 : return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
37 : else
38 14750 : return false;
39 : }
40 : else
41 : { /* |-operator */
42 4 : if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
43 2 : return true;
44 : else
45 2 : return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
46 : }
47 : }
48 :
49 : typedef struct
50 : {
51 : ltree *node;
52 : char *operand;
53 : } CHKVAL;
54 :
55 : static bool
56 21526 : checkcondition_str(void *checkval, ITEM *val)
57 : {
58 21526 : ltree_level *level = LTREE_FIRST(((CHKVAL *) checkval)->node);
59 21526 : int tlen = ((CHKVAL *) checkval)->node->numlevel;
60 21526 : char *op = ((CHKVAL *) checkval)->operand + val->distance;
61 : int (*cmpptr) (const char *, const char *, size_t);
62 :
63 21526 : cmpptr = (val->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
64 144610 : while (tlen > 0)
65 : {
66 128384 : if (val->flag & LVAR_SUBLEXEME)
67 : {
68 8 : if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
69 2 : return true;
70 : }
71 128376 : else if ((val->length == level->len ||
72 128388 : (level->len > val->length && (val->flag & LVAR_ANYEND))) &&
73 78212 : (*cmpptr) (op, level->name, val->length) == 0)
74 5298 : return true;
75 :
76 123084 : tlen--;
77 123084 : level = LEVEL_NEXT(level);
78 : }
79 :
80 16226 : return false;
81 : }
82 :
83 : Datum
84 17360 : ltxtq_exec(PG_FUNCTION_ARGS)
85 : {
86 17360 : ltree *val = PG_GETARG_LTREE_P(0);
87 17360 : ltxtquery *query = PG_GETARG_LTXTQUERY_P(1);
88 : CHKVAL chkval;
89 : bool result;
90 :
91 17360 : chkval.node = val;
92 17360 : chkval.operand = GETOPERAND(query);
93 :
94 17360 : result = ltree_execute(GETQUERY(query),
95 : &chkval,
96 : true,
97 : checkcondition_str);
98 :
99 17360 : PG_FREE_IF_COPY(val, 0);
100 17360 : PG_FREE_IF_COPY(query, 1);
101 17360 : PG_RETURN_BOOL(result);
102 : }
103 :
104 : Datum
105 0 : ltxtq_rexec(PG_FUNCTION_ARGS)
106 : {
107 0 : PG_RETURN_DATUM(DirectFunctionCall2(ltxtq_exec,
108 : PG_GETARG_DATUM(1),
109 : PG_GETARG_DATUM(0)
110 : ));
111 : }
|