Age Owner TLA 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 :
7558 bruce 13 CBC 3 : PG_FUNCTION_INFO_V1(ltxtq_exec);
14 2 : PG_FUNCTION_INFO_V1(ltxtq_rexec);
15 :
16 : /*
17 : * check for boolean condition
18 : */
19 : bool
5050 20 25660 : 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 */
2743 noah 23 25660 : check_stack_depth();
24 :
7558 bruce 25 25660 : if (curitem->type == VAL)
26 14664 : return (*chkcond) (checkval, curitem);
3940 peter_e 27 10996 : else if (curitem->val == (int32) '!')
28 : {
29 : return calcnot ?
7547 bruce 30 3 : ((ltree_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
7558 31 6 : : true;
32 : }
3940 peter_e 33 10993 : else if (curitem->val == (int32) '&')
34 : {
7522 bruce 35 10991 : if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
7547 36 3670 : return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
37 : else
7558 38 7321 : return false;
39 : }
40 : else
41 : { /* |-operator */
7547 42 2 : if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
7558 43 1 : return true;
44 : else
7547 45 1 : 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
5050 56 10763 : checkcondition_str(void *checkval, ITEM *val)
57 : {
7522 58 10763 : ltree_level *level = LTREE_FIRST(((CHKVAL *) checkval)->node);
59 10763 : int tlen = ((CHKVAL *) checkval)->node->numlevel;
60 10763 : char *op = ((CHKVAL *) checkval)->operand + val->distance;
61 : int (*cmpptr) (const char *, const char *, size_t);
62 :
5396 teodor 63 10763 : cmpptr = (val->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
7522 bruce 64 72305 : while (tlen > 0)
65 : {
6248 neilc 66 64192 : if (val->flag & LVAR_SUBLEXEME)
67 : {
7522 bruce 68 4 : if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
7558 69 1 : return true;
70 : }
1165 alvherre 71 64188 : else if ((val->length == level->len ||
72 64194 : (level->len > val->length && (val->flag & LVAR_ANYEND))) &&
7522 bruce 73 39106 : (*cmpptr) (op, level->name, val->length) == 0)
7558 74 2649 : return true;
75 :
76 61542 : tlen--;
7522 77 61542 : level = LEVEL_NEXT(level);
78 : }
79 :
7558 80 8113 : return false;
81 : }
82 :
83 : Datum
7522 84 8680 : ltxtq_exec(PG_FUNCTION_ARGS)
85 : {
2029 tgl 86 8680 : ltree *val = PG_GETARG_LTREE_P(0);
87 8680 : ltxtquery *query = PG_GETARG_LTXTQUERY_P(1);
88 : CHKVAL chkval;
89 : bool result;
90 :
7558 bruce 91 8680 : chkval.node = val;
92 8680 : chkval.operand = GETOPERAND(query);
93 :
1165 alvherre 94 8680 : result = ltree_execute(GETQUERY(query),
95 : &chkval,
96 : true,
97 : checkcondition_str);
98 :
7558 bruce 99 8680 : PG_FREE_IF_COPY(val, 0);
100 8680 : PG_FREE_IF_COPY(query, 1);
101 8680 : PG_RETURN_BOOL(result);
102 : }
103 :
104 : Datum
7522 bruce 105 UBC 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 : }
|