Age Owner TLA Line data Source code
1 : /*
2 : * contrib/intarray/_int_bool.c
3 : */
4 : #include "postgres.h"
5 :
6 : #include "_int.h"
7 : #include "miscadmin.h"
8 : #include "utils/builtins.h"
9 :
7242 bruce 10 CBC 2 : PG_FUNCTION_INFO_V1(bqarr_in);
11 2 : PG_FUNCTION_INFO_V1(bqarr_out);
12 2 : PG_FUNCTION_INFO_V1(boolop);
13 1 : PG_FUNCTION_INFO_V1(rboolop);
14 1 : PG_FUNCTION_INFO_V1(querytree);
15 :
16 :
17 : /* parser's states */
18 : #define WAITOPERAND 1
19 : #define WAITENDOPERAND 2
20 : #define WAITOPERATOR 3
21 :
22 : /*
23 : * node of query tree, also used
24 : * for storing polish notation in parser
25 : */
26 : typedef struct NODE
27 : {
28 : int32 type;
29 : int32 val;
30 : struct NODE *next;
31 : } NODE;
32 :
33 : typedef struct
34 : {
35 : char *buf;
36 : int32 state;
37 : int32 count;
38 : struct Node *escontext;
39 : /* reverse polish notation in list (for temporary usage) */
40 : NODE *str;
41 : /* number in str */
42 : int32 num;
43 : } WORKSTATE;
44 :
45 : /*
46 : * get token from query string
47 : */
48 : static int32
3940 peter_e 49 GIC 515 : gettoken(WORKSTATE *state, int32 *val)
7242 bruce 50 ECB : {
51 : char nnn[16];
52 : int innn;
53 :
6406 tgl 54 GIC 515 : *val = 0; /* default result */
6406 tgl 55 ECB :
4455 tgl 56 GIC 515 : innn = 0;
7242 bruce 57 ECB : while (1)
58 : {
4455 tgl 59 GIC 821 : if (innn >= sizeof(nnn))
4455 tgl 60 LBC 0 : return ERR; /* buffer overrun => syntax error */
7242 bruce 61 GBC 821 : switch (state->state)
7242 bruce 62 ECB : {
7242 bruce 63 GIC 297 : case WAITOPERAND:
4455 tgl 64 CBC 297 : innn = 0;
7242 bruce 65 297 : if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
66 106 : *(state->buf) == '-')
7242 bruce 67 ECB : {
7242 bruce 68 GIC 191 : state->state = WAITENDOPERAND;
4455 tgl 69 CBC 191 : nnn[innn++] = *(state->buf);
7242 bruce 70 ECB : }
7242 bruce 71 GIC 106 : else if (*(state->buf) == '!')
7242 bruce 72 ECB : {
7242 bruce 73 GIC 45 : (state->buf)++;
3940 peter_e 74 CBC 45 : *val = (int32) '!';
7242 bruce 75 45 : return OPR;
7242 bruce 76 ECB : }
7242 bruce 77 GIC 61 : else if (*(state->buf) == '(')
7242 bruce 78 ECB : {
7242 bruce 79 GIC 43 : state->count++;
7242 bruce 80 CBC 43 : (state->buf)++;
81 43 : return OPEN;
7242 bruce 82 ECB : }
7242 bruce 83 GIC 18 : else if (*(state->buf) != ' ')
7242 bruce 84 CBC 2 : return ERR;
85 207 : break;
86 275 : case WAITENDOPERAND:
87 275 : if (*(state->buf) >= '0' && *(state->buf) <= '9')
7242 bruce 88 ECB : {
4455 tgl 89 GIC 84 : nnn[innn++] = *(state->buf);
7242 bruce 90 ECB : }
91 : else
92 : {
93 : long lval;
94 :
4455 tgl 95 GIC 191 : nnn[innn] = '\0';
4455 tgl 96 CBC 191 : errno = 0;
97 191 : lval = strtol(nnn, NULL, 0);
3940 peter_e 98 191 : *val = (int32) lval;
4455 tgl 99 191 : if (errno != 0 || (long) *val != lval)
4455 tgl 100 LBC 0 : return ERR;
7242 bruce 101 GBC 191 : state->state = WAITOPERATOR;
7242 bruce 102 CBC 72 : return (state->count && *(state->buf) == '\0')
103 263 : ? ERR : VAL;
7242 bruce 104 ECB : }
7242 bruce 105 GIC 84 : break;
7242 bruce 106 CBC 249 : case WAITOPERATOR:
107 249 : if (*(state->buf) == '&' || *(state->buf) == '|')
7242 bruce 108 ECB : {
7242 bruce 109 GIC 114 : state->state = WAITOPERAND;
3940 peter_e 110 CBC 114 : *val = (int32) *(state->buf);
7242 bruce 111 114 : (state->buf)++;
112 114 : return OPR;
7242 bruce 113 ECB : }
7242 bruce 114 GIC 135 : else if (*(state->buf) == ')')
7242 bruce 115 ECB : {
7242 bruce 116 GIC 43 : (state->buf)++;
7242 bruce 117 CBC 43 : state->count--;
118 43 : return (state->count < 0) ? ERR : CLOSE;
7242 bruce 119 ECB : }
7242 bruce 120 GIC 92 : else if (*(state->buf) == '\0')
7242 bruce 121 CBC 75 : return (state->count) ? ERR : END;
122 17 : else if (*(state->buf) != ' ')
123 2 : return ERR;
124 15 : break;
7242 bruce 125 LBC 0 : default:
7242 bruce 126 UBC 0 : return ERR;
7242 bruce 127 EUB : break;
128 : }
7242 bruce 129 GIC 306 : (state->buf)++;
7242 bruce 130 ECB : }
131 : }
132 :
133 : /*
134 : * push new one in polish notation reverse view
135 : */
136 : static void
3940 peter_e 137 GIC 350 : pushquery(WORKSTATE *state, int32 type, int32 val)
7242 bruce 138 ECB : {
7242 bruce 139 GIC 350 : NODE *tmp = (NODE *) palloc(sizeof(NODE));
7242 bruce 140 ECB :
7242 bruce 141 GIC 350 : tmp->type = type;
7242 bruce 142 CBC 350 : tmp->val = val;
143 350 : tmp->next = state->str;
144 350 : state->str = tmp;
145 350 : state->num++;
146 350 : }
7242 bruce 147 ECB :
148 : #define STACKDEPTH 16
149 :
150 : /*
151 : * make polish notation of query
152 : */
153 : static int32
5050 bruce 154 GIC 122 : makepol(WORKSTATE *state)
7242 bruce 155 ECB : {
156 : int32 val,
157 : type;
158 : int32 stack[STACKDEPTH];
3940 peter_e 159 GIC 122 : int32 lenstack = 0;
7242 bruce 160 ECB :
161 : /* since this function recurses, it could be driven to stack overflow */
4473 tgl 162 GIC 122 : check_stack_depth();
4473 tgl 163 ECB :
7242 bruce 164 GIC 515 : while ((type = gettoken(state, &val)) != END)
7242 bruce 165 ECB : {
7242 bruce 166 GIC 440 : switch (type)
7242 bruce 167 ECB : {
7242 bruce 168 GIC 191 : case VAL:
7242 bruce 169 CBC 191 : pushquery(state, type, val);
3940 peter_e 170 280 : while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
171 78 : stack[lenstack - 1] == (int32) '!'))
7242 bruce 172 ECB : {
7242 bruce 173 GIC 89 : lenstack--;
7242 bruce 174 CBC 89 : pushquery(state, OPR, stack[lenstack]);
7242 bruce 175 ECB : }
7242 bruce 176 GIC 191 : break;
7242 bruce 177 CBC 159 : case OPR:
3940 peter_e 178 159 : if (lenstack && val == (int32) '|')
7242 bruce 179 3 : pushquery(state, OPR, val);
7242 bruce 180 ECB : else
181 : {
7242 bruce 182 GIC 156 : if (lenstack == STACKDEPTH)
102 andrew 183 UNC 0 : ereturn(state->escontext, ERR,
7199 tgl 184 EUB : (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
185 : errmsg("statement too complex")));
7242 bruce 186 GIC 156 : stack[lenstack] = val;
7242 bruce 187 CBC 156 : lenstack++;
7242 bruce 188 ECB : }
7242 bruce 189 GIC 159 : break;
7242 bruce 190 CBC 43 : case OPEN:
191 43 : if (makepol(state) == ERR)
7242 bruce 192 LBC 0 : return ERR;
3940 peter_e 193 GBC 66 : while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
3940 peter_e 194 CBC 18 : stack[lenstack - 1] == (int32) '!'))
7242 bruce 195 ECB : {
7242 bruce 196 GIC 23 : lenstack--;
7242 bruce 197 CBC 23 : pushquery(state, OPR, stack[lenstack]);
7242 bruce 198 ECB : }
7242 bruce 199 GIC 43 : break;
7242 bruce 200 CBC 43 : case CLOSE:
201 57 : while (lenstack)
7242 bruce 202 ECB : {
7242 bruce 203 GIC 14 : lenstack--;
7242 bruce 204 CBC 14 : pushquery(state, OPR, stack[lenstack]);
7242 bruce 205 ECB : };
7242 bruce 206 GIC 43 : return END;
7242 bruce 207 ECB : break;
7242 bruce 208 GIC 4 : case ERR:
7242 bruce 209 ECB : default:
102 andrew 210 GNC 4 : ereturn(state->escontext, ERR,
7199 tgl 211 ECB : (errcode(ERRCODE_SYNTAX_ERROR),
212 : errmsg("syntax error")));
213 : }
214 : }
215 :
7242 bruce 216 CBC 105 : while (lenstack)
217 : {
218 30 : lenstack--;
219 30 : pushquery(state, OPR, stack[lenstack]);
220 : };
221 75 : return END;
222 : }
223 :
224 : typedef struct
225 : {
226 : int32 *arrb;
227 : int32 *arre;
228 : } CHKVAL;
229 :
230 : /*
231 : * is there value 'val' in (sorted) array or not ?
232 : */
233 : static bool
1105 akorotkov 234 223162 : checkcondition_arr(void *checkval, ITEM *item, void *options)
235 : {
3940 peter_e 236 223162 : int32 *StopLow = ((CHKVAL *) checkval)->arrb;
237 223162 : int32 *StopHigh = ((CHKVAL *) checkval)->arre;
238 : int32 *StopMiddle;
239 :
240 : /* Loop invariant: StopLow <= val < StopHigh */
241 :
7242 bruce 242 770743 : while (StopLow < StopHigh)
243 : {
244 556778 : StopMiddle = StopLow + (StopHigh - StopLow) / 2;
6185 teodor 245 556778 : if (*StopMiddle == item->val)
2061 peter_e 246 9197 : return true;
6185 teodor 247 547581 : else if (*StopMiddle < item->val)
7242 bruce 248 129422 : StopLow = StopMiddle + 1;
249 : else
250 418159 : StopHigh = StopMiddle;
251 : }
252 213965 : return false;
253 : }
254 :
255 : static bool
1105 akorotkov 256 43839 : checkcondition_bit(void *checkval, ITEM *item, void *siglen)
257 : {
1060 tgl 258 43839 : return GETBIT(checkval, HASHVAL(item->val, (int) (intptr_t) siglen));
259 : }
260 :
261 : /*
262 : * evaluate boolean expression, using chkcond() to test the primitive cases
263 : */
264 : static bool
1105 akorotkov 265 693384 : execute(ITEM *curitem, void *checkval, void *options, bool calcnot,
266 : bool (*chkcond) (void *checkval, ITEM *item, void *options))
267 : {
268 : /* since this function recurses, it could be driven to stack overflow */
4473 tgl 269 693384 : check_stack_depth();
270 :
7242 bruce 271 693384 : if (curitem->type == VAL)
1105 akorotkov 272 295991 : return (*chkcond) (checkval, curitem, options);
3940 peter_e 273 397393 : else if (curitem->val == (int32) '!')
274 : {
275 : return calcnot ?
1105 akorotkov 276 118943 : ((execute(curitem - 1, checkval, options, calcnot, chkcond)) ? false : true)
7242 bruce 277 291288 : : true;
278 : }
3940 peter_e 279 225048 : else if (curitem->val == (int32) '&')
280 : {
1105 akorotkov 281 121854 : if (execute(curitem + curitem->left, checkval, options, calcnot, chkcond))
282 62355 : return execute(curitem - 1, checkval, options, calcnot, chkcond);
283 : else
7242 bruce 284 59499 : return false;
285 : }
286 : else
287 : { /* |-operator */
1105 akorotkov 288 103194 : if (execute(curitem + curitem->left, checkval, options, calcnot, chkcond))
7242 bruce 289 5706 : return true;
290 : else
1105 akorotkov 291 97488 : return execute(curitem - 1, checkval, options, calcnot, chkcond);
292 : }
293 : }
294 :
295 : /*
296 : * signconsistent & execconsistent called by *_consistent
297 : */
298 : bool
299 50701 : signconsistent(QUERYTYPE *query, BITVECP sign, int siglen, bool calcnot)
300 : {
4473 tgl 301 101402 : return execute(GETQUERY(query) + query->size - 1,
1060 302 50701 : (void *) sign, (void *) (intptr_t) siglen, calcnot,
303 : checkcondition_bit);
304 : }
305 :
306 : /* Array must be sorted! */
307 : bool
5050 bruce 308 55498 : execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
309 : {
310 : CHKVAL chkval;
311 :
6350 tgl 312 55498 : CHECKARRVALID(array);
7242 bruce 313 55498 : chkval.arrb = ARRPTR(array);
314 55498 : chkval.arre = chkval.arrb + ARRNELEMS(array);
4473 tgl 315 55498 : return execute(GETQUERY(query) + query->size - 1,
316 : (void *) &chkval, NULL, calcnot,
317 : checkcondition_arr);
318 : }
319 :
320 : typedef struct
321 : {
322 : ITEM *first;
323 : bool *mapped_check;
324 : } GinChkVal;
325 :
326 : static bool
1105 akorotkov 327 28990 : checkcondition_gin(void *checkval, ITEM *item, void *options)
328 : {
6031 bruce 329 28990 : GinChkVal *gcv = (GinChkVal *) checkval;
330 :
331 28990 : return gcv->mapped_check[item - gcv->first];
332 : }
333 :
334 : bool
4473 tgl 335 14901 : gin_bool_consistent(QUERYTYPE *query, bool *check)
336 : {
337 : GinChkVal gcv;
6031 bruce 338 14901 : ITEM *items = GETQUERY(query);
339 : int i,
340 14901 : j = 0;
341 :
4473 tgl 342 14901 : if (query->size <= 0)
2062 peter_e 343 UBC 0 : return false;
344 :
345 : /*
346 : * Set up data for checkcondition_gin. This must agree with the query
347 : * extraction code in ginint4_queryextract.
348 : */
6185 teodor 349 CBC 14901 : gcv.first = items;
6031 bruce 350 14901 : gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
351 82210 : for (i = 0; i < query->size; i++)
352 : {
353 67309 : if (items[i].type == VAL)
354 30964 : gcv.mapped_check[i] = check[j++];
355 : }
356 :
4473 tgl 357 14901 : return execute(GETQUERY(query) + query->size - 1,
358 : (void *) &gcv, NULL, true,
359 : checkcondition_gin);
360 : }
361 :
362 : static bool
363 36 : contains_required_value(ITEM *curitem)
364 : {
365 : /* since this function recurses, it could be driven to stack overflow */
366 36 : check_stack_depth();
367 :
368 36 : if (curitem->type == VAL)
369 14 : return true;
3940 peter_e 370 22 : else if (curitem->val == (int32) '!')
371 : {
372 : /*
373 : * Assume anything under a NOT is non-required. For some cases with
374 : * nested NOTs, we could prove there's a required value, but it seems
375 : * unlikely to be worth the trouble.
376 : */
4473 tgl 377 6 : return false;
378 : }
3940 peter_e 379 16 : else if (curitem->val == (int32) '&')
380 : {
381 : /* If either side has a required value, we're good */
4473 tgl 382 10 : if (contains_required_value(curitem + curitem->left))
383 8 : return true;
384 : else
385 2 : return contains_required_value(curitem - 1);
386 : }
387 : else
388 : { /* |-operator */
389 : /* Both sides must have required values */
390 6 : if (contains_required_value(curitem + curitem->left))
391 6 : return contains_required_value(curitem - 1);
392 : else
4473 tgl 393 UBC 0 : return false;
394 : }
395 : }
396 :
397 : bool
4473 tgl 398 CBC 12 : query_has_required_values(QUERYTYPE *query)
399 : {
400 12 : if (query->size <= 0)
4473 tgl 401 UBC 0 : return false;
4473 tgl 402 CBC 12 : return contains_required_value(GETQUERY(query) + query->size - 1);
403 : }
404 :
405 : /*
406 : * boolean operations
407 : */
408 : Datum
7242 bruce 409 UBC 0 : rboolop(PG_FUNCTION_ARGS)
410 : {
411 : /* just reverse the operands */
4473 tgl 412 0 : return DirectFunctionCall2(boolop,
413 : PG_GETARG_DATUM(1),
414 : PG_GETARG_DATUM(0));
415 : }
416 :
417 : Datum
7242 bruce 418 CBC 68450 : boolop(PG_FUNCTION_ARGS)
419 : {
4473 tgl 420 68450 : ArrayType *val = PG_GETARG_ARRAYTYPE_P_COPY(0);
421 68450 : QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(1);
422 : CHKVAL chkval;
423 : bool result;
424 :
6350 425 68450 : CHECKARRVALID(val);
7242 bruce 426 68450 : PREPAREARR(val);
427 68450 : chkval.arrb = ARRPTR(val);
428 68450 : chkval.arre = chkval.arrb + ARRNELEMS(val);
4473 tgl 429 68450 : result = execute(GETQUERY(query) + query->size - 1,
430 : &chkval, NULL, true,
431 : checkcondition_arr);
7242 bruce 432 68450 : pfree(val);
433 :
434 68450 : PG_FREE_IF_COPY(query, 1);
435 68450 : PG_RETURN_BOOL(result);
436 : }
437 :
438 : static void
3940 peter_e 439 348 : findoprnd(ITEM *ptr, int32 *pos)
440 : {
441 : /* since this function recurses, it could be driven to stack overflow. */
3338 noah 442 348 : check_stack_depth();
443 :
444 : #ifdef BS_DEBUG
445 : elog(DEBUG3, (ptr[*pos].type == OPR) ?
446 : "%d %c" : "%d %d", *pos, ptr[*pos].val);
447 : #endif
7242 bruce 448 348 : if (ptr[*pos].type == VAL)
449 : {
450 189 : ptr[*pos].left = 0;
451 189 : (*pos)--;
452 : }
3940 peter_e 453 159 : else if (ptr[*pos].val == (int32) '!')
454 : {
7242 bruce 455 45 : ptr[*pos].left = -1;
456 45 : (*pos)--;
457 45 : findoprnd(ptr, pos);
458 : }
459 : else
460 : {
461 114 : ITEM *curitem = &ptr[*pos];
3940 peter_e 462 114 : int32 tmp = *pos;
463 :
7242 bruce 464 114 : (*pos)--;
465 114 : findoprnd(ptr, pos);
466 114 : curitem->left = *pos - tmp;
467 114 : findoprnd(ptr, pos);
468 : }
469 348 : }
470 :
471 :
472 : /*
473 : * input
474 : */
475 : Datum
476 79 : bqarr_in(PG_FUNCTION_ARGS)
477 : {
478 79 : char *buf = (char *) PG_GETARG_POINTER(0);
479 : WORKSTATE state;
480 : int32 i;
481 : QUERYTYPE *query;
482 : int32 commonlen;
483 : ITEM *ptr;
484 : NODE *tmp;
3940 peter_e 485 79 : int32 pos = 0;
102 andrew 486 GNC 79 : struct Node *escontext = fcinfo->context;
7242 bruce 487 ECB :
488 : #ifdef BS_DEBUG
489 : StringInfoData pbuf;
490 : #endif
491 :
7242 bruce 492 GIC 79 : state.buf = buf;
7242 bruce 493 CBC 79 : state.state = WAITOPERAND;
494 79 : state.count = 0;
495 79 : state.num = 0;
496 79 : state.str = NULL;
102 andrew 497 GNC 79 : state.escontext = escontext;
7242 bruce 498 ECB :
499 : /* make polish notation (postfix, but in reverse order) */
102 andrew 500 GNC 79 : if (makepol(&state) == ERR)
501 4 : PG_RETURN_NULL();
7242 bruce 502 GIC 75 : if (!state.num)
102 andrew 503 UNC 0 : ereturn(escontext, (Datum) 0,
7199 tgl 504 ECB : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
505 : errmsg("empty query")));
7242 bruce 506 EUB :
3338 noah 507 GIC 75 : if (state.num > QUERYTYPEMAXITEMS)
102 andrew 508 UNC 0 : ereturn(escontext, (Datum) 0,
509 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2118 tgl 510 ECB : errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
2118 tgl 511 EUB : state.num, (int) QUERYTYPEMAXITEMS)));
7242 bruce 512 GIC 75 : commonlen = COMPUTESIZE(state.num);
513 :
514 75 : query = (QUERYTYPE *) palloc(commonlen);
5884 tgl 515 CBC 75 : SET_VARSIZE(query, commonlen);
7242 bruce 516 GIC 75 : query->size = state.num;
7242 bruce 517 CBC 75 : ptr = GETQUERY(query);
7242 bruce 518 ECB :
7242 bruce 519 CBC 423 : for (i = state.num - 1; i >= 0; i--)
7242 bruce 520 ECB : {
7242 bruce 521 GIC 348 : ptr[i].type = state.str->type;
7242 bruce 522 CBC 348 : ptr[i].val = state.str->val;
7242 bruce 523 GIC 348 : tmp = state.str->next;
7242 bruce 524 CBC 348 : pfree(state.str);
525 348 : state.str = tmp;
7242 bruce 526 ECB : }
527 :
7242 bruce 528 CBC 75 : pos = query->size - 1;
7242 bruce 529 GIC 75 : findoprnd(ptr, &pos);
530 : #ifdef BS_DEBUG
7242 bruce 531 ECB : initStringInfo(&pbuf);
532 : for (i = 0; i < query->size; i++)
533 : {
534 : if (ptr[i].type == OPR)
535 : appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
536 : else
537 : appendStringInfo(&pbuf, "%d ", ptr[i].val);
538 : }
539 : elog(DEBUG3, "POR: %s", pbuf.data);
540 : pfree(pbuf.data);
541 : #endif
542 :
7242 bruce 543 GIC 75 : PG_RETURN_POINTER(query);
544 : }
545 :
7242 bruce 546 ECB :
547 : /*
548 : * out function
549 : */
550 : typedef struct
551 : {
552 : ITEM *curpol;
553 : char *buf;
554 : char *cur;
555 : int32 buflen;
556 : } INFIX;
557 :
558 : #define RESIZEBUF(inf,addsize) while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) { \
559 : int32 len = inf->cur - inf->buf; \
560 : inf->buflen *= 2; \
561 : inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
562 : inf->cur = inf->buf + len; \
563 : }
564 :
565 : static void
5624 bruce 566 GIC 180 : infix(INFIX *in, bool first)
567 : {
568 : /* since this function recurses, it could be driven to stack overflow. */
2743 noah 569 CBC 180 : check_stack_depth();
570 :
7242 bruce 571 GIC 180 : if (in->curpol->type == VAL)
7242 bruce 572 ECB : {
7242 bruce 573 GIC 95 : RESIZEBUF(in, 11);
7242 bruce 574 CBC 95 : sprintf(in->cur, "%d", in->curpol->val);
7242 bruce 575 GIC 95 : in->cur = strchr(in->cur, '\0');
7242 bruce 576 CBC 95 : in->curpol--;
7242 bruce 577 ECB : }
3940 peter_e 578 CBC 85 : else if (in->curpol->val == (int32) '!')
7242 bruce 579 ECB : {
7242 bruce 580 GIC 27 : bool isopr = false;
7242 bruce 581 ECB :
7242 bruce 582 GIC 27 : RESIZEBUF(in, 1);
7242 bruce 583 CBC 27 : *(in->cur) = '!';
7242 bruce 584 GIC 27 : in->cur++;
7242 bruce 585 CBC 27 : *(in->cur) = '\0';
586 27 : in->curpol--;
587 27 : if (in->curpol->type == OPR)
7242 bruce 588 ECB : {
7242 bruce 589 CBC 6 : isopr = true;
590 6 : RESIZEBUF(in, 2);
7242 bruce 591 GIC 6 : sprintf(in->cur, "( ");
7242 bruce 592 CBC 6 : in->cur = strchr(in->cur, '\0');
7242 bruce 593 ECB : }
7242 bruce 594 CBC 27 : infix(in, isopr);
595 27 : if (isopr)
596 : {
597 6 : RESIZEBUF(in, 2);
598 6 : sprintf(in->cur, " )");
7242 bruce 599 GIC 6 : in->cur = strchr(in->cur, '\0');
7242 bruce 600 ECB : }
601 : }
602 : else
603 : {
3940 peter_e 604 GIC 58 : int32 op = in->curpol->val;
605 : INFIX nrm;
606 :
7242 bruce 607 CBC 58 : in->curpol--;
3940 peter_e 608 GIC 58 : if (op == (int32) '|' && !first)
609 : {
7242 bruce 610 CBC 10 : RESIZEBUF(in, 2);
611 10 : sprintf(in->cur, "( ");
7242 bruce 612 GIC 10 : in->cur = strchr(in->cur, '\0');
7242 bruce 613 ECB : }
614 :
7242 bruce 615 CBC 58 : nrm.curpol = in->curpol;
7242 bruce 616 GIC 58 : nrm.buflen = 16;
617 58 : nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
7242 bruce 618 ECB :
619 : /* get right operand */
7242 bruce 620 CBC 58 : infix(&nrm, false);
621 :
622 : /* get & print left operand */
623 58 : in->curpol = nrm.curpol;
7242 bruce 624 GIC 58 : infix(in, false);
625 :
7242 bruce 626 ECB : /* print operator & right operand */
7242 bruce 627 CBC 62 : RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
7242 bruce 628 GIC 58 : sprintf(in->cur, " %c %s", op, nrm.buf);
629 58 : in->cur = strchr(in->cur, '\0');
7242 bruce 630 CBC 58 : pfree(nrm.buf);
7242 bruce 631 ECB :
3940 peter_e 632 CBC 58 : if (op == (int32) '|' && !first)
7242 bruce 633 ECB : {
7242 bruce 634 GIC 10 : RESIZEBUF(in, 2);
7242 bruce 635 CBC 10 : sprintf(in->cur, " )");
7242 bruce 636 GIC 10 : in->cur = strchr(in->cur, '\0');
7242 bruce 637 ECB : }
638 : }
7242 bruce 639 CBC 180 : }
640 :
641 :
7242 bruce 642 ECB : Datum
7242 bruce 643 GIC 37 : bqarr_out(PG_FUNCTION_ARGS)
644 : {
4473 tgl 645 37 : QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
7242 bruce 646 ECB : INFIX nrm;
647 :
7242 bruce 648 CBC 37 : if (query->size == 0)
7199 tgl 649 UIC 0 : ereport(ERROR,
650 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7199 tgl 651 ECB : errmsg("empty query")));
7199 tgl 652 EUB :
7242 bruce 653 GIC 37 : nrm.curpol = GETQUERY(query) + query->size - 1;
654 37 : nrm.buflen = 32;
655 37 : nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
7242 bruce 656 CBC 37 : *(nrm.cur) = '\0';
657 37 : infix(&nrm, true);
7242 bruce 658 ECB :
7242 bruce 659 CBC 37 : PG_FREE_IF_COPY(query, 0);
660 37 : PG_RETURN_POINTER(nrm.buf);
661 : }
7242 bruce 662 ECB :
663 :
664 : /* Useless old "debugging" function for a fundamentally wrong algorithm */
665 : Datum
7242 bruce 666 UIC 0 : querytree(PG_FUNCTION_ARGS)
667 : {
4473 tgl 668 0 : elog(ERROR, "querytree is no longer implemented");
4473 tgl 669 EUB : PG_RETURN_NULL();
670 : }
|