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);
8 PG_FUNCTION_INFO_V1(boolop);
9 Datum boolop(PG_FUNCTION_ARGS);
11 PG_FUNCTION_INFO_V1(rboolop);
12 Datum rboolop(PG_FUNCTION_ARGS);
14 PG_FUNCTION_INFO_V1(querytree);
15 Datum querytree(PG_FUNCTION_ARGS);
27 #define WAITENDOPERAND 2
28 #define WAITOPERATOR 3
31 * node of query tree, also used
32 * for storing polish notation in parser
46 /* reverse polish notation in list (for temporary usage) */
53 * get token from query string
56 gettoken(WORKSTATE * state, int4 *val)
61 *val = 0; /* default result */
70 if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
73 state->state = WAITENDOPERAND;
74 *curnnn = *(state->buf);
77 else if (*(state->buf) == '!')
83 else if (*(state->buf) == '(')
89 else if (*(state->buf) != ' ')
93 if (*(state->buf) >= '0' && *(state->buf) <= '9')
95 *curnnn = *(state->buf);
101 *val = (int4) atoi(nnn);
102 state->state = WAITOPERATOR;
103 return (state->count && *(state->buf) == '\0')
108 if (*(state->buf) == '&' || *(state->buf) == '|')
110 state->state = WAITOPERAND;
111 *val = (int4) *(state->buf);
115 else if (*(state->buf) == ')')
119 return (state->count < 0) ? ERR : CLOSE;
121 else if (*(state->buf) == '\0')
122 return (state->count) ? ERR : END;
123 else if (*(state->buf) != ' ')
136 * push new one in polish notation reverse view
139 pushquery(WORKSTATE * state, int4 type, int4 val)
141 NODE *tmp = (NODE *) palloc(sizeof(NODE));
145 tmp->next = state->str;
150 #define STACKDEPTH 16
153 * make polish notation of query
156 makepol(WORKSTATE * state)
160 int4 stack[STACKDEPTH];
163 while ((type = gettoken(state, &val)) != END)
168 pushquery(state, type, val);
169 while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
170 stack[lenstack - 1] == (int4) '!'))
173 pushquery(state, OPR, stack[lenstack]);
177 if (lenstack && val == (int4) '|')
178 pushquery(state, OPR, val);
181 if (lenstack == STACKDEPTH)
183 (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
184 errmsg("statement too complex")));
185 stack[lenstack] = val;
190 if (makepol(state) == ERR)
192 if (lenstack && (stack[lenstack - 1] == (int4) '&' ||
193 stack[lenstack - 1] == (int4) '!'))
196 pushquery(state, OPR, stack[lenstack]);
203 pushquery(state, OPR, stack[lenstack]);
210 (errcode(ERRCODE_SYNTAX_ERROR),
211 errmsg("syntax error")));
220 pushquery(state, OPR, stack[lenstack]);
232 * is there value 'val' in array or not ?
235 checkcondition_arr(void *checkval, int4 val)
237 int4 *StopLow = ((CHKVAL *) checkval)->arrb;
238 int4 *StopHigh = ((CHKVAL *) checkval)->arre;
241 /* Loop invariant: StopLow <= val < StopHigh */
243 while (StopLow < StopHigh)
245 StopMiddle = StopLow + (StopHigh - StopLow) / 2;
246 if (*StopMiddle == val)
248 else if (*StopMiddle < val)
249 StopLow = StopMiddle + 1;
251 StopHigh = StopMiddle;
257 checkcondition_bit(void *checkval, int4 val)
259 return GETBIT(checkval, HASHVAL(val));
263 * check for boolean condition
266 execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, int4 val))
269 if (curitem->type == VAL)
270 return (*chkcond) (checkval, curitem->val);
271 else if (curitem->val == (int4) '!')
274 ((execute(curitem - 1, checkval, calcnot, chkcond)) ? false : true)
277 else if (curitem->val == (int4) '&')
279 if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
280 return execute(curitem - 1, checkval, calcnot, chkcond);
286 if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
289 return execute(curitem - 1, checkval, calcnot, chkcond);
295 * signconsistent & execconsistent called by *_consistent
298 signconsistent(QUERYTYPE * query, BITVEC sign, bool calcnot)
301 GETQUERY(query) + query->size - 1,
302 (void *) sign, calcnot,
308 execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot)
312 CHECKARRVALID(array);
313 chkval.arrb = ARRPTR(array);
314 chkval.arre = chkval.arrb + ARRNELEMS(array);
316 GETQUERY(query) + query->size - 1,
317 (void *) &chkval, calcnot,
326 rboolop(PG_FUNCTION_ARGS)
328 return DirectFunctionCall2(
336 boolop(PG_FUNCTION_ARGS)
338 ArrayType *val = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
339 QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
347 PG_FREE_IF_COPY(query, 1);
348 PG_RETURN_BOOL(false);
352 chkval.arrb = ARRPTR(val);
353 chkval.arre = chkval.arrb + ARRNELEMS(val);
355 GETQUERY(query) + query->size - 1,
361 PG_FREE_IF_COPY(query, 1);
362 PG_RETURN_BOOL(result);
366 findoprnd(ITEM * ptr, int4 *pos)
369 elog(DEBUG3, (ptr[*pos].type == OPR) ?
370 "%d %c" : "%d %d", *pos, ptr[*pos].val);
372 if (ptr[*pos].type == VAL)
377 else if (ptr[*pos].val == (int4) '!')
385 ITEM *curitem = &ptr[*pos];
390 curitem->left = *pos - tmp;
400 bqarr_in(PG_FUNCTION_ARGS)
402 char *buf = (char *) PG_GETARG_POINTER(0);
416 state.state = WAITOPERAND;
421 /* make polish notation (postfix, but in reverse order) */
425 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
426 errmsg("empty query")));
428 commonlen = COMPUTESIZE(state.num);
429 query = (QUERYTYPE *) palloc(commonlen);
430 query->len = commonlen;
431 query->size = state.num;
432 ptr = GETQUERY(query);
434 for (i = state.num - 1; i >= 0; i--)
436 ptr[i].type = state.str->type;
437 ptr[i].val = state.str->val;
438 tmp = state.str->next;
443 pos = query->size - 1;
444 findoprnd(ptr, &pos);
446 initStringInfo(&pbuf);
447 for (i = 0; i < query->size; i++)
449 if (ptr[i].type == OPR)
450 appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
452 appendStringInfo(&pbuf, "%d ", ptr[i].val);
454 elog(DEBUG3, "POR: %s", pbuf.data);
458 PG_RETURN_POINTER(query);
473 #define RESIZEBUF(inf,addsize) while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) { \
474 int4 len = inf->cur - inf->buf; \
476 inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
477 inf->cur = inf->buf + len; \
481 infix(INFIX * in, bool first)
483 if (in->curpol->type == VAL)
486 sprintf(in->cur, "%d", in->curpol->val);
487 in->cur = strchr(in->cur, '\0');
490 else if (in->curpol->val == (int4) '!')
499 if (in->curpol->type == OPR)
503 sprintf(in->cur, "( ");
504 in->cur = strchr(in->cur, '\0');
510 sprintf(in->cur, " )");
511 in->cur = strchr(in->cur, '\0');
516 int4 op = in->curpol->val;
520 if (op == (int4) '|' && !first)
523 sprintf(in->cur, "( ");
524 in->cur = strchr(in->cur, '\0');
527 nrm.curpol = in->curpol;
529 nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
531 /* get right operand */
534 /* get & print left operand */
535 in->curpol = nrm.curpol;
538 /* print operator & right operand */
539 RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
540 sprintf(in->cur, " %c %s", op, nrm.buf);
541 in->cur = strchr(in->cur, '\0');
544 if (op == (int4) '|' && !first)
547 sprintf(in->cur, " )");
548 in->cur = strchr(in->cur, '\0');
555 bqarr_out(PG_FUNCTION_ARGS)
557 QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
560 if (query->size == 0)
562 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
563 errmsg("empty query")));
565 nrm.curpol = GETQUERY(query) + query->size - 1;
567 nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
571 PG_FREE_IF_COPY(query, 0);
572 PG_RETURN_POINTER(nrm.buf);
576 countdroptree(ITEM * q, int4 pos)
578 if (q[pos].type == VAL)
580 else if (q[pos].val == (int4) '!')
581 return 1 + countdroptree(q, pos - 1);
583 return 1 + countdroptree(q, pos - 1) + countdroptree(q, pos + q[pos].left);
588 * result of all '!' will be = 'true', so
589 * we can modify query tree for clearing
592 shorterquery(ITEM * q, int4 len)
597 bool notisleft = false;
607 for (posnot = 0; posnot < len; posnot++)
608 if (q[posnot].type == OPR && q[posnot].val == (int4) '!')
617 /* last operator is ! */
618 if (posnot == len - 1)
621 /* find operator for this operand */
622 for (poscor = posnot + 1; poscor < len; poscor++)
624 if (q[poscor].type == OPR)
626 if (poscor == posnot + 1)
631 else if (q[poscor].left + poscor == posnot)
638 if (q[poscor].val == (int4) '!')
640 drop = countdroptree(q, poscor);
641 q[poscor - 1].type = VAL;
642 for (i = poscor + 1; i < len; i++)
643 if (q[i].type == OPR && q[i].left + i <= poscor)
644 q[i].left += drop - 2;
645 memcpy((void *) &q[poscor - drop + 1],
646 (void *) &q[poscor - 1],
647 sizeof(ITEM) * (len - (poscor - 1)));
650 else if (q[poscor].val == (int4) '|')
652 drop = countdroptree(q, poscor);
653 q[poscor - 1].type = VAL;
654 q[poscor].val = (int4) '!';
656 for (i = poscor + 1; i < len; i++)
657 if (q[i].type == OPR && q[i].left + i < poscor)
658 q[i].left += drop - 2;
659 memcpy((void *) &q[poscor - drop + 1],
660 (void *) &q[poscor - 1],
661 sizeof(ITEM) * (len - (poscor - 1)));
667 (notisleft && q[poscor - 1].type == OPR &&
668 q[poscor - 1].val == (int4) '!') ||
669 (!notisleft && q[poscor + q[poscor].left].type == OPR &&
670 q[poscor + q[poscor].left].val == (int4) '!')
673 drop = countdroptree(q, poscor);
674 q[poscor - 1].type = VAL;
675 q[poscor].val = (int4) '!';
677 for (i = poscor + 1; i < len; i++)
678 if (q[i].type == OPR && q[i].left + i < poscor)
679 q[i].left += drop - 2;
680 memcpy((void *) &q[poscor - drop + 1],
681 (void *) &q[poscor - 1],
682 sizeof(ITEM) * (len - (poscor - 1)));
686 { /* drop only operator */
687 int4 subtreepos = (notisleft) ?
688 poscor - 1 : poscor + q[poscor].left;
689 int4 subtreelen = countdroptree(q, subtreepos);
691 drop = countdroptree(q, poscor);
692 for (i = poscor + 1; i < len; i++)
693 if (q[i].type == OPR && q[i].left + i < poscor)
694 q[i].left += drop - subtreelen;
695 memcpy((void *) &q[subtreepos + 1],
696 (void *) &q[poscor + 1],
697 sizeof(ITEM) * (len - (poscor - 1)));
698 memcpy((void *) &q[poscor - drop + 1],
699 (void *) &q[subtreepos - subtreelen + 1],
700 sizeof(ITEM) * (len - (drop - subtreelen)));
701 len -= drop - subtreelen;
710 querytree(PG_FUNCTION_ARGS)
712 QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
718 if (query->size == 0)
720 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
721 errmsg("empty query")));
723 q = (ITEM *) palloc(sizeof(ITEM) * query->size);
724 memcpy((void *) q, GETQUERY(query), sizeof(ITEM) * query->size);
725 len = shorterquery(q, query->size);
726 PG_FREE_IF_COPY(query, 0);
730 res = (text *) palloc(1 + VARHDRSZ);
731 VARATT_SIZEP(res) = 1 + VARHDRSZ;
732 *((char *) VARDATA(res)) = 'T';
736 nrm.curpol = q + len - 1;
738 nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
742 res = (text *) palloc(nrm.cur - nrm.buf + VARHDRSZ);
743 VARATT_SIZEP(res) = nrm.cur - nrm.buf + VARHDRSZ;
744 strncpy(VARDATA(res), nrm.buf, nrm.cur - nrm.buf);
748 PG_RETURN_POINTER(res);