Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Functions

_int_bool.c File Reference

#include "postgres.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "_int.h"
Include dependency graph for _int_bool.c:

Go to the source code of this file.

Data Structures

struct  NODE
struct  WORKSTATE
struct  CHKVAL
struct  GinChkVal
struct  INFIX

Defines

#define WAITOPERAND   1
#define WAITENDOPERAND   2
#define WAITOPERATOR   3
#define STACKDEPTH   16
#define RESIZEBUF(inf, addsize)

Typedefs

typedef struct NODE NODE

Functions

 PG_FUNCTION_INFO_V1 (bqarr_in)
 PG_FUNCTION_INFO_V1 (bqarr_out)
Datum bqarr_in (PG_FUNCTION_ARGS)
Datum bqarr_out (PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1 (boolop)
Datum boolop (PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1 (rboolop)
Datum rboolop (PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1 (querytree)
Datum querytree (PG_FUNCTION_ARGS)
static int32 gettoken (WORKSTATE *state, int32 *val)
static void pushquery (WORKSTATE *state, int32 type, int32 val)
static int32 makepol (WORKSTATE *state)
static bool checkcondition_arr (void *checkval, ITEM *item)
static bool checkcondition_bit (void *checkval, ITEM *item)
static bool execute (ITEM *curitem, void *checkval, bool calcnot, bool(*chkcond)(void *checkval, ITEM *item))
bool signconsistent (QUERYTYPE *query, BITVEC sign, bool calcnot)
bool execconsistent (QUERYTYPE *query, ArrayType *array, bool calcnot)
static bool checkcondition_gin (void *checkval, ITEM *item)
bool gin_bool_consistent (QUERYTYPE *query, bool *check)
static bool contains_required_value (ITEM *curitem)
bool query_has_required_values (QUERYTYPE *query)
static void findoprnd (ITEM *ptr, int32 *pos)
static void infix (INFIX *in, bool first)

Define Documentation

#define RESIZEBUF (   inf,
  addsize 
)
Value:
while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) { \
    int32 len = inf->cur - inf->buf; \
    inf->buflen *= 2; \
    inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
    inf->cur = inf->buf + len; \
}

Definition at line 556 of file _int_bool.c.

Referenced by infix().

#define STACKDEPTH   16

Definition at line 156 of file _int_bool.c.

Referenced by makepol().

#define WAITENDOPERAND   2

Definition at line 28 of file _int_bool.c.

Referenced by gettoken().

#define WAITOPERAND   1

Definition at line 27 of file _int_bool.c.

Referenced by gettoken().

#define WAITOPERATOR   3

Definition at line 29 of file _int_bool.c.

Referenced by gettoken().


Typedef Documentation

typedef struct NODE NODE

Function Documentation

Datum boolop ( PG_FUNCTION_ARGS   ) 
Datum bqarr_in ( PG_FUNCTION_ARGS   ) 

Definition at line 483 of file _int_bool.c.

References appendStringInfo(), WORKSTATE::buf, buf, COMPUTESIZE, WORKSTATE::count, StringInfoData::data, DEBUG3, elog, ereport, errcode(), errmsg(), ERROR, findoprnd(), GETQUERY, i, initStringInfo(), NODE::left, makepol(), NODE::next, WORKSTATE::num, OPR, palloc(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, SET_VARSIZE, QUERYTYPE::size, WORKSTATE::state, WORKSTATE::str, NODE::type, ITEM::type, val, NODE::val, and ITEM::val.

{
    char       *buf = (char *) PG_GETARG_POINTER(0);
    WORKSTATE   state;
    int32       i;
    QUERYTYPE  *query;
    int32       commonlen;
    ITEM       *ptr;
    NODE       *tmp;
    int32       pos = 0;

#ifdef BS_DEBUG
    StringInfoData pbuf;
#endif

    state.buf = buf;
    state.state = WAITOPERAND;
    state.count = 0;
    state.num = 0;
    state.str = NULL;

    /* make polish notation (postfix, but in reverse order) */
    makepol(&state);
    if (!state.num)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("empty query")));

    commonlen = COMPUTESIZE(state.num);
    query = (QUERYTYPE *) palloc(commonlen);
    SET_VARSIZE(query, commonlen);
    query->size = state.num;
    ptr = GETQUERY(query);

    for (i = state.num - 1; i >= 0; i--)
    {
        ptr[i].type = state.str->type;
        ptr[i].val = state.str->val;
        tmp = state.str->next;
        pfree(state.str);
        state.str = tmp;
    }

    pos = query->size - 1;
    findoprnd(ptr, &pos);
#ifdef BS_DEBUG
    initStringInfo(&pbuf);
    for (i = 0; i < query->size; i++)
    {
        if (ptr[i].type == OPR)
            appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
        else
            appendStringInfo(&pbuf, "%d ", ptr[i].val);
    }
    elog(DEBUG3, "POR: %s", pbuf.data);
    pfree(pbuf.data);
#endif

    PG_RETURN_POINTER(query);
}

Datum bqarr_out ( PG_FUNCTION_ARGS   ) 

Definition at line 638 of file _int_bool.c.

References INFIX::buf, INFIX::buflen, INFIX::cur, INFIX::curpol, ereport, errcode(), errmsg(), ERROR, GETQUERY, infix(), palloc(), PG_FREE_IF_COPY, PG_GETARG_QUERYTYPE_P, PG_RETURN_POINTER, and QUERYTYPE::size.

{
    QUERYTYPE  *query = PG_GETARG_QUERYTYPE_P(0);
    INFIX       nrm;

    if (query->size == 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("empty query")));

    nrm.curpol = GETQUERY(query) + query->size - 1;
    nrm.buflen = 32;
    nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
    *(nrm.cur) = '\0';
    infix(&nrm, true);

    PG_FREE_IF_COPY(query, 0);
    PG_RETURN_POINTER(nrm.buf);
}

static bool checkcondition_arr ( void *  checkval,
ITEM item 
) [static]

Definition at line 244 of file _int_bool.c.

References val, and ITEM::val.

Referenced by boolop(), and execconsistent().

{
    int32      *StopLow = ((CHKVAL *) checkval)->arrb;
    int32      *StopHigh = ((CHKVAL *) checkval)->arre;
    int32      *StopMiddle;

    /* Loop invariant: StopLow <= val < StopHigh */

    while (StopLow < StopHigh)
    {
        StopMiddle = StopLow + (StopHigh - StopLow) / 2;
        if (*StopMiddle == item->val)
            return (true);
        else if (*StopMiddle < item->val)
            StopLow = StopMiddle + 1;
        else
            StopHigh = StopMiddle;
    }
    return false;
}

static bool checkcondition_bit ( void *  checkval,
ITEM item 
) [static]

Definition at line 266 of file _int_bool.c.

References GETBIT, HASHVAL, and ITEM::val.

Referenced by signconsistent().

{
    return GETBIT(checkval, HASHVAL(item->val));
}

static bool checkcondition_gin ( void *  checkval,
ITEM item 
) [static]

Definition at line 337 of file _int_bool.c.

References GinChkVal::first, and GinChkVal::mapped_check.

Referenced by gin_bool_consistent().

{
    GinChkVal  *gcv = (GinChkVal *) checkval;

    return gcv->mapped_check[item - gcv->first];
}

static bool contains_required_value ( ITEM curitem  )  [static]

Definition at line 373 of file _int_bool.c.

References check_stack_depth(), ITEM::left, ITEM::type, ITEM::val, and VAL.

Referenced by query_has_required_values().

{
    /* since this function recurses, it could be driven to stack overflow */
    check_stack_depth();

    if (curitem->type == VAL)
        return true;
    else if (curitem->val == (int32) '!')
    {
        /*
         * Assume anything under a NOT is non-required.  For some cases with
         * nested NOTs, we could prove there's a required value, but it seems
         * unlikely to be worth the trouble.
         */
        return false;
    }
    else if (curitem->val == (int32) '&')
    {
        /* If either side has a required value, we're good */
        if (contains_required_value(curitem + curitem->left))
            return true;
        else
            return contains_required_value(curitem - 1);
    }
    else
    {                           /* |-operator */
        /* Both sides must have required values */
        if (contains_required_value(curitem + curitem->left))
            return contains_required_value(curitem - 1);
        else
            return false;
    }
}

bool execconsistent ( QUERYTYPE query,
ArrayType array,
bool  calcnot 
)

Definition at line 318 of file _int_bool.c.

References CHKVAL::arrb, CHKVAL::arre, ARRNELEMS, ARRPTR, CHECKARRVALID, checkcondition_arr(), execute(), GETQUERY, and QUERYTYPE::size.

Referenced by g_int_consistent().

{
    CHKVAL      chkval;

    CHECKARRVALID(array);
    chkval.arrb = ARRPTR(array);
    chkval.arre = chkval.arrb + ARRNELEMS(array);
    return execute(GETQUERY(query) + query->size - 1,
                   (void *) &chkval, calcnot,
                   checkcondition_arr);
}

static bool execute ( ITEM curitem,
void *  checkval,
bool  calcnot,
bool(*)(void *checkval, ITEM *item)  chkcond 
) [static]

Definition at line 275 of file _int_bool.c.

References check_stack_depth(), ITEM::left, ITEM::type, ITEM::val, and VAL.

Referenced by boolop(), execconsistent(), gin_bool_consistent(), and signconsistent().

{
    /* since this function recurses, it could be driven to stack overflow */
    check_stack_depth();

    if (curitem->type == VAL)
        return (*chkcond) (checkval, curitem);
    else if (curitem->val == (int32) '!')
    {
        return (calcnot) ?
            ((execute(curitem - 1, checkval, calcnot, chkcond)) ? false : true)
            : true;
    }
    else if (curitem->val == (int32) '&')
    {
        if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
            return execute(curitem - 1, checkval, calcnot, chkcond);
        else
            return false;
    }
    else
    {                           /* |-operator */
        if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
            return true;
        else
            return execute(curitem - 1, checkval, calcnot, chkcond);
    }
}

static void findoprnd ( ITEM ptr,
int32 pos 
) [static]

Definition at line 449 of file _int_bool.c.

References DEBUG3, elog, ITEM::left, OPR, NODE::type, VAL, and val.

Referenced by bqarr_in().

{
#ifdef BS_DEBUG
    elog(DEBUG3, (ptr[*pos].type == OPR) ?
         "%d  %c" : "%d  %d", *pos, ptr[*pos].val);
#endif
    if (ptr[*pos].type == VAL)
    {
        ptr[*pos].left = 0;
        (*pos)--;
    }
    else if (ptr[*pos].val == (int32) '!')
    {
        ptr[*pos].left = -1;
        (*pos)--;
        findoprnd(ptr, pos);
    }
    else
    {
        ITEM       *curitem = &ptr[*pos];
        int32       tmp = *pos;

        (*pos)--;
        findoprnd(ptr, pos);
        curitem->left = *pos - tmp;
        findoprnd(ptr, pos);
    }
}

static int32 gettoken ( WORKSTATE state,
int32 val 
) [static]

Definition at line 57 of file _int_bool.c.

References WORKSTATE::buf, WORKSTATE::count, ERR, NULL, WORKSTATE::state, VAL, WAITENDOPERAND, WAITOPERAND, and WAITOPERATOR.

Referenced by makepol().

{
    char        nnn[16];
    int         innn;

    *val = 0;                   /* default result */

    innn = 0;
    while (1)
    {
        if (innn >= sizeof(nnn))
            return ERR;         /* buffer overrun => syntax error */
        switch (state->state)
        {
            case WAITOPERAND:
                innn = 0;
                if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
                    *(state->buf) == '-')
                {
                    state->state = WAITENDOPERAND;
                    nnn[innn++] = *(state->buf);
                }
                else if (*(state->buf) == '!')
                {
                    (state->buf)++;
                    *val = (int32) '!';
                    return OPR;
                }
                else if (*(state->buf) == '(')
                {
                    state->count++;
                    (state->buf)++;
                    return OPEN;
                }
                else if (*(state->buf) != ' ')
                    return ERR;
                break;
            case WAITENDOPERAND:
                if (*(state->buf) >= '0' && *(state->buf) <= '9')
                {
                    nnn[innn++] = *(state->buf);
                }
                else
                {
                    long        lval;

                    nnn[innn] = '\0';
                    errno = 0;
                    lval = strtol(nnn, NULL, 0);
                    *val = (int32) lval;
                    if (errno != 0 || (long) *val != lval)
                        return ERR;
                    state->state = WAITOPERATOR;
                    return (state->count && *(state->buf) == '\0')
                        ? ERR : VAL;
                }
                break;
            case WAITOPERATOR:
                if (*(state->buf) == '&' || *(state->buf) == '|')
                {
                    state->state = WAITOPERAND;
                    *val = (int32) *(state->buf);
                    (state->buf)++;
                    return OPR;
                }
                else if (*(state->buf) == ')')
                {
                    (state->buf)++;
                    state->count--;
                    return (state->count < 0) ? ERR : CLOSE;
                }
                else if (*(state->buf) == '\0')
                    return (state->count) ? ERR : END;
                else if (*(state->buf) != ' ')
                    return ERR;
                break;
            default:
                return ERR;
                break;
        }
        (state->buf)++;
    }
}

bool gin_bool_consistent ( QUERYTYPE query,
bool check 
)

Definition at line 345 of file _int_bool.c.

References checkcondition_gin(), execute(), GinChkVal::first, GETQUERY, i, GinChkVal::mapped_check, palloc(), QUERYTYPE::size, NODE::type, and VAL.

Referenced by ginint4_consistent().

{
    GinChkVal   gcv;
    ITEM       *items = GETQUERY(query);
    int         i,
                j = 0;

    if (query->size <= 0)
        return FALSE;

    /*
     * Set up data for checkcondition_gin.  This must agree with the query
     * extraction code in ginint4_queryextract.
     */
    gcv.first = items;
    gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
    for (i = 0; i < query->size; i++)
    {
        if (items[i].type == VAL)
            gcv.mapped_check[i] = check[j++];
    }

    return execute(GETQUERY(query) + query->size - 1,
                   (void *) &gcv, true,
                   checkcondition_gin);
}

static void infix ( INFIX in,
bool  first 
) [static]

Definition at line 564 of file _int_bool.c.

References INFIX::buf, INFIX::buflen, INFIX::cur, INFIX::curpol, OPR, palloc(), pfree(), RESIZEBUF, ITEM::type, ITEM::val, and VAL.

Referenced by bqarr_out().

{
    if (in->curpol->type == VAL)
    {
        RESIZEBUF(in, 11);
        sprintf(in->cur, "%d", in->curpol->val);
        in->cur = strchr(in->cur, '\0');
        in->curpol--;
    }
    else if (in->curpol->val == (int32) '!')
    {
        bool        isopr = false;

        RESIZEBUF(in, 1);
        *(in->cur) = '!';
        in->cur++;
        *(in->cur) = '\0';
        in->curpol--;
        if (in->curpol->type == OPR)
        {
            isopr = true;
            RESIZEBUF(in, 2);
            sprintf(in->cur, "( ");
            in->cur = strchr(in->cur, '\0');
        }
        infix(in, isopr);
        if (isopr)
        {
            RESIZEBUF(in, 2);
            sprintf(in->cur, " )");
            in->cur = strchr(in->cur, '\0');
        }
    }
    else
    {
        int32       op = in->curpol->val;
        INFIX       nrm;

        in->curpol--;
        if (op == (int32) '|' && !first)
        {
            RESIZEBUF(in, 2);
            sprintf(in->cur, "( ");
            in->cur = strchr(in->cur, '\0');
        }

        nrm.curpol = in->curpol;
        nrm.buflen = 16;
        nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);

        /* get right operand */
        infix(&nrm, false);

        /* get & print left operand */
        in->curpol = nrm.curpol;
        infix(in, false);

        /* print operator & right operand */
        RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
        sprintf(in->cur, " %c %s", op, nrm.buf);
        in->cur = strchr(in->cur, '\0');
        pfree(nrm.buf);

        if (op == (int32) '|' && !first)
        {
            RESIZEBUF(in, 2);
            sprintf(in->cur, " )");
            in->cur = strchr(in->cur, '\0');
        }
    }
}

static int32 makepol ( WORKSTATE state  )  [static]

Definition at line 162 of file _int_bool.c.

References check_stack_depth(), CLOSE, END, ereport, ERR, errcode(), errmsg(), ERROR, gettoken(), OPEN, OPR, pushquery(), STACKDEPTH, NODE::type, VAL, and val.

Referenced by bqarr_in().

{
    int32       val,
                type;
    int32       stack[STACKDEPTH];
    int32       lenstack = 0;

    /* since this function recurses, it could be driven to stack overflow */
    check_stack_depth();

    while ((type = gettoken(state, &val)) != END)
    {
        switch (type)
        {
            case VAL:
                pushquery(state, type, val);
                while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
                                    stack[lenstack - 1] == (int32) '!'))
                {
                    lenstack--;
                    pushquery(state, OPR, stack[lenstack]);
                }
                break;
            case OPR:
                if (lenstack && val == (int32) '|')
                    pushquery(state, OPR, val);
                else
                {
                    if (lenstack == STACKDEPTH)
                        ereport(ERROR,
                                (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
                                 errmsg("statement too complex")));
                    stack[lenstack] = val;
                    lenstack++;
                }
                break;
            case OPEN:
                if (makepol(state) == ERR)
                    return ERR;
                while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
                                    stack[lenstack - 1] == (int32) '!'))
                {
                    lenstack--;
                    pushquery(state, OPR, stack[lenstack]);
                }
                break;
            case CLOSE:
                while (lenstack)
                {
                    lenstack--;
                    pushquery(state, OPR, stack[lenstack]);
                };
                return END;
                break;
            case ERR:
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("syntax error")));
                return ERR;

        }
    }

    while (lenstack)
    {
        lenstack--;
        pushquery(state, OPR, stack[lenstack]);
    };
    return END;
}

PG_FUNCTION_INFO_V1 ( querytree   ) 
PG_FUNCTION_INFO_V1 ( bqarr_out   ) 
PG_FUNCTION_INFO_V1 ( boolop   ) 
PG_FUNCTION_INFO_V1 ( bqarr_in   ) 
PG_FUNCTION_INFO_V1 ( rboolop   ) 
static void pushquery ( WORKSTATE state,
int32  type,
int32  val 
) [static]

Definition at line 145 of file _int_bool.c.

References NODE::next, WORKSTATE::num, palloc(), WORKSTATE::str, NODE::type, and NODE::val.

Referenced by makepol().

{
    NODE       *tmp = (NODE *) palloc(sizeof(NODE));

    tmp->type = type;
    tmp->val = val;
    tmp->next = state->str;
    state->str = tmp;
    state->num++;
}

bool query_has_required_values ( QUERYTYPE query  ) 

Definition at line 408 of file _int_bool.c.

References contains_required_value(), GETQUERY, and QUERYTYPE::size.

Referenced by ginint4_queryextract().

{
    if (query->size <= 0)
        return false;
    return contains_required_value(GETQUERY(query) + query->size - 1);
}

Datum querytree ( PG_FUNCTION_ARGS   ) 

Definition at line 661 of file _int_bool.c.

References elog, ERROR, and PG_RETURN_NULL.

{
    elog(ERROR, "querytree is no longer implemented");
    PG_RETURN_NULL();
}

Datum rboolop ( PG_FUNCTION_ARGS   ) 

Definition at line 419 of file _int_bool.c.

References boolop(), DirectFunctionCall2, and PG_GETARG_DATUM.

{
    /* just reverse the operands */
    return DirectFunctionCall2(boolop,
                               PG_GETARG_DATUM(1),
                               PG_GETARG_DATUM(0));
}

bool signconsistent ( QUERYTYPE query,
BITVEC  sign,
bool  calcnot 
)

Definition at line 309 of file _int_bool.c.

References checkcondition_bit(), execute(), GETQUERY, and QUERYTYPE::size.

Referenced by g_intbig_consistent().

{
    return execute(GETQUERY(query) + query->size - 1,
                   (void *) sign, calcnot,
                   checkcondition_bit);
}