Age Owner Branch data 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 : :
7929 bruce@momjian.us 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
5421 20 : 25436 : 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 */
3114 noah@leadboat.com 23 : 25436 : check_stack_depth();
24 : :
7929 bruce@momjian.us 25 [ + + ]: 25436 : if (curitem->type == VAL)
26 : 14553 : return (*chkcond) (checkval, curitem);
4311 peter_e@gmx.net 27 [ + + ]: 10883 : else if (curitem->val == (int32) '!')
28 : : {
29 : : return calcnot ?
7918 bruce@momjian.us 30 : 3 : ((ltree_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
7929 31 [ + - + + ]: 6 : : true;
32 : : }
4311 peter_e@gmx.net 33 [ + + ]: 10880 : else if (curitem->val == (int32) '&')
34 : : {
7893 bruce@momjian.us 35 [ + + ]: 10878 : if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
7918 36 : 3672 : return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
37 : : else
7929 38 : 7206 : return false;
39 : : }
40 : : else
41 : : { /* |-operator */
7918 42 [ + + ]: 2 : if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
7929 43 : 1 : return true;
44 : : else
7918 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
5421 56 : 10763 : checkcondition_str(void *checkval, ITEM *val)
57 : : {
7893 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 : :
5767 teodor@sigaev.ru 63 [ + + ]: 10763 : cmpptr = (val->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
7893 bruce@momjian.us 64 [ + + ]: 72305 : while (tlen > 0)
65 : : {
6619 neilc@samurai.com 66 [ + + ]: 64192 : if (val->flag & LVAR_SUBLEXEME)
67 : : {
7893 bruce@momjian.us 68 [ + + ]: 4 : if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
7929 69 : 1 : return true;
70 : : }
1536 alvherre@alvh.no-ip. 71 [ + + ]: 64188 : else if ((val->length == level->len ||
72 [ + + + + : 64194 : (level->len > val->length && (val->flag & LVAR_ANYEND))) &&
+ + ]
7893 bruce@momjian.us 73 : 39106 : (*cmpptr) (op, level->name, val->length) == 0)
7929 74 : 2649 : return true;
75 : :
76 : 61542 : tlen--;
7893 77 : 61542 : level = LEVEL_NEXT(level);
78 : : }
79 : :
7929 80 : 8113 : return false;
81 : : }
82 : :
83 : : Datum
7893 84 : 8680 : ltxtq_exec(PG_FUNCTION_ARGS)
85 : : {
2400 tgl@sss.pgh.pa.us 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 : :
7929 bruce@momjian.us 91 : 8680 : chkval.node = val;
92 : 8680 : chkval.operand = GETOPERAND(query);
93 : :
1536 alvherre@alvh.no-ip. 94 : 8680 : result = ltree_execute(GETQUERY(query),
95 : : &chkval,
96 : : true,
97 : : checkcondition_str);
98 : :
7929 bruce@momjian.us 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
7893 bruce@momjian.us 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 : : }
|