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)
68
if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
71
state->state = WAITENDOPERAND;
72
*curnnn = *(state->buf);
75
else if (*(state->buf) == '!')
81
else if (*(state->buf) == '(')
87
else if (*(state->buf) != ' ')
91
if (*(state->buf) >= '0' && *(state->buf) <= '9')
93
*curnnn = *(state->buf);
99
*val = (int4) atoi(nnn);
100
state->state = WAITOPERATOR;
101
return (state->count && *(state->buf) == '\0')
106
if (*(state->buf) == '&' || *(state->buf) == '|')
108
state->state = WAITOPERAND;
109
*val = (int4) *(state->buf);
113
else if (*(state->buf) == ')')
117
return (state->count < 0) ? ERR : CLOSE;
119
else if (*(state->buf) == '\0')
120
return (state->count) ? ERR : END;
121
else if (*(state->buf) != ' ')
134
* push new one in polish notation reverse view
137
pushquery(WORKSTATE * state, int4 type, int4 val)
139
NODE *tmp = (NODE *) palloc(sizeof(NODE));
143
tmp->next = state->str;
148
#define STACKDEPTH 16
151
* make polish notation of query
154
makepol(WORKSTATE * state)
158
int4 stack[STACKDEPTH];
161
while ((type = gettoken(state, &val)) != END)
166
pushquery(state, type, val);
167
while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
168
stack[lenstack - 1] == (int4) '!'))
171
pushquery(state, OPR, stack[lenstack]);
175
if (lenstack && val == (int4) '|')
176
pushquery(state, OPR, val);
179
if (lenstack == STACKDEPTH)
181
(errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
182
errmsg("statement too complex")));
183
stack[lenstack] = val;
188
if (makepol(state) == ERR)
190
if (lenstack && (stack[lenstack - 1] == (int4) '&' ||
191
stack[lenstack - 1] == (int4) '!'))
194
pushquery(state, OPR, stack[lenstack]);
201
pushquery(state, OPR, stack[lenstack]);
208
(errcode(ERRCODE_SYNTAX_ERROR),
209
errmsg("syntax error")));
218
pushquery(state, OPR, stack[lenstack]);
230
* is there value 'val' in array or not ?
233
checkcondition_arr(void *checkval, int4 val)
235
int4 *StopLow = ((CHKVAL *) checkval)->arrb;
236
int4 *StopHigh = ((CHKVAL *) checkval)->arre;
239
/* Loop invariant: StopLow <= val < StopHigh */
241
while (StopLow < StopHigh)
243
StopMiddle = StopLow + (StopHigh - StopLow) / 2;
244
if (*StopMiddle == val)
246
else if (*StopMiddle < val)
247
StopLow = StopMiddle + 1;
249
StopHigh = StopMiddle;
255
checkcondition_bit(void *checkval, int4 val)
257
return GETBIT(checkval, HASHVAL(val));
261
* check for boolean condition
264
execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, int4 val))
267
if (curitem->type == VAL)
268
return (*chkcond) (checkval, curitem->val);
269
else if (curitem->val == (int4) '!')
272
((execute(curitem - 1, checkval, calcnot, chkcond)) ? false : true)
275
else if (curitem->val == (int4) '&')
277
if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
278
return execute(curitem - 1, checkval, calcnot, chkcond);
284
if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
287
return execute(curitem - 1, checkval, calcnot, chkcond);
293
* signconsistent & execconsistent called by *_consistent
296
signconsistent(QUERYTYPE * query, BITVEC sign, bool calcnot)
299
GETQUERY(query) + query->size - 1,
300
(void *) sign, calcnot,
306
execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot)
310
chkval.arrb = ARRPTR(array);
311
chkval.arre = chkval.arrb + ARRNELEMS(array);
313
GETQUERY(query) + query->size - 1,
314
(void *) &chkval, calcnot,
323
rboolop(PG_FUNCTION_ARGS)
325
return DirectFunctionCall2(
333
boolop(PG_FUNCTION_ARGS)
335
ArrayType *val = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
336
QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
343
PG_FREE_IF_COPY(query, 1);
344
PG_RETURN_BOOL(false);
348
chkval.arrb = ARRPTR(val);
349
chkval.arre = chkval.arrb + ARRNELEMS(val);
351
GETQUERY(query) + query->size - 1,
357
PG_FREE_IF_COPY(query, 1);
358
PG_RETURN_BOOL(result);
362
findoprnd(ITEM * ptr, int4 *pos)
365
elog(DEBUG3, (ptr[*pos].type == OPR) ?
366
"%d %c" : "%d %d", *pos, ptr[*pos].val);
368
if (ptr[*pos].type == VAL)
373
else if (ptr[*pos].val == (int4) '!')
381
ITEM *curitem = &ptr[*pos];
386
curitem->left = *pos - tmp;
396
bqarr_in(PG_FUNCTION_ARGS)
398
char *buf = (char *) PG_GETARG_POINTER(0);
412
state.state = WAITOPERAND;
417
/* make polish notation (postfix, but in reverse order) */
421
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
422
errmsg("empty query")));
424
commonlen = COMPUTESIZE(state.num);
425
query = (QUERYTYPE *) palloc(commonlen);
426
query->len = commonlen;
427
query->size = state.num;
428
ptr = GETQUERY(query);
430
for (i = state.num - 1; i >= 0; i--)
432
ptr[i].type = state.str->type;
433
ptr[i].val = state.str->val;
434
tmp = state.str->next;
439
pos = query->size - 1;
440
findoprnd(ptr, &pos);
442
initStringInfo(&pbuf);
443
for (i = 0; i < query->size; i++)
445
if (ptr[i].type == OPR)
446
appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
448
appendStringInfo(&pbuf, "%d ", ptr[i].val);
450
elog(DEBUG3, "POR: %s", pbuf.data);
454
PG_RETURN_POINTER(query);
469
#define RESIZEBUF(inf,addsize) while( ( inf->cur - inf->buf ) + addsize + 1 >= inf->buflen ) { \
470
int4 len = inf->cur - inf->buf; \
472
inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
473
inf->cur = inf->buf + len; \
477
infix(INFIX * in, bool first)
479
if (in->curpol->type == VAL)
482
sprintf(in->cur, "%d", in->curpol->val);
483
in->cur = strchr(in->cur, '\0');
486
else if (in->curpol->val == (int4) '!')
495
if (in->curpol->type == OPR)
499
sprintf(in->cur, "( ");
500
in->cur = strchr(in->cur, '\0');
506
sprintf(in->cur, " )");
507
in->cur = strchr(in->cur, '\0');
512
int4 op = in->curpol->val;
516
if (op == (int4) '|' && !first)
519
sprintf(in->cur, "( ");
520
in->cur = strchr(in->cur, '\0');
523
nrm.curpol = in->curpol;
525
nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
527
/* get right operand */
530
/* get & print left operand */
531
in->curpol = nrm.curpol;
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');
540
if (op == (int4) '|' && !first)
543
sprintf(in->cur, " )");
544
in->cur = strchr(in->cur, '\0');
551
bqarr_out(PG_FUNCTION_ARGS)
553
QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
556
if (query->size == 0)
558
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
559
errmsg("empty query")));
561
nrm.curpol = GETQUERY(query) + query->size - 1;
563
nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
567
PG_FREE_IF_COPY(query, 0);
568
PG_RETURN_POINTER(nrm.buf);
572
countdroptree(ITEM * q, int4 pos)
574
if (q[pos].type == VAL)
576
else if (q[pos].val == (int4) '!')
577
return 1 + countdroptree(q, pos - 1);
579
return 1 + countdroptree(q, pos - 1) + countdroptree(q, pos + q[pos].left);
584
* result of all '!' will be = 'true', so
585
* we can modify query tree for clearing
588
shorterquery(ITEM * q, int4 len)
593
bool notisleft = false;
603
for (posnot = 0; posnot < len; posnot++)
604
if (q[posnot].type == OPR && q[posnot].val == (int4) '!')
613
/* last operator is ! */
614
if (posnot == len - 1)
617
/* find operator for this operand */
618
for (poscor = posnot + 1; poscor < len; poscor++)
620
if (q[poscor].type == OPR)
622
if (poscor == posnot + 1)
627
else if (q[poscor].left + poscor == posnot)
634
if (q[poscor].val == (int4) '!')
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)));
646
else if (q[poscor].val == (int4) '|')
648
drop = countdroptree(q, poscor);
649
q[poscor - 1].type = VAL;
650
q[poscor].val = (int4) '!';
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)));
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) '!')
669
drop = countdroptree(q, poscor);
670
q[poscor - 1].type = VAL;
671
q[poscor].val = (int4) '!';
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)));
682
{ /* drop only operator */
683
int4 subtreepos = (notisleft) ?
684
poscor - 1 : poscor + q[poscor].left;
685
int4 subtreelen = countdroptree(q, subtreepos);
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;
706
querytree(PG_FUNCTION_ARGS)
708
QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
714
if (query->size == 0)
716
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
717
errmsg("empty query")));
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);
726
res = (text *) palloc(1 + VARHDRSZ);
727
VARATT_SIZEP(res) = 1 + VARHDRSZ;
728
*((char *) VARDATA(res)) = 'T';
732
nrm.curpol = q + len - 1;
734
nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
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);
744
PG_RETURN_POINTER(res);