~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to contrib/intarray/_int_bool.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "_int.h"
 
2
 
 
3
PG_FUNCTION_INFO_V1(bqarr_in);
 
4
PG_FUNCTION_INFO_V1(bqarr_out);
 
5
Datum           bqarr_in(PG_FUNCTION_ARGS);
 
6
Datum           bqarr_out(PG_FUNCTION_ARGS);
 
7
 
 
8
PG_FUNCTION_INFO_V1(boolop);
 
9
Datum           boolop(PG_FUNCTION_ARGS);
 
10
 
 
11
PG_FUNCTION_INFO_V1(rboolop);
 
12
Datum           rboolop(PG_FUNCTION_ARGS);
 
13
 
 
14
PG_FUNCTION_INFO_V1(querytree);
 
15
Datum           querytree(PG_FUNCTION_ARGS);
 
16
 
 
17
 
 
18
#define END             0
 
19
#define ERR             1
 
20
#define VAL             2
 
21
#define OPR             3
 
22
#define OPEN    4
 
23
#define CLOSE   5
 
24
 
 
25
/* parser's states */
 
26
#define WAITOPERAND 1
 
27
#define WAITENDOPERAND  2
 
28
#define WAITOPERATOR    3
 
29
 
 
30
/*
 
31
 * node of query tree, also used
 
32
 * for storing polish notation in parser
 
33
 */
 
34
typedef struct NODE
 
35
{
 
36
        int4            type;
 
37
        int4            val;
 
38
        struct NODE *next;
 
39
}       NODE;
 
40
 
 
41
typedef struct
 
42
{
 
43
        char       *buf;
 
44
        int4            state;
 
45
        int4            count;
 
46
        /* reverse polish notation in list (for temporary usage) */
 
47
        NODE       *str;
 
48
        /* number in str */
 
49
        int4            num;
 
50
}       WORKSTATE;
 
51
 
 
52
/*
 
53
 * get token from query string
 
54
 */
 
55
static int4
 
56
gettoken(WORKSTATE * state, int4 *val)
 
57
{
 
58
        char            nnn[16],
 
59
                           *curnnn;
 
60
 
 
61
        curnnn = nnn;
 
62
        while (1)
 
63
        {
 
64
                switch (state->state)
 
65
                {
 
66
                        case WAITOPERAND:
 
67
                                curnnn = nnn;
 
68
                                if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
 
69
                                        *(state->buf) == '-')
 
70
                                {
 
71
                                        state->state = WAITENDOPERAND;
 
72
                                        *curnnn = *(state->buf);
 
73
                                        curnnn++;
 
74
                                }
 
75
                                else if (*(state->buf) == '!')
 
76
                                {
 
77
                                        (state->buf)++;
 
78
                                        *val = (int4) '!';
 
79
                                        return OPR;
 
80
                                }
 
81
                                else if (*(state->buf) == '(')
 
82
                                {
 
83
                                        state->count++;
 
84
                                        (state->buf)++;
 
85
                                        return OPEN;
 
86
                                }
 
87
                                else if (*(state->buf) != ' ')
 
88
                                        return ERR;
 
89
                                break;
 
90
                        case WAITENDOPERAND:
 
91
                                if (*(state->buf) >= '0' && *(state->buf) <= '9')
 
92
                                {
 
93
                                        *curnnn = *(state->buf);
 
94
                                        curnnn++;
 
95
                                }
 
96
                                else
 
97
                                {
 
98
                                        *curnnn = '\0';
 
99
                                        *val = (int4) atoi(nnn);
 
100
                                        state->state = WAITOPERATOR;
 
101
                                        return (state->count && *(state->buf) == '\0')
 
102
                                                ? ERR : VAL;
 
103
                                }
 
104
                                break;
 
105
                        case WAITOPERATOR:
 
106
                                if (*(state->buf) == '&' || *(state->buf) == '|')
 
107
                                {
 
108
                                        state->state = WAITOPERAND;
 
109
                                        *val = (int4) *(state->buf);
 
110
                                        (state->buf)++;
 
111
                                        return OPR;
 
112
                                }
 
113
                                else if (*(state->buf) == ')')
 
114
                                {
 
115
                                        (state->buf)++;
 
116
                                        state->count--;
 
117
                                        return (state->count < 0) ? ERR : CLOSE;
 
118
                                }
 
119
                                else if (*(state->buf) == '\0')
 
120
                                        return (state->count) ? ERR : END;
 
121
                                else if (*(state->buf) != ' ')
 
122
                                        return ERR;
 
123
                                break;
 
124
                        default:
 
125
                                return ERR;
 
126
                                break;
 
127
                }
 
128
                (state->buf)++;
 
129
        }
 
130
        return END;
 
131
}
 
132
 
 
133
/*
 
134
 * push new one in polish notation reverse view
 
135
 */
 
136
static void
 
137
pushquery(WORKSTATE * state, int4 type, int4 val)
 
138
{
 
139
        NODE       *tmp = (NODE *) palloc(sizeof(NODE));
 
140
 
 
141
        tmp->type = type;
 
142
        tmp->val = val;
 
143
        tmp->next = state->str;
 
144
        state->str = tmp;
 
145
        state->num++;
 
146
}
 
147
 
 
148
#define STACKDEPTH      16
 
149
 
 
150
/*
 
151
 * make polish notation of query
 
152
 */
 
153
static int4
 
154
makepol(WORKSTATE * state)
 
155
{
 
156
        int4            val,
 
157
                                type;
 
158
        int4            stack[STACKDEPTH];
 
159
        int4            lenstack = 0;
 
160
 
 
161
        while ((type = gettoken(state, &val)) != END)
 
162
        {
 
163
                switch (type)
 
164
                {
 
165
                        case VAL:
 
166
                                pushquery(state, type, val);
 
167
                                while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
 
168
                                                                        stack[lenstack - 1] == (int4) '!'))
 
169
                                {
 
170
                                        lenstack--;
 
171
                                        pushquery(state, OPR, stack[lenstack]);
 
172
                                }
 
173
                                break;
 
174
                        case OPR:
 
175
                                if (lenstack && val == (int4) '|')
 
176
                                        pushquery(state, OPR, val);
 
177
                                else
 
178
                                {
 
179
                                        if (lenstack == STACKDEPTH)
 
180
                                                ereport(ERROR,
 
181
                                                                (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
 
182
                                                                 errmsg("statement too complex")));
 
183
                                        stack[lenstack] = val;
 
184
                                        lenstack++;
 
185
                                }
 
186
                                break;
 
187
                        case OPEN:
 
188
                                if (makepol(state) == ERR)
 
189
                                        return ERR;
 
190
                                if (lenstack && (stack[lenstack - 1] == (int4) '&' ||
 
191
                                                                 stack[lenstack - 1] == (int4) '!'))
 
192
                                {
 
193
                                        lenstack--;
 
194
                                        pushquery(state, OPR, stack[lenstack]);
 
195
                                }
 
196
                                break;
 
197
                        case CLOSE:
 
198
                                while (lenstack)
 
199
                                {
 
200
                                        lenstack--;
 
201
                                        pushquery(state, OPR, stack[lenstack]);
 
202
                                };
 
203
                                return END;
 
204
                                break;
 
205
                        case ERR:
 
206
                        default:
 
207
                                ereport(ERROR,
 
208
                                                (errcode(ERRCODE_SYNTAX_ERROR),
 
209
                                                 errmsg("syntax error")));
 
210
                                return ERR;
 
211
 
 
212
                }
 
213
        }
 
214
 
 
215
        while (lenstack)
 
216
        {
 
217
                lenstack--;
 
218
                pushquery(state, OPR, stack[lenstack]);
 
219
        };
 
220
        return END;
 
221
}
 
222
 
 
223
typedef struct
 
224
{
 
225
        int4       *arrb;
 
226
        int4       *arre;
 
227
}       CHKVAL;
 
228
 
 
229
/*
 
230
 * is there value 'val' in array or not ?
 
231
 */
 
232
static bool
 
233
checkcondition_arr(void *checkval, int4 val)
 
234
{
 
235
        int4       *StopLow = ((CHKVAL *) checkval)->arrb;
 
236
        int4       *StopHigh = ((CHKVAL *) checkval)->arre;
 
237
        int4       *StopMiddle;
 
238
 
 
239
        /* Loop invariant: StopLow <= val < StopHigh */
 
240
 
 
241
        while (StopLow < StopHigh)
 
242
        {
 
243
                StopMiddle = StopLow + (StopHigh - StopLow) / 2;
 
244
                if (*StopMiddle == val)
 
245
                        return (true);
 
246
                else if (*StopMiddle < val)
 
247
                        StopLow = StopMiddle + 1;
 
248
                else
 
249
                        StopHigh = StopMiddle;
 
250
        }
 
251
        return false;
 
252
}
 
253
 
 
254
static bool
 
255
checkcondition_bit(void *checkval, int4 val)
 
256
{
 
257
        return GETBIT(checkval, HASHVAL(val));
 
258
}
 
259
 
 
260
/*
 
261
 * check for boolean condition
 
262
 */
 
263
static bool
 
264
execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, int4 val))
 
265
{
 
266
 
 
267
        if (curitem->type == VAL)
 
268
                return (*chkcond) (checkval, curitem->val);
 
269
        else if (curitem->val == (int4) '!')
 
270
        {
 
271
                return (calcnot) ?
 
272
                        ((execute(curitem - 1, checkval, calcnot, chkcond)) ? false : true)
 
273
                        : true;
 
274
        }
 
275
        else if (curitem->val == (int4) '&')
 
276
        {
 
277
                if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
 
278
                        return execute(curitem - 1, checkval, calcnot, chkcond);
 
279
                else
 
280
                        return false;
 
281
        }
 
282
        else
 
283
        {                                                       /* |-operator */
 
284
                if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
 
285
                        return true;
 
286
                else
 
287
                        return execute(curitem - 1, checkval, calcnot, chkcond);
 
288
        }
 
289
        return false;
 
290
}
 
291
 
 
292
/*
 
293
 * signconsistent & execconsistent called by *_consistent
 
294
 */
 
295
bool
 
296
signconsistent(QUERYTYPE * query, BITVEC sign, bool calcnot)
 
297
{
 
298
        return execute(
 
299
                                   GETQUERY(query) + query->size - 1,
 
300
                                   (void *) sign, calcnot,
 
301
                                   checkcondition_bit
 
302
                );
 
303
}
 
304
 
 
305
bool
 
306
execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot)
 
307
{
 
308
        CHKVAL          chkval;
 
309
 
 
310
        chkval.arrb = ARRPTR(array);
 
311
        chkval.arre = chkval.arrb + ARRNELEMS(array);
 
312
        return execute(
 
313
                                   GETQUERY(query) + query->size - 1,
 
314
                                   (void *) &chkval, calcnot,
 
315
                                   checkcondition_arr
 
316
                );
 
317
}
 
318
 
 
319
/*
 
320
 * boolean operations
 
321
 */
 
322
Datum
 
323
rboolop(PG_FUNCTION_ARGS)
 
324
{
 
325
        return DirectFunctionCall2(
 
326
                                                           boolop,
 
327
                                                           PG_GETARG_DATUM(1),
 
328
                                                           PG_GETARG_DATUM(0)
 
329
                );
 
330
}
 
331
 
 
332
Datum
 
333
boolop(PG_FUNCTION_ARGS)
 
334
{
 
335
        ArrayType  *val = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
 
336
        QUERYTYPE  *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
 
337
        CHKVAL          chkval;
 
338
        bool            result;
 
339
 
 
340
        if (ARRISVOID(val))
 
341
        {
 
342
                pfree(val);
 
343
                PG_FREE_IF_COPY(query, 1);
 
344
                PG_RETURN_BOOL(false);
 
345
        }
 
346
 
 
347
        PREPAREARR(val);
 
348
        chkval.arrb = ARRPTR(val);
 
349
        chkval.arre = chkval.arrb + ARRNELEMS(val);
 
350
        result = execute(
 
351
                                         GETQUERY(query) + query->size - 1,
 
352
                                         &chkval, true,
 
353
                                         checkcondition_arr
 
354
                );
 
355
        pfree(val);
 
356
 
 
357
        PG_FREE_IF_COPY(query, 1);
 
358
        PG_RETURN_BOOL(result);
 
359
}
 
360
 
 
361
static void
 
362
findoprnd(ITEM * ptr, int4 *pos)
 
363
{
 
364
#ifdef BS_DEBUG
 
365
        elog(DEBUG3, (ptr[*pos].type == OPR) ?
 
366
                 "%d  %c" : "%d  %d", *pos, ptr[*pos].val);
 
367
#endif
 
368
        if (ptr[*pos].type == VAL)
 
369
        {
 
370
                ptr[*pos].left = 0;
 
371
                (*pos)--;
 
372
        }
 
373
        else if (ptr[*pos].val == (int4) '!')
 
374
        {
 
375
                ptr[*pos].left = -1;
 
376
                (*pos)--;
 
377
                findoprnd(ptr, pos);
 
378
        }
 
379
        else
 
380
        {
 
381
                ITEM       *curitem = &ptr[*pos];
 
382
                int4            tmp = *pos;
 
383
 
 
384
                (*pos)--;
 
385
                findoprnd(ptr, pos);
 
386
                curitem->left = *pos - tmp;
 
387
                findoprnd(ptr, pos);
 
388
        }
 
389
}
 
390
 
 
391
 
 
392
/*
 
393
 * input
 
394
 */
 
395
Datum
 
396
bqarr_in(PG_FUNCTION_ARGS)
 
397
{
 
398
        char       *buf = (char *) PG_GETARG_POINTER(0);
 
399
        WORKSTATE       state;
 
400
        int4            i;
 
401
        QUERYTYPE  *query;
 
402
        int4            commonlen;
 
403
        ITEM       *ptr;
 
404
        NODE       *tmp;
 
405
        int4            pos = 0;
 
406
 
 
407
#ifdef BS_DEBUG
 
408
        StringInfoData pbuf;
 
409
#endif
 
410
 
 
411
        state.buf = buf;
 
412
        state.state = WAITOPERAND;
 
413
        state.count = 0;
 
414
        state.num = 0;
 
415
        state.str = NULL;
 
416
 
 
417
        /* make polish notation (postfix, but in reverse order) */
 
418
        makepol(&state);
 
419
        if (!state.num)
 
420
                ereport(ERROR,
 
421
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
422
                                 errmsg("empty query")));
 
423
 
 
424
        commonlen = COMPUTESIZE(state.num);
 
425
        query = (QUERYTYPE *) palloc(commonlen);
 
426
        query->len = commonlen;
 
427
        query->size = state.num;
 
428
        ptr = GETQUERY(query);
 
429
 
 
430
        for (i = state.num - 1; i >= 0; i--)
 
431
        {
 
432
                ptr[i].type = state.str->type;
 
433
                ptr[i].val = state.str->val;
 
434
                tmp = state.str->next;
 
435
                pfree(state.str);
 
436
                state.str = tmp;
 
437
        }
 
438
 
 
439
        pos = query->size - 1;
 
440
        findoprnd(ptr, &pos);
 
441
#ifdef BS_DEBUG
 
442
        initStringInfo(&pbuf);
 
443
        for (i = 0; i < query->size; i++)
 
444
        {
 
445
                if (ptr[i].type == OPR)
 
446
                        appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
 
447
                else
 
448
                        appendStringInfo(&pbuf, "%d ", ptr[i].val);
 
449
        }
 
450
        elog(DEBUG3, "POR: %s", pbuf.data);
 
451
        pfree(pbuf.data);
 
452
#endif
 
453
 
 
454
        PG_RETURN_POINTER(query);
 
455
}
 
456
 
 
457
 
 
458
/*
 
459
 * out function
 
460
 */
 
461
typedef struct
 
462
{
 
463
        ITEM       *curpol;
 
464
        char       *buf;
 
465
        char       *cur;
 
466
        int4            buflen;
 
467
}       INFIX;
 
468
 
 
469
#define RESIZEBUF(inf,addsize) while( ( inf->cur - inf->buf ) + addsize + 1 >= inf->buflen ) { \
 
470
        int4 len = inf->cur - inf->buf; \
 
471
        inf->buflen *= 2; \
 
472
        inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
 
473
        inf->cur = inf->buf + len; \
 
474
}
 
475
 
 
476
static void
 
477
infix(INFIX * in, bool first)
 
478
{
 
479
        if (in->curpol->type == VAL)
 
480
        {
 
481
                RESIZEBUF(in, 11);
 
482
                sprintf(in->cur, "%d", in->curpol->val);
 
483
                in->cur = strchr(in->cur, '\0');
 
484
                in->curpol--;
 
485
        }
 
486
        else if (in->curpol->val == (int4) '!')
 
487
        {
 
488
                bool            isopr = false;
 
489
 
 
490
                RESIZEBUF(in, 1);
 
491
                *(in->cur) = '!';
 
492
                in->cur++;
 
493
                *(in->cur) = '\0';
 
494
                in->curpol--;
 
495
                if (in->curpol->type == OPR)
 
496
                {
 
497
                        isopr = true;
 
498
                        RESIZEBUF(in, 2);
 
499
                        sprintf(in->cur, "( ");
 
500
                        in->cur = strchr(in->cur, '\0');
 
501
                }
 
502
                infix(in, isopr);
 
503
                if (isopr)
 
504
                {
 
505
                        RESIZEBUF(in, 2);
 
506
                        sprintf(in->cur, " )");
 
507
                        in->cur = strchr(in->cur, '\0');
 
508
                }
 
509
        }
 
510
        else
 
511
        {
 
512
                int4            op = in->curpol->val;
 
513
                INFIX           nrm;
 
514
 
 
515
                in->curpol--;
 
516
                if (op == (int4) '|' && !first)
 
517
                {
 
518
                        RESIZEBUF(in, 2);
 
519
                        sprintf(in->cur, "( ");
 
520
                        in->cur = strchr(in->cur, '\0');
 
521
                }
 
522
 
 
523
                nrm.curpol = in->curpol;
 
524
                nrm.buflen = 16;
 
525
                nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 
526
 
 
527
                /* get right operand */
 
528
                infix(&nrm, false);
 
529
 
 
530
                /* get & print left operand */
 
531
                in->curpol = nrm.curpol;
 
532
                infix(in, false);
 
533
 
 
534
                /* print operator & right operand */
 
535
                RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
 
536
                sprintf(in->cur, " %c %s", op, nrm.buf);
 
537
                in->cur = strchr(in->cur, '\0');
 
538
                pfree(nrm.buf);
 
539
 
 
540
                if (op == (int4) '|' && !first)
 
541
                {
 
542
                        RESIZEBUF(in, 2);
 
543
                        sprintf(in->cur, " )");
 
544
                        in->cur = strchr(in->cur, '\0');
 
545
                }
 
546
        }
 
547
}
 
548
 
 
549
 
 
550
Datum
 
551
bqarr_out(PG_FUNCTION_ARGS)
 
552
{
 
553
        QUERYTYPE  *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
 
554
        INFIX           nrm;
 
555
 
 
556
        if (query->size == 0)
 
557
                ereport(ERROR,
 
558
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
559
                                 errmsg("empty query")));
 
560
 
 
561
        nrm.curpol = GETQUERY(query) + query->size - 1;
 
562
        nrm.buflen = 32;
 
563
        nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 
564
        *(nrm.cur) = '\0';
 
565
        infix(&nrm, true);
 
566
 
 
567
        PG_FREE_IF_COPY(query, 0);
 
568
        PG_RETURN_POINTER(nrm.buf);
 
569
}
 
570
 
 
571
static int4
 
572
countdroptree(ITEM * q, int4 pos)
 
573
{
 
574
        if (q[pos].type == VAL)
 
575
                return 1;
 
576
        else if (q[pos].val == (int4) '!')
 
577
                return 1 + countdroptree(q, pos - 1);
 
578
        else
 
579
                return 1 + countdroptree(q, pos - 1) + countdroptree(q, pos + q[pos].left);
 
580
}
 
581
 
 
582
/*
 
583
 * common algorithm:
 
584
 * result of all '!' will be = 'true', so
 
585
 * we can modify query tree for clearing
 
586
 */
 
587
static int4
 
588
shorterquery(ITEM * q, int4 len)
 
589
{
 
590
        int4            index,
 
591
                                posnot,
 
592
                                poscor;
 
593
        bool            notisleft = false;
 
594
        int4            drop,
 
595
                                i;
 
596
 
 
597
        /* out all '!' */
 
598
        do
 
599
        {
 
600
                index = 0;
 
601
                drop = 0;
 
602
                /* find ! */
 
603
                for (posnot = 0; posnot < len; posnot++)
 
604
                        if (q[posnot].type == OPR && q[posnot].val == (int4) '!')
 
605
                        {
 
606
                                index = 1;
 
607
                                break;
 
608
                        }
 
609
 
 
610
                if (posnot == len)
 
611
                        return len;
 
612
 
 
613
                /* last operator is ! */
 
614
                if (posnot == len - 1)
 
615
                        return 0;
 
616
 
 
617
                /* find operator for this operand */
 
618
                for (poscor = posnot + 1; poscor < len; poscor++)
 
619
                {
 
620
                        if (q[poscor].type == OPR)
 
621
                        {
 
622
                                if (poscor == posnot + 1)
 
623
                                {
 
624
                                        notisleft = false;
 
625
                                        break;
 
626
                                }
 
627
                                else if (q[poscor].left + poscor == posnot)
 
628
                                {
 
629
                                        notisleft = true;
 
630
                                        break;
 
631
                                }
 
632
                        }
 
633
                }
 
634
                if (q[poscor].val == (int4) '!')
 
635
                {
 
636
                        drop = countdroptree(q, poscor);
 
637
                        q[poscor - 1].type = VAL;
 
638
                        for (i = poscor + 1; i < len; i++)
 
639
                                if (q[i].type == OPR && q[i].left + i <= poscor)
 
640
                                        q[i].left += drop - 2;
 
641
                        memcpy((void *) &q[poscor - drop + 1],
 
642
                                   (void *) &q[poscor - 1],
 
643
                                   sizeof(ITEM) * (len - (poscor - 1)));
 
644
                        len -= drop - 2;
 
645
                }
 
646
                else if (q[poscor].val == (int4) '|')
 
647
                {
 
648
                        drop = countdroptree(q, poscor);
 
649
                        q[poscor - 1].type = VAL;
 
650
                        q[poscor].val = (int4) '!';
 
651
                        q[poscor].left = -1;
 
652
                        for (i = poscor + 1; i < len; i++)
 
653
                                if (q[i].type == OPR && q[i].left + i < poscor)
 
654
                                        q[i].left += drop - 2;
 
655
                        memcpy((void *) &q[poscor - drop + 1],
 
656
                                   (void *) &q[poscor - 1],
 
657
                                   sizeof(ITEM) * (len - (poscor - 1)));
 
658
                        len -= drop - 2;
 
659
                }
 
660
                else
 
661
                {                                               /* &-operator */
 
662
                        if (
 
663
                                (notisleft && q[poscor - 1].type == OPR &&
 
664
                                 q[poscor - 1].val == (int4) '!') ||
 
665
                                (!notisleft && q[poscor + q[poscor].left].type == OPR &&
 
666
                                 q[poscor + q[poscor].left].val == (int4) '!')
 
667
                                )
 
668
                        {                                       /* drop subtree */
 
669
                                drop = countdroptree(q, poscor);
 
670
                                q[poscor - 1].type = VAL;
 
671
                                q[poscor].val = (int4) '!';
 
672
                                q[poscor].left = -1;
 
673
                                for (i = poscor + 1; i < len; i++)
 
674
                                        if (q[i].type == OPR && q[i].left + i < poscor)
 
675
                                                q[i].left += drop - 2;
 
676
                                memcpy((void *) &q[poscor - drop + 1],
 
677
                                           (void *) &q[poscor - 1],
 
678
                                           sizeof(ITEM) * (len - (poscor - 1)));
 
679
                                len -= drop - 2;
 
680
                        }
 
681
                        else
 
682
                        {                                       /* drop only operator */
 
683
                                int4            subtreepos = (notisleft) ?
 
684
                                poscor - 1 : poscor + q[poscor].left;
 
685
                                int4            subtreelen = countdroptree(q, subtreepos);
 
686
 
 
687
                                drop = countdroptree(q, poscor);
 
688
                                for (i = poscor + 1; i < len; i++)
 
689
                                        if (q[i].type == OPR && q[i].left + i < poscor)
 
690
                                                q[i].left += drop - subtreelen;
 
691
                                memcpy((void *) &q[subtreepos + 1],
 
692
                                           (void *) &q[poscor + 1],
 
693
                                           sizeof(ITEM) * (len - (poscor - 1)));
 
694
                                memcpy((void *) &q[poscor - drop + 1],
 
695
                                           (void *) &q[subtreepos - subtreelen + 1],
 
696
                                           sizeof(ITEM) * (len - (drop - subtreelen)));
 
697
                                len -= drop - subtreelen;
 
698
                        }
 
699
                }
 
700
        } while (index);
 
701
        return len;
 
702
}
 
703
 
 
704
 
 
705
Datum
 
706
querytree(PG_FUNCTION_ARGS)
 
707
{
 
708
        QUERYTYPE  *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
 
709
        INFIX           nrm;
 
710
        text       *res;
 
711
        ITEM       *q;
 
712
        int4            len;
 
713
 
 
714
        if (query->size == 0)
 
715
                ereport(ERROR,
 
716
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
717
                                 errmsg("empty query")));
 
718
 
 
719
        q = (ITEM *) palloc(sizeof(ITEM) * query->size);
 
720
        memcpy((void *) q, GETQUERY(query), sizeof(ITEM) * query->size);
 
721
        len = shorterquery(q, query->size);
 
722
        PG_FREE_IF_COPY(query, 0);
 
723
 
 
724
        if (len == 0)
 
725
        {
 
726
                res = (text *) palloc(1 + VARHDRSZ);
 
727
                VARATT_SIZEP(res) = 1 + VARHDRSZ;
 
728
                *((char *) VARDATA(res)) = 'T';
 
729
        }
 
730
        else
 
731
        {
 
732
                nrm.curpol = q + len - 1;
 
733
                nrm.buflen = 32;
 
734
                nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 
735
                *(nrm.cur) = '\0';
 
736
                infix(&nrm, true);
 
737
 
 
738
                res = (text *) palloc(nrm.cur - nrm.buf + VARHDRSZ);
 
739
                VARATT_SIZEP(res) = nrm.cur - nrm.buf + VARHDRSZ;
 
740
                strncpy(VARDATA(res), nrm.buf, nrm.cur - nrm.buf);
 
741
        }
 
742
        pfree(q);
 
743
 
 
744
        PG_RETURN_POINTER(res);
 
745
}